From 19d0f84f028da5afe15aa0285d13b28e54acb8d7 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 18 Dec 2024 15:30:33 +0000 Subject: [PATCH 01/11] Introduce intent URL param and make it change the default lobby behaviour (#2828) * Introduce `intent` URL param and make it change the default lobby behaviour * Mark skipLobby as deprecated * Add support for unknown intent which is default for when not specified --- docs/url-params.md | 57 ++++++++++++++++++++++--------------------- src/UrlParams.test.ts | 50 ++++++++++++++++++++++++++++++++++++- src/UrlParams.ts | 23 ++++++++++++++++- 3 files changed, 100 insertions(+), 30 deletions(-) diff --git a/docs/url-params.md b/docs/url-params.md index 010a4ec8..740e0218 100644 --- a/docs/url-params.md +++ b/docs/url-params.md @@ -32,31 +32,32 @@ There are two formats for Element Call urls. ## Parameters -| Name | Values | Required for widget | Required for SPA | Description | -| ------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `allowIceFallback` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Allows use of fallback STUN servers for ICE if the user's homeserver doesn’t provide any. | -| `analyticsID` | Posthog analytics ID | No | No | Available only with user's consent for sharing telemetry in Element Web. | -| `appPrompt` | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Prompts the user to launch the native mobile app upon entering a room, applicable only on Android and iOS, and must be enabled in config. | -| `baseUrl` | | Yes | Not applicable | The base URL of the homeserver to use for media lookups. | -| `confineToRoom` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Keeps the user confined to the current call/room. | -| `deviceId` | Matrix device ID | Yes | Not applicable | The Matrix device ID for the widget host. | -| `displayName` | | No | No | Display name used for auto-registration. | -| `enableE2EE` (deprecated) | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Legacy flag to enable end-to-end encryption, not used in the `livekit` branch. | -| `fontScale` | A decimal number such as `0.9` | No, defaults to `1.0` | No, defaults to `1.0` | Factor by which to scale the interface's font size. | -| `fonts` | | No | No | Defines the font(s) used by the interface. Multiple font parameters can be specified: `?font=font-one&font=font-two...`. | -| `hideHeader` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Hides the room header when in a call. | -| `hideScreensharing` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Hides the screen-sharing button. | -| `homeserver` | | Not applicable | No | Homeserver for registering a new (guest) user, configures non-default guest user server when creating a spa link. | -| `lang` | [BCP 47](https://www.rfc-editor.org/info/bcp47) code | No | No | The language the app should use. | -| `parentUrl` | | Yes | Not applicable | The url used to send widget action postMessages. This should be the domain of the client or the webview the widget is hosted in. (in case the widget is not in an Iframe but in a dedicated webview we send the postMessages same WebView the widget lives in. Filtering is done in the widget so it ignores the messages it receives from itself) | -| `password` | | No | No | E2EE password when using a shared secret. (For individual sender keys in embedded mode this is not required.) | -| `perParticipantE2EE` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Enables per participant encryption with Keys exchanged over encrypted matrix room messages. | -| `preload` | `true` or `false` | No, defaults to `false` | Not applicable | Pauses app before joining a call until an `io.element.join` widget action is seen, allowing preloading. | -| `returnToLobby` | `true` or `false` | No, defaults to `false` | Not applicable | Displays the lobby in widget mode after leaving a call; shows a blank page if set to `false`. Useful for video rooms. | -| `roomId` | [Matrix Room ID](https://spec.matrix.org/v1.12/appendices/#room-ids) | Yes | No | Anything about what room we're pointed to should be from useRoomIdentifier which parses the path and resolves alias with respect to the default server name, however roomId is an exception as we need the room ID in embedded widget mode, and not the room alias (or even the via params because we are not trying to join it). This is also not validated, where it is in `useRoomIdentifier()`. | -| `showControls` | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Displays controls like mute, screen-share, invite, and hangup buttons during a call. | -| `skipLobby` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Skips the lobby to join a call directly, can be combined with preload in widget. When `true` the audio and video inputs will be muted by default. (This means there currently is no way to start without muted video if one wants to skip the lobby. Also not in widget mode.) | -| `theme` | One of: `light`, `dark`, `light-high-contrast`, `dark-high-contrast` | No, defaults to `dark` | No, defaults to `dark` | UI theme to use. | -| `userId` | [Matrix User Identifier](https://spec.matrix.org/v1.12/appendices/#user-identifiers) | Yes | Not applicable | The Matrix user ID. | -| `viaServers` | Comma separated list of [Matrix Server Names](https://spec.matrix.org/v1.12/appendices/#server-name) | Not applicable | No | Homeserver for joining a room, non-empty value required for rooms not on the user’s default homeserver. | -| `widgetId` | [MSC2774](https://github.com/matrix-org/matrix-spec-proposals/pull/2774) format widget ID | Yes | Not applicable | The id used by the widget. The presence of this parameter implies that element call will not connect to a homeserver directly and instead tries to establish postMessage communication via the `parentUrl`. | +| Name | Values | Required for widget | Required for SPA | Description | +| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `allowIceFallback` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Allows use of fallback STUN servers for ICE if the user's homeserver doesn’t provide any. | +| `analyticsID` | Posthog analytics ID | No | No | Available only with user's consent for sharing telemetry in Element Web. | +| `appPrompt` | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Prompts the user to launch the native mobile app upon entering a room, applicable only on Android and iOS, and must be enabled in config. | +| `baseUrl` | | Yes | Not applicable | The base URL of the homeserver to use for media lookups. | +| `confineToRoom` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Keeps the user confined to the current call/room. | +| `deviceId` | Matrix device ID | Yes | Not applicable | The Matrix device ID for the widget host. | +| `displayName` | | No | No | Display name used for auto-registration. | +| `enableE2EE` (deprecated) | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Legacy flag to enable end-to-end encryption, not used in the `livekit` branch. | +| `fontScale` | A decimal number such as `0.9` | No, defaults to `1.0` | No, defaults to `1.0` | Factor by which to scale the interface's font size. | +| `fonts` | | No | No | Defines the font(s) used by the interface. Multiple font parameters can be specified: `?font=font-one&font=font-two...`. | +| `hideHeader` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Hides the room header when in a call. | +| `hideScreensharing` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Hides the screen-sharing button. | +| `homeserver` | | Not applicable | No | Homeserver for registering a new (guest) user, configures non-default guest user server when creating a spa link. | +| `intent` | `start_call` or `join_existing` | No, defaults to `start_call` | No, defaults to `start_call` | The intent of the user with respect to the call. e.g. if they clicked a Start Call button, this would be `start_call`. If it was a Join Call button, it would be `join_existing`. | +| `lang` | [BCP 47](https://www.rfc-editor.org/info/bcp47) code | No | No | The language the app should use. | +| `parentUrl` | | Yes | Not applicable | The url used to send widget action postMessages. This should be the domain of the client or the webview the widget is hosted in. (in case the widget is not in an Iframe but in a dedicated webview we send the postMessages same WebView the widget lives in. Filtering is done in the widget so it ignores the messages it receives from itself) | +| `password` | | No | No | E2EE password when using a shared secret. (For individual sender keys in embedded mode this is not required.) | +| `perParticipantE2EE` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Enables per participant encryption with Keys exchanged over encrypted matrix room messages. | +| `preload` | `true` or `false` | No, defaults to `false` | Not applicable | Pauses app before joining a call until an `io.element.join` widget action is seen, allowing preloading. | +| `returnToLobby` | `true` or `false` | No, defaults to `false` | Not applicable | Displays the lobby in widget mode after leaving a call; shows a blank page if set to `false`. Useful for video rooms. | +| `roomId` | [Matrix Room ID](https://spec.matrix.org/v1.12/appendices/#room-ids) | Yes | No | Anything about what room we're pointed to should be from useRoomIdentifier which parses the path and resolves alias with respect to the default server name, however roomId is an exception as we need the room ID in embedded widget mode, and not the room alias (or even the via params because we are not trying to join it). This is also not validated, where it is in `useRoomIdentifier()`. | +| `showControls` | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Displays controls like mute, screen-share, invite, and hangup buttons during a call. | +| `skipLobby` (deprecated: use `intent` instead) | `true` or `false` | No. If `intent` is explicitly `start_call` then defaults to `true`. Otherwise defaults to `false` | No, defaults to `false` | Skips the lobby to join a call directly, can be combined with preload in widget. When `true` the audio and video inputs will be muted by default. (This means there currently is no way to start without muted video if one wants to skip the lobby. Also not in widget mode.) | +| `theme` | One of: `light`, `dark`, `light-high-contrast`, `dark-high-contrast` | No, defaults to `dark` | No, defaults to `dark` | UI theme to use. | +| `userId` | [Matrix User Identifier](https://spec.matrix.org/v1.12/appendices/#user-identifiers) | Yes | Not applicable | The Matrix user ID. | +| `viaServers` | Comma separated list of [Matrix Server Names](https://spec.matrix.org/v1.12/appendices/#server-name) | Not applicable | No | Homeserver for joining a room, non-empty value required for rooms not on the user’s default homeserver. | +| `widgetId` | [MSC2774](https://github.com/matrix-org/matrix-spec-proposals/pull/2774) format widget ID | Yes | Not applicable | The id used by the widget. The presence of this parameter implies that element call will not connect to a homeserver directly and instead tries to establish postMessage communication via the `parentUrl`. | diff --git a/src/UrlParams.test.ts b/src/UrlParams.test.ts index 10f1386b..092b51d3 100644 --- a/src/UrlParams.test.ts +++ b/src/UrlParams.test.ts @@ -7,7 +7,11 @@ Please see LICENSE in the repository root for full details. import { describe, expect, it } from "vitest"; -import { getRoomIdentifierFromUrl, getUrlParams } from "../src/UrlParams"; +import { + getRoomIdentifierFromUrl, + getUrlParams, + UserIntent, +} from "../src/UrlParams"; const ROOM_NAME = "roomNameHere"; const ROOM_ID = "!d45f138fsd"; @@ -195,4 +199,48 @@ describe("UrlParams", () => { expect(getUrlParams("?homeserver=asd").homeserver).toBe("asd"); }); }); + + describe("intent", () => { + it("defaults to unknown", () => { + expect(getUrlParams().intent).toBe(UserIntent.Unknown); + }); + + it("ignores intent if it is not a valid value", () => { + expect(getUrlParams("?intent=foo").intent).toBe(UserIntent.Unknown); + }); + + it("accepts start_call", () => { + expect(getUrlParams("?intent=start_call").intent).toBe( + UserIntent.StartNewCall, + ); + }); + + it("accepts join_existing", () => { + expect(getUrlParams("?intent=join_existing").intent).toBe( + UserIntent.JoinExistingCall, + ); + }); + }); + + describe("skipLobby", () => { + it("defaults to false", () => { + expect(getUrlParams().skipLobby).toBe(false); + }); + + it("defaults to false if intent is start_call in SPA mode", () => { + expect(getUrlParams("?intent=start_call").skipLobby).toBe(false); + }); + + it("defaults to true if intent is start_call in widget mode", () => { + expect( + getUrlParams( + "?intent=start_call&widgetId=12345&parentUrl=https%3A%2F%2Flocalhost%2Ffoo", + ).skipLobby, + ).toBe(true); + }); + + it("default to false if intent is join_existing", () => { + expect(getUrlParams("?intent=join_existing").skipLobby).toBe(false); + }); + }); }); diff --git a/src/UrlParams.ts b/src/UrlParams.ts index e0aae237..423235ae 100644 --- a/src/UrlParams.ts +++ b/src/UrlParams.ts @@ -19,6 +19,12 @@ interface RoomIdentifier { viaServers: string[]; } +export enum UserIntent { + StartNewCall = "start_call", + JoinExistingCall = "join_existing", + Unknown = "unknown", +} + // If you need to add a new flag to this interface, prefer a name that describes // a specific behavior (such as 'confineToRoom'), rather than one that describes // the situations that call for this behavior ('isEmbedded'). This makes it @@ -142,6 +148,13 @@ export interface UrlParams { * creating a spa link. */ homeserver: string | null; + + /** + * The user's intent with respect to the call. + * e.g. if they clicked a Start Call button, this would be `start_call`. + * If it was a Join Call button, it would be `join_existing`. + */ + intent: string | null; } // This is here as a stopgap, but what would be far nicer is a function that @@ -211,6 +224,10 @@ export const getUrlParams = ( const fontScale = parseFloat(parser.getParam("fontScale") ?? ""); + let intent = parser.getParam("intent"); + if (!intent || !Object.values(UserIntent).includes(intent as UserIntent)) { + intent = UserIntent.Unknown; + } const widgetId = parser.getParam("widgetId"); const parentUrl = parser.getParam("parentUrl"); const isWidget = !!widgetId && !!parentUrl; @@ -243,11 +260,15 @@ export const getUrlParams = ( analyticsID: parser.getParam("analyticsID"), allowIceFallback: parser.getFlagParam("allowIceFallback"), perParticipantE2EE: parser.getFlagParam("perParticipantE2EE"), - skipLobby: parser.getFlagParam("skipLobby"), + skipLobby: parser.getFlagParam( + "skipLobby", + isWidget && intent === UserIntent.StartNewCall, + ), returnToLobby: isWidget ? parser.getFlagParam("returnToLobby") : true, theme: parser.getParam("theme"), viaServers: !isWidget ? parser.getParam("viaServers") : null, homeserver: !isWidget ? parser.getParam("homeserver") : null, + intent, }; }; From ba5da7e9af13a71d45cf9ee33a08523194e23656 Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 18 Dec 2024 15:31:45 +0000 Subject: [PATCH 02/11] Inform user that their camera is starting in Lobby (#2869) * Inform user that their camera is starting Instead of just showing a grey box. * Review feedback * Show spinner from design suggestion * useMemo * Lint * Lint * Feedback from review * Use colour that actually exists * Refactor into Avatar superclass * . * Remove size limit behaviour * Add VideoPreview tests --- locales/en/app.json | 1 + src/Avatar.tsx | 2 +- src/room/VideoPreview.module.css | 11 +++++ src/room/VideoPreview.test.tsx | 73 ++++++++++++++++++++++++++++++++ src/room/VideoPreview.tsx | 37 +++++++++++----- src/tile/TileAvatar.module.css | 20 +++++++++ src/tile/TileAvatar.test.tsx | 27 ++++++++++++ src/tile/TileAvatar.tsx | 30 +++++++++++++ 8 files changed, 189 insertions(+), 12 deletions(-) create mode 100644 src/room/VideoPreview.test.tsx create mode 100644 src/tile/TileAvatar.module.css create mode 100644 src/tile/TileAvatar.test.tsx create mode 100644 src/tile/TileAvatar.tsx diff --git a/locales/en/app.json b/locales/en/app.json index a47e5beb..0e71fd4e 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -195,6 +195,7 @@ "version": "{{productName}} version: {{version}}", "video_tile": { "always_show": "Always show", + "camera_starting": "Video loading...", "change_fit_contain": "Fit to frame", "collapse": "Collapse", "expand": "Expand", diff --git a/src/Avatar.tsx b/src/Avatar.tsx index dcdead7a..a76afbca 100644 --- a/src/Avatar.tsx +++ b/src/Avatar.tsx @@ -33,7 +33,7 @@ export const sizes = new Map([ [Size.XL, 90], ]); -interface Props { +export interface Props { id: string; name: string; className?: string; diff --git a/src/room/VideoPreview.module.css b/src/room/VideoPreview.module.css index 89422af7..eeb9276b 100644 --- a/src/room/VideoPreview.module.css +++ b/src/room/VideoPreview.module.css @@ -25,6 +25,17 @@ video.mirror { transform: scaleX(-1); } +.preview .cameraStarting { + position: absolute; + top: var(--cpd-space-10x); + left: 0; + right: 0; + bottom: 0; + display: flex; + justify-content: center; + color: var(--cpd-color-text-secondary); +} + .avatarContainer { position: absolute; top: 0; diff --git a/src/room/VideoPreview.test.tsx b/src/room/VideoPreview.test.tsx new file mode 100644 index 00000000..068ad050 --- /dev/null +++ b/src/room/VideoPreview.test.tsx @@ -0,0 +1,73 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { expect, describe, it, vi, beforeAll } from "vitest"; +import { render } from "@testing-library/react"; + +import { type MatrixInfo, VideoPreview } from "./VideoPreview"; +import { type MuteStates } from "./MuteStates"; +import { E2eeType } from "../e2ee/e2eeType"; + +function mockMuteStates({ audio = true, video = true } = {}): MuteStates { + return { + audio: { enabled: audio, setEnabled: vi.fn() }, + video: { enabled: video, setEnabled: vi.fn() }, + }; +} + +describe("VideoPreview", () => { + const matrixInfo: MatrixInfo = { + userId: "@a:example.org", + displayName: "Alice", + avatarUrl: "", + roomId: "", + roomName: "", + e2eeSystem: { kind: E2eeType.NONE }, + roomAlias: null, + roomAvatar: null, + }; + + beforeAll(() => { + window.ResizeObserver = class ResizeObserver { + public observe(): void { + // do nothing + } + public unobserve(): void { + // do nothing + } + public disconnect(): void { + // do nothing + } + }; + }); + + it("shows avatar with video disabled", () => { + const { queryByRole } = render( + } + />, + ); + expect(queryByRole("img", { name: "@a:example.org" })).toBeVisible(); + }); + + it("shows loading status with video enabled but no track", () => { + const { queryByRole } = render( + } + />, + ); + expect(queryByRole("status")).toHaveTextContent( + "video_tile.camera_starting", + ); + }); +}); diff --git a/src/room/VideoPreview.tsx b/src/room/VideoPreview.tsx index f9609b99..e2d8303f 100644 --- a/src/room/VideoPreview.tsx +++ b/src/room/VideoPreview.tsx @@ -5,12 +5,13 @@ SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ -import { useEffect, useRef, type FC, type ReactNode } from "react"; +import { useEffect, useMemo, useRef, type FC, type ReactNode } from "react"; import useMeasure from "react-use-measure"; import { facingModeFromLocalTrack, type LocalVideoTrack } from "livekit-client"; import classNames from "classnames"; +import { useTranslation } from "react-i18next"; -import { Avatar } from "../Avatar"; +import { TileAvatar } from "../tile/TileAvatar"; import styles from "./VideoPreview.module.css"; import { type MuteStates } from "./MuteStates"; import { type EncryptionSystem } from "../e2ee/sharedKeyManagement"; @@ -39,6 +40,7 @@ export const VideoPreview: FC = ({ videoTrack, children, }) => { + const { t } = useTranslation(); const [previewRef, previewBounds] = useMeasure(); const videoEl = useRef(null); @@ -53,6 +55,11 @@ export const VideoPreview: FC = ({ }; }, [videoTrack]); + const cameraIsStarting = useMemo( + () => muteStates.video.enabled && !videoTrack, + [muteStates.video.enabled, videoTrack], + ); + return (
diff --git a/src/tile/TileAvatar.module.css b/src/tile/TileAvatar.module.css new file mode 100644 index 00000000..fa05c552 --- /dev/null +++ b/src/tile/TileAvatar.module.css @@ -0,0 +1,20 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +.loading { + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; + opacity: 0.5; + /* TODO: make this --cpd-color-fg-primary when available. */ + color: var(--cpd-color-text-primary); +} diff --git a/src/tile/TileAvatar.test.tsx b/src/tile/TileAvatar.test.tsx new file mode 100644 index 00000000..ae5ab610 --- /dev/null +++ b/src/tile/TileAvatar.test.tsx @@ -0,0 +1,27 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { expect, describe, it } from "vitest"; +import { render } from "@testing-library/react"; + +import { TileAvatar } from "./TileAvatar"; + +describe("TileAvatar", () => { + it("should show loading spinner when loading", () => { + const { container } = render( + , + ); + expect(container.querySelector(".loading")).toBeInTheDocument(); + }); + + it("should not show loading spinner when not loading", () => { + const { container } = render( + , + ); + expect(container.querySelector(".loading")).not.toBeInTheDocument(); + }); +}); diff --git a/src/tile/TileAvatar.tsx b/src/tile/TileAvatar.tsx new file mode 100644 index 00000000..bba826cd --- /dev/null +++ b/src/tile/TileAvatar.tsx @@ -0,0 +1,30 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { type FC } from "react"; +import { InlineSpinner } from "@vector-im/compound-web"; + +import styles from "./TileAvatar.module.css"; +import { Avatar, type Props as AvatarProps } from "../Avatar"; + +interface Props extends AvatarProps { + size: number; + loading?: boolean; +} + +export const TileAvatar: FC = ({ size, loading, ...props }) => { + return ( +
+ {loading && ( +
+ +
+ )} + +
+ ); +}; From 6d5dc0dfb77823fdf8d13c1536d027a4d15f636a Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Wed, 18 Dec 2024 17:03:29 +0000 Subject: [PATCH 03/11] Fix loading of matrix-sdk-crypto-wasm when running in local development mode (#2915) Fixes problem loading rust crypto when using `yarn dev` --- vite.config.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/vite.config.js b/vite.config.js index 1feb7d66..7f088801 100644 --- a/vite.config.js +++ b/vite.config.js @@ -109,5 +109,12 @@ export default defineConfig(({ mode }) => { "@radix-ui/react-dismissable-layer", ], }, + // Vite is using esbuild in development mode, which doesn't work with the wasm loader + // in matrix-sdk-crypto-wasm, so we need to exclude it here. This doesn't affect the + // production build (which uses rollup) which still works as expected. + // https://vite.dev/guide/why.html#why-not-bundle-with-esbuild + optimizeDeps: { + exclude: ["@matrix-org/matrix-sdk-crypto-wasm"], + }, }; }); From 7d00f85abc85706f1dc93118bc5c722c0e65788f Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Thu, 19 Dec 2024 12:37:10 +0000 Subject: [PATCH 04/11] Add screen share sound effect. (#2917) --- src/room/CallEventAudioRenderer.tsx | 15 +++++++++++++-- src/sound/screen_share_started.mp3 | Bin 0 -> 17323 bytes src/sound/screen_share_started.ogg | Bin 0 -> 16737 bytes src/state/CallViewModel.ts | 15 +++++++++++++++ 4 files changed, 28 insertions(+), 2 deletions(-) create mode 100644 src/sound/screen_share_started.mp3 create mode 100644 src/sound/screen_share_started.ogg diff --git a/src/room/CallEventAudioRenderer.tsx b/src/room/CallEventAudioRenderer.tsx index a2a0a7f1..97270791 100644 --- a/src/room/CallEventAudioRenderer.tsx +++ b/src/room/CallEventAudioRenderer.tsx @@ -13,8 +13,10 @@ import joinCallSoundMp3 from "../sound/join_call.mp3"; import joinCallSoundOgg from "../sound/join_call.ogg"; import leftCallSoundMp3 from "../sound/left_call.mp3"; import leftCallSoundOgg from "../sound/left_call.ogg"; -import handSoundOgg from "../sound/raise_hand.ogg?url"; -import handSoundMp3 from "../sound/raise_hand.mp3?url"; +import handSoundOgg from "../sound/raise_hand.ogg"; +import handSoundMp3 from "../sound/raise_hand.mp3"; +import screenShareStartedOgg from "../sound/screen_share_started.ogg"; +import screenShareStartedMp3 from "../sound/screen_share_started.mp3"; import { useAudioContext } from "../useAudioContext"; import { prefetchSounds } from "../soundUtils"; import { useReactions } from "../useReactions"; @@ -38,6 +40,10 @@ export const callEventAudioSounds = prefetchSounds({ mp3: handSoundMp3, ogg: handSoundOgg, }, + screenshareStarted: { + mp3: screenShareStartedMp3, + ogg: screenShareStartedOgg, + }, }); export function CallEventAudioRenderer({ @@ -89,9 +95,14 @@ export function CallEventAudioRenderer({ void audioEngineRef.current?.playSound("left"); }); + const screenshareSub = vm.newScreenShare$.subscribe(() => { + void audioEngineRef.current?.playSound("screenshareStarted"); + }); + return (): void => { joinSub.unsubscribe(); leftSub.unsubscribe(); + screenshareSub.unsubscribe(); }; }, [audioEngineRef, vm]); diff --git a/src/sound/screen_share_started.mp3 b/src/sound/screen_share_started.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..5a4113f98340b222880bae8f8a96f0314bce41f1 GIT binary patch literal 17323 zcmdSfWmFXJA29r(mtMMI>7|!$Sh|+(Ub-6;5OJ68?(RmB6a;Am1f&rJ1*Ak#QUUqF zqyOjJZ}0c_oO7MYb7szGzVp3mv{Xg00XP5vtbYp;1_TH23^OD(v9PfCyHEJH{BKiO z7$yjN_><%O_rU*k(eicm`+EWD-@*?7DkuO4hmeqrjE07WiHVI33KbL-6cdw?fy33* z)O2(V4b9EXZEYPL-Q9hCeS?F;!%?W%*x2Oc%*_1!{L<2@s)mN=&!2a8_Vo=7jgODN zd$+K#wzjslwYz(C^y9~m%gfu_hljuSl13=$s)-5;!(bRq|L6HAQ5;z5X#jxw_Z&D8 z0RI0u@&D@jufHk)V1h}8OJPHRJp9_T4jUkf$d~KwL}6qT*JDYY0st5Q<3|VZ-(T>I z!2lqNEpF{aq@R`Wk8NCp|9nL6?K0`$pKvz+2t~Z%t7vr8_DxVB9KnKjzJ2}d;*J9E z;RgWFf-wL?0c%_WibUs26hb3qdl)ImtkSc}GK@!q&14}3V!V5$DEJf}M}jMR`s}}g z(tFy6?P~=VY#I1B{SL^u*35Ft?9p6}|GC-w2m@GYebJO~61pT&$-?@pG`kN@jM10@ z6mJ3TRHYKBbVln;9PMAO&S9{D+y3mmEJ>kg?lQxVXLlOn9~?!ZWmbx!(dc3L)05Lk zZ;$b3R|EyY)KEqkG-j)TJv4_zFG&~)8%17lVa+(=i@^A$4!~IG;W5WGAVD1qP_4Kz z$q>T7HM=l#3TRk ziU`0&VUFZSAD>wcVGsEwFSA*2B>eLy0F88$&#$=;0cJ6MSSPdqf$C3***0Azvs^Bm z32KAkIM{v;)0U3KUDr*I> zaHyau3kZlx>ppSSYW%*t(n9&=ar8I*E6$9^Z|QK5M5u%uDF(zN1Lq{6Y_25%gzV4YNH-lkJ#AeKW9vw0KBa&UJh z#VWHM6dH>l^*$7Rs!^#a_uBmf=P}RFKlbqAc%<=Wc>pDV)5MUtOM%zqne?SeUwQxS zCpwzwg+1!v+lrL0em~jqHBzvxc;tBi!fmP;1pSB4OH~}8q%ReRA^-e|(-xmX5z&QO z1~x8J@W*Zn+B1!Uf*hS_6Y5&E&62bEjJ-2jO|d6&z7Rl1?Ukz*3#>fQbvfoRC|P};JF-Pt zmv|Z>2lgd>)8>({x6Ws+PC{e4voTkStBKQkWMh}y)b>_Pnd4&!zT-Loo>=N}0%N(3bp#s?l^%-?%=;Oq zN-&_14WJzAjCqHY@E&n~HWijtD3^MjU`kl4nN!$T-u|&sHccO=#Bmm12cqmqQbo9+ z*>4K#wlh30^vuigKK82C78hxyI(Ioh?rfZQG4RF%a88JqCJdF0=f*Jaw4**hj@yn; z!L0Qx9$@^J|4Gx^--=I1zqUBFab33v*teTbS%Z=s9Zsod*E-CU@}6WxDW7z=htKWt zf?2JgrK&iGY#rFXTIM+Si0|)br6fN*cH9(dc=PS5$x{2pHxGeXPkYm=HxH}xz~5Sk zkvD7xyv`t=4<7lYVu(p57oy;h!OoAHkG(LUs(}ElBQA#pkQ@gw3Xq{^M{%>p3WyiR z^@B?4-_mhjUziZG?LNjbq2~}VP*+ip`_d%Ssw;M4k`uA{c1er?j8qSe1_c1cb#9me z3zUZEB#G>8!~K4hRGW`{lG!pnM#>hidp>r2S`yj^vjdE3xin7VbQN_~jiVyzN3JfQ zJr~{QUfR^3jMdWQ&we`;&~orSM^^JJz#F$6ew`A2u!T7yG*Q0__({=%Ua8h1aF=3r zbz9B|hlilXE_=LSY&;YEPU>y?2#pHqHHmx3hjqkuZ$Ell43ZqA87r`GUR1GWCrT)b~XXIL-mld`2&fiV#hLi1Hb%U$7pxa2JbCmo*M(i- zU~;r~w*s3eo2Ubu5THYU4J$!eeTKocacJ8r!B(-Cnlx^jN0z6io0LY{?hPh^WIt>4 zOYJxGzcQdVA~fd0V(Y_(xA2x3aAT>KBaqi~XWZo27w;<*|KK^|LoH(xsy97HpNwJCz>MYt4s&r_9`B?aDChbdn^ z{gSGYBVbnAtfQ9$5Mc&ft76bngwjetNHDnY23@bMXaL4O;ffGJ`{W*VpfEFQ##oXqd_4omx`k$B?346UqJ@5?U|D z(%pY-J6WYnt=uI3pqX*<5>UHfalF;J2v0ts8oA7%xDgsADX_OFQzv1=_sB^!;E=yat1#R;pBPr)~}%@9h)|1HN^?u`tHD8Ol9d~MF+#lrdDI0;%# z*?%p*4lneWV6X7-Sz2b($Ca<@o+if)XT41dBTc}t(%i5sn2C1Bd|Q_Dr(LO|aC{83npJUY#V4(*0DebOG#kar=ZI=WP%H@Ym1`X3F#q$u%lGIL1FLv`0tr~s(-sW)0tKKVz zu@AXNk6R!AijhD!&8aaNJw2#2#4f+QC2NH zTqY2vjVnpo8#7g9O8Bd1qP((5V zDSp5Bbh0U}Tbe{1**fwt-DsDe#Qq#qnOg;#yAd-tjtfa*ZMwSAw4Ez@|I4z)Ni4%t zDoy89ZV!mdPUOf`2aJ1HjO2J#7b!DUb{owoBaG{uGEG;-$Upc8xqU#Q)|Bm5tWnsgZ^Pcmk%B%THi5SX!+@h|V5 z*uHN%{F&0NO^#jkBa=2y8~rVN3;B4csh`DD}e z%i?Jf16c*xu2shHLT65=cdx5)A8T29S=ygwRuP3GB^S<$k!ykK)nfn`p)D_p*0jk5 zW;)B0%nSlP8RdL`Ga;+bCc2S6XyxEPCbwgGrUSGjVE1*a*K@hGTMF5Vn>VxnFaDWO zBUTE_PC`82b=0Lte4>K!Q_AgII1J8U*#}eol%dnD-+nY(bs3w*W8KC>xyRM=h9YH< zXq$`J`Xm$zwS1hDx&$v1-D={(i~ zZ39nw8~PGzw}$x1?x0wIR6zsdQn}sr)6bwky8>bAWDu*4Lc?~n>@O{vsGUX(rLJso_j_G;A2>T@K?f2p<$K> zV+FijG0Ik+*o=6sPw@W5zZih&F16^TLouoCI!))n>5}*=Sz4gKWmx#{#}t!WhE(Z) z^;=t{rRj?$)`vK@&|as_Fk#zc+#HkXF~ke=)%fb4uH|&5l#Z?YbmUf9NLnx^A%@(g zYVaNce-<1^M@j3yB%g)G-H3VBfO{%4G#T%3?x?#!n^nICXI~bt5(=)+-KU&j@QFXk z3Cs2TP&rhcuobCyHDKUZHkql-)4deX1#nAjG*#)xghyIWH2N~<%I6-j42K3}+i59z z!MeIw5)ar#q@lf?&ED2Ba_`-ybg9zz1;r0MIq9wB%@NY5)N7J^SQmghmPgr!nYUb3 z2M@FI2pmc_a%^9tB|6qFBou#Ph<@eDMah+URisu&v`Q8g;bRwTj`LaX>zh^CmBJBO zo{gxYJ3~JA{NlvEyT3i~9Zww&B;`PGlZ60Ht2aw_2#QAz7+L;ToqYuP4c=lbcZO(bW;X)t1>5cC|p7)T#fcvK4hM<0)u|Pqi4T zsXv54ulxY_D}C)*3(%iFQ4<})rk67^Nr0mJ4zto({8;|`ncG>RjCt#HOzJ?VBq>`qbCiFW7W+$qR*{nbBCoXZL4$vuB|a4F zMo|Hn*jd{8m<1nc={@2KV=>|;urnDuoiSSwkHKtMYI^;RkpHZ=ii++w@*UY#3@(U0 z2#IlICP!s;~-m>SJ_6h^-=aYN= z$TEq=t~Uj#U_{tEhQuBW+k5TT#kqw&@BBpWOJ~~@#mG&KX`hlVOgZDK&@J0MM0f>k z(RcCq`!L$AMY5hO&!&F2e^Y%FlOWCPiyDN0>Ff&ew!{Ko z-=O>O!f{3C{YY!+aT_h;?LvKq_V)p@! zL&!PxjkH=LfJJN8kH6%D$tCqQHr&SSjX@rWO={z?JLPj35-FG{IKA*0iy7(E48eLM zWD-{K?%ncQ!*iw=vdF1>&(2M{*FAPdVWIrSA%BNwnr^pRhwxX&o1#g<>h0^~TkV|; zEm{?)scuuKv zV71VPQcC=gZcLuUs+SE3Ex+ZnZ+|u3rX(gv)){Yvdg&vW{N%Oo2-2p(zBj=MJrPVk zS&hFIO1lTP+_Wqo)dDQdo)WHYj#63fdIkkWye&yiqbfto@JjWIO~Sk;14|E6TE4Wp z*k0pq$?2daC5+WP+jnoeXAbK1Z|>b#eEo{22eUcIH+`p^d;!A~C7$E*H8wpTa$Ij- zZPEIJ=f;^?p?B!MQgMVR(TKXPE-9NKKk>gC!%V&YE^=@Dgm?6{T#Gp)D-MR1GUa? z^&-^CjLEPw55x4cOErkrH4X~%fN+h9$=rrM-rOS4&hc3|Pny%dl}iAySxo_>SWPI2 zqljw)zcX7LZUzGTD|uYO^}uT=nbR+?>Im}RTHF%r^^%Y9AHTfR(9ue;zto?ger1LR z+up=JkC`{i{Hh!*I%&qv4Sz$@o~4S?$z12~8N%;@*6O>UtO&`I?zl2PXn@kfH_XbF z`|*<5dT?+Vx4bwerwg@>o;I*ZdkcK3avC-G5#yOWY4MX+EPbv1_OAc)ycAaQ-_L5E zndYDW6I9ewNrNw56c)x4iM`$JWT z8=vOr1IMRUNQgp^2Jb!H;q%@Dr-HX^f9V>Rc5F|}4jb}^;x8)brZnHIklxA#+a zY?X(o>IsX8f$4bilF7<)j!ZAS;oQD)`-u{5PV;g55X?9?sAt(RnqYJr6Z4woD1%lw zv!HlAwV)v4Y?y(RlU2&%a%v(ahE^+6auKs%WM)|=(vWTHx7YJ%%nECgIvy>K=c*K3 zdA`0Yv+Fg;j+0atmYl~Ss^wRW&5`1lH)M{-<5ho_KRoEwkC1U?iv}glazPqB8u;8@Nx4F1~(MQ&)V> zFZxxao0~Isi*J-VpL+uxIN1UHL$yMrFD^9Q?n?l5B{Lb)bH3*6DeJjg>RX}I$=FXy z_x7Tp8qryzhmwu?5QnT^8vX!CupwKE3PbGsJoF-KIxgXGT4#RIRrO`xC%sG#ZH9{r z1xoio?Uo=;+?OQNob&GDY~Zb+&;@%RU$IZToQv#sistEia#a8W zX69u$j&SFa0={U(*{?D6GJOkZlVBpRqVQ)<02eohJf@nnNl?y3!yQ*@XC_MdkcT7) zx4l>UYK@YwRqSx z{6ALQ7(bzm!G*rRZSwE}`y>m|oC+PzS@z9hv)bd}=4y|#iSy!vcjgIAc2I59{7}uM z3B|`!zjeH6~n^{0+=LgvDB@N&fW`;`M~>HW_Q`Ihan zCaImS-~a44nY>QakO$!wgrw;jSsorDWMxmT{ygk!_V8NMj5h&M033>?@}BR~AxkSo z{Xi_d;);({cO%xI%EqJ>e1grBt<|)Dk_A4G()8$#9zJ7SHGpbZlE~WJ;`_SB%OD$oM{#?Mr84J6edD+n7$~w{R%&@zMZHt{0kK`P+m^vM?vhg}tm)2dHuCbx7&cT61FPlj3_A8Bq zy|hnb8XKtn$oS^I)Ry7L085FJKJJ=vW!5*KkHGgEIUe15Xhy<|^@`MNcCNyt3^Wc7 zl7`Jl@xNk0Pqv?iZd7BRUYaR8Xe5PoOIkX>e_`!PWb)p5Xm-@-81h7aJDt)Rgt}GU zjz`j_eyl+Kq?fs*z30$V61n7z{pW9q8i|q9m-XY>_T%O0@YzqokH}Qfm8(}8{F}|+ zHd%B;SbxC_sCc-=P<*fe$bqbq3gU@IJ%?!8oC$EjW3GBu1up`OJxj`8an9uHUt6fC z=c)ccCLUE7JZtEoqf6MGE3tS?f1RqdW3Y*6oD!h{3dzhIgGDmnAO`Dsa01aQ1a5wc zl8VI945ghpHb*p8^bAQ6o-mG*8m4pv9L}tnKPMfT;SB8+>e>@SY_JHr4kg=B3T2ip zy*@C0py|ikw%Nkzk%Tb%?v}IpL7`>~cM;ZQLK0=0sl5|-Z_L$uv?9zOF2w&%Qnr$7 z2?Bbn3emfii=D}?eow~>9E@{|26o_7_^e{0tbS2fwp3L!{dCf*!LdtpYsRA6Q?J$h zbpPCx8%E9}{`)wRPaIJox&Q#!HEozu6#1WdQM3&_(MbhS9{qmo`7AneCY0-<1LdxoE z@3D_d9{$XKYKRsC4na@%_ z&c)rE_C|I}eiWsV0z>u{)e}aIgH(nx*?q14%4bRPgrQ^Q(-F~!bl=Vudp@t++j9W4 z7@eN8DU@{%8EEqnAGYXF5UX%S!uV3G>gN`|l&A)(`_EHNYCp$HrUK`-Rl0w z;ZF*ZKOuF>Z+_jGZ$9SO3>b0vylXUQPFl`RDohfs2s{pL@MHF6PWbgP0&88@drBKHc~Q7u)!dcA^pv>P z87_eizI2%+-!e$ePgZ;_kB3m(g-g(-i{0PDMvGcob`E#;B7`F*VouKa+)KH3F z*a*hDVuRg}u7_vpGdG0aPhiu+O?23L>i)Lhs8dMT8MQdNL8O@dxCIofFfy!i#kSPp zn3#%CnZbi}kqCv8_^@s`15{51Ny{9_>beeG-Ru^7>KuPE_{sa9#bC2ll*$d|ob<(; zXD=4sSkDjU`mrJb3~@RS9sq}Lf1>4|zZEdzD602OpB!neO}FT$Er_48uF}%xy<^FK zh|^OVh;WE+%V=w~4D-llHAGmp;*WGGp3AhhoX5vEi5Zb7rs^#F9XHyKR6b=4{1rIc zX9i{^iaf9{72MFK7$Z57K$ETQEV?W)f`u7TM`mn01&yF1VbeB>^pe0+Nz{GgjM=ub z?CRw_EK+W>M0?cd!{?BTVae$V{mzEI_1M0&t0absFV_|C2Xk+_4sY-8TYp^&WKJ~! zsza}f|Kq?Apw-PJcId|4w2F_=tC&k<#g@2DukOQixw$|jejiYSSBtwCUBnA+CwyKu zzC?a;AvJ!HyLC&T-RUi;9x{!1mCm>UXB#Ls07)ebnWo?Za#RK|Wh0kg4i2L_nQpR% z=MAqhk~cdhNV$F<=UNu5wxSt`*fV<{s$_Y8HR-k9y}bpU_mD>i6Q2tA74NXjo|erX z`}KVM;w&OvA(q*OGuHP3I~q|_GD?wZLCi&OfKRPis)o#}d++Jf_0QiiVb_rZ(Hv$u zZ=rcJ?BiI6kDQehC^1qpWN{ttX)LgBdv54BVW&O?Fq`hGpxH;Go|0UIRCqlT!sBC0j=G*rP@$|jyJTI?uy^*%`sPK)k z6|sja>KhMEI6r^PT`DVsjRDjH>{qTbs?aey;nU$mYm3T!U~FX4kZA|~I!aF=d$R#T z(^4bN;{Mawo>~9Po6I+oQThb`Ve~X#g6=nJG(Oq!k(9UHV#iStWB%s8=0e!W%t#IPPj0T3e-uJ$8daqv>FzeZP#uE^Lz9)_sQUJH>QDc9Y z#iYWQ=KAOFn-HbXtGlF6F{E=y_uHc?j);c}DkyilpvB6K-&JOCn9N)q6=*8SX4ok$ zHUD1z`^AIenEJy5RX)TCGhfM~;{ z3vNX2m$b6QsXk7mykb0r3@)_haQqkEP@dP!c&*B>_xSU-UpIbIOdO@K27)8$Lt zxZKoysfCnb?;16M&G~VIJR&-Voj7U7qZy@&xuWMe3u_0@XSKXHi%(p~Q?~A(C?=iD z$Z-`@CaYfmz^ebjk$1o{D;6ynvp@LxON-TGfwBiS3+K+Qyfp%#WHT}UST(DOe#6}E zXTs2%aMj3cLow^koZiLjaDf+RIMphpffq$^YNwldr59nCn7U3Pl{lY=Ngwzk+LGpe z3g?)geNsj@j9N=>PlR|$XF%DJl*y)AyACQ$mBM?5{4qQJBzhhRp$K=j^4uxR?y}9U zdhOvObmm&FkW?>TW3*hw10NYQL`}4p?VtbS1kCrM+RdRd{+66g0}kJG6Orq%+3iCm zg~GbTp4j32{LJZe@HY5O851`CBr6^v>Lw!U&Z-1mM0aQ2d7$}NOS0$x{3DY_90lI- z{jGns#v9Roc$)aIDZ$pi{sIhKI9*A!w#yA>RJOstUP^?6qAvE-B|k;EbF ztkxP04eWN&Hy>n~p!xNj>{JZ^aM%D`3@Le$Mm&mQa#yR+5NiJY0*nAvWqpvqLH>H= zYU>G3xe=s-Hvp3is*3=Z`%d$J5K6 z>D>0J5;N-gcL*Q`4@fO4Xv21fb8*Vx#ADS4jOf<{Fk60X)A79dv8t!aHy9K9 z)naIw5-BP-yR6boH15eb_-K!%di;Fi=lkXOv4V*+ZtiZB31Tu~7KjFLbQzJ-+8JHm@E=o$ z();}2Dr^F!fByNHi)NyTFX7NrEj+qRAD6g9_jMtG?b>0%LYLv5M1Q{>B*^(CMsAL} zkP%Adc(ZLpGiQp^L)0XMT(%o1$q=_gvQr+0DX9QfTR3-HhggPR)Sto!HRXe4qPmX| zJyL^nA!0j=6J}FbkVsx=v8#lEsGO`Et}ETF@@}+Jt)R{ zP6NpDFYfyI@;Zw-*`zylhkGHn%8xui5Aq-3J35m|;aUsyo1=;&vO1uc(VDj5B3X-?#(+*SRjMco>&j?iG74$k_i>q=T_n@ z;@tV$|HWydmK4-z(|*rrGEV8FE-v4x_pH*{>u8UUgEZ~2aq#qHD&6;4^HeEen5jp9 zF3r^blia+CrrL`~(Z|*sE7jj2DcEHtKjjw(6z$RiSbfcj8%1tG*O_9?zLgY-{@+5L z6)psD5CH7o8sLB{PF+8V8x%Nfcf$KFsC^LoZd2^L^D9rn$d4O~vWY&P;iMSZcIfxY ztwJpGzI$QFLjO|@)+^bdKXxhTB&zd30|3?l$Z1=o)zK;-(@ zI(E=Fh&)Qok)8JroKF4<(4c3i`;y-rOT@}!{?#YfyI?%&_J{g@N=eU?r@w#7<3`;q z(+U(yiB%mI37q#YdY-47<)3~y0&u(Z2v7yb{w@nyOhpyZRN%zIjeq_V1X1P!+A5*a z^V)U220pPl_>9dw0yRcxD0OXVPc9VSL_}`=6V<4WPjGvF_epajU-+6bb%L-Lw5EOP z;r{7uaE$5T)PI%>TMnrO=H@<3i|N=&0aB#8KtA+clBmuL#Lz1OHolx3*9$Eu1q5Dd zHBT)mFQf`bhWZl5iKdPoLeSJ;vZQ!&Og*OfwJZmk9abDWH393XKN^lPoPiea=k@p6 z&9{G_yFJ|JMq%t7D4XIHNZUD2@u18OV(4kSDN&z~MWMDh-%p$UT=9rO*pn3-JT^oZ zPaln&PMi?d`&Qk8hAX;;h%g^dDJ?zsE+r$b)*tHmVsn%I$vgN7rQ%ujb7EeK$J)ki z!P~C&T3I@H7!~;Lr&uqfP(u{+GUR9U#0*0jS)i3>1HsZY!Jh$6omWY<27JmQJ;mgF zEl*!SEPA-gv<&j!P>Ym9S)22x@4|Dcm+3QPj&LzKunYdnaC6;BU*vM9BBPoi0Exk3 zet>y84Ke>W|M)q5#Dz}_D_zz=7e`veCn}HNbeNgM!v*b3{bhU>a(if3VFLk?biO

L{mHpMORBTBj!q2B;KrzKn^cwHd!v*OOoMQxLI8pAl zebgJ2Z-0;}AF`df{d1&@;o+B~<$}^XM;>8y?umM|`c&Rw91Hg&jmE%K>s8fLh=g7f z3Tp_b3|VQJj{&cxg|HsdI+CKDh;yt`=l|M(Mg=Sn!-W(ga^K-NYMK9}PbhpdLAI>r zgWssRa+ zxZuDbdc+5Ejmpv#^Mv?MePLGh(E`DP>2Nv=s3~F?=r?4SmghX)B(Jaf<@s}b*URoh zdtb2N+^HeIr?E|)_1^Wm>3K0*-x$rsQ{i3uiM$foVH8E$h+GPYZZnfR&QO78siajg zd!w4dGJt{x8(v^^Vc3=veoZluG_?RO`gOQ|K9tqXed^434Sv<7A$o6{Yf_?n}N^|zd_g1}u%JX7b|_DE;ro56vfzb4Y}X$~6OAD#C)p#Z`E`KO;h=hMV0 zl<_y)Z#WIoP|zM4{2Tvn!+Lpt{h6fn9($tE2yW}Xm$Bm|z*l&gabjm3{S_tt zot0r(x~Y1*!1Ji6UC}QZZ#HLF=k=8aG{!X6qqHdsOZF4vVJ~BqJc`f>i!Bb2V5Byq z6`bw(k#52a*2~c)_(UA%tN8-)ti}aYPOW(eE-@khSdx&Us|-HLPif)J-&ktBe{#9a zUcWdWWGcbonV7ceSYg&;Dkv07715a1SUKDdX+5#Q#KfS>r&5P2CGHvzjU9QEMqwb& zGUBAFLuBhBPX`7BQNq7*qt1na=|oMoue9D3sc(~6GTzIb==2zeO-58tOH1=d0T@I8 z51#s3VLHad6RAQ?#LJ1gu-T)JjWL!Q?_9i0p7+kXvb<zChp!}_2j(j{ap{j97Z1JRpC5>3>iO_n;twk`(b5b2TN6uFNm zbIgmgl%>Y}^>_Y8ij@FU!+P}u4tMEGb>2-(O&O#l`RX-Hk;}1?TH>$WjEGjj!*UOs zdcjeww94eJWh?C(_uFB3;k6udBBPPOZskt53f^0qBB;HJeJ=G%t!COA6R{0aDV^2_ z3kseT#1*G-m?2a%|HWvUv_p#6_Wl^Ki1`Rhec9bywQ#X}Lqx>cF2DBbZJp?;YwR0!l~iJXftg5q|Rgp*w1G=qN}S+Ezz@2&c?fT9`NE<~6e%2=kj??D_w?P2o1 z(wy&aqW<$NT(}xGfW#2Fe{qP(R3~36T(0{U|A)!vr2?9xg_i!7xS;JI4Fti5zxl_* zW!O5e8a>MiC1C|{)%(P`v|_DQaLHm55i2lk1O5HDYD87ar}s0jQoU$P^pZT}En=Ju z^uP-&BZhLBTmt)FGkFuANJ1r9vgUI1sGr^pe}DGC^mhE_cNgu^vXp@jjBN;p%lgM3PzB1nynm)uwQ15#>un`~JMLRRcdUMasYlDo~w-}h01 zoDmyRSo_A)XXmAs=xil#=eX{y_@9qXDY)4k6M%iWF-W?~Ed{q!Gwuy%+QS}u7XZhw ze`NL^fy5IIi5P2i9-ts2Ifp z^`6}AV4=q#s!op8M7wm0p-TE86TMONOyD~75@js*^8pWW;glu4fs#mE-h4&=sNdwe zUJE`h+C3u2+614`jm2Q%2s4grLd=erO5w;tKkV;D-0yfP4?!aIsU;584UbJK=#wjP z9#_0%y`m=i_B+;$h8*`GjHpBQc1zj~`J`a@w}lr$7ZexT6LqP)3j7OiV%?pYo;g7hJ$s%cwtZB&vsOxIW z`?k2hh(3so9Y^{L1e2@2UDoD)&YL1fCpt>(cuGtdVMkLP{$*!`X%3s$lv#KN3&v## zQ#!=5{ySEE1d?nsstIJXXhTy4N;}|zR_}B-YniBgHGewcQ%NQHh!Wg_K>}-6pbZNB zLM61{ZGnUCoE4J&_Mw1v%l;32vi&ns$7gF^@D5|8$*EmqqK+B-A|d*HFb2^z%wUv| z5tB_Bg|Tg0cZ4y&M&KB=Nsc{`v(xf%nI=fmjC5RLKMNrnGL(OhGW8t_xdC(Coe}Of z97f~x(^1?ejMhm|vX@_XYc|PTVh0*=j6h1}qd+rKCi6o|Z?!L~MJjf}H0up^1X@S2 zWq=p?YvK$l_hQ8}4pMTEJWYPqcSfo=GXMNn3C~{$O+*(MA?@lw89}_Bg#C@=&-V|} zp~Y-UGmQ;;@?J;zEq*((?22xKCBslr%Rg`pak=;bMYuJ)a1uwri?1sU3hb8MO#jLqsxO~ zn0W|j@u`Zy6@Oqz0g2>lu(q|qgiP%cJ$(PWd&uR{vyqK3x46ihm*W;PL$#vkM7*7?!u^Q3kcE5y~#YITRKy+?WU=D#`lWm4!iI zaA#hQ$jCZPLx>@$@E{aa^R2fMGIHu=MbM<=C|BTmL!hoJAJe&Tov1NE-5)_&ZV77* zPe6~&T2}6#j`7rdn4|VOXYHf0UWvt4XCgkZYIW5xaMXk$$C5No>4N|Hze`_S;8l(8 z4I6S*pF{=;coMpof=RyaD4-#t6-?$nZ_aLPbuolj<($Kv@`zzL^hgE~>GWfo~fS#Ii2R~jA zpJpb8gm_=<5EkaJC^_OP1(~=>dP)`L@K&!mte`Fkf7e|WepoT$TllsF|w zgpY`4BTDj_@k*N=BT$KYSur*&dNhjC4JqK7Cn)m4&})uxUWh|7ry9nWfnXyw7&`uG zueb<=983TC_mQ6e;8w-z3)}X@rG-D%wIR;wA|N?AOzftGptpvlk885>Uheq{U0ok1 zOMX(88iE4G1KDesnETg_1Rya!~Ee-LD4(;PBvd{1#M_FD_m7OXfoX4 znh1(X+rkeTcEZ%Ju3S%M0qAlC~(ML#YZF|u)h2j(+cJ`r-+|z;IAlr9V^0$ z6s|Lrt|5oBQ;+Epa2xD?$3^KShse(;E;x5<;UYZja;;6|J# zGH}RXktec&_~S9Jw>;?_kNmhF%paB*7e)rK-|evq2B1b*a~ykf#zRAWIam^LP)14s zmxKi~urFfu!T^nA_%>}YRS<%%P$3~1t_ku`lnL<+Mz6YTG{Gu~k{Xw4v{r1o1 z`4ji@W~0w{HH1Wde;lPt+Hx*-DqtqO|NQfbFFXa6qx+J!t(}h`j|2F1_DV?vPY%(B z#M|f@`44o$O%)%%M_UKz>It*q(t=I=#fQY$91j|>aiRQJoK{hO8I_A_pF;#&kCmzABz2Sm=M~w#!2nbQwSBi~sD2l-`SA|ykkbl^6dzT)D_JsHO>GPf3)sT&%w+$?Gihg zbo9G(b``ykWc=`ns!L`3w$b|bCgS1Y;Wr1te?{2zi`0`Ax2|P7na?L4#Y$IVqH^@G&}36y)ay~-R@;R*nCv1$2fUJ z_V5b3XC@YEi{-xlo)(eL9DI@w9c43j5&ago^r4(r6#mLy zYK~Y&CjRd)EV3{T>@QSgy26jhqFK5L#IA8EKrl|285V_*0TjjwLSi1#hj~-E6=IuY z02NBbmlM|1gcA8*!GJPIboUfH&?OCSNpa3zN6zv0r$o7^^yqmMyrun~-Cc&PvR{GMf>LvIk{;ne7MKz z2pHA6o`=htcPNj;Q4hWXHcqn15=>)RPcJ}<7nxD&B7(Q|_lEOm%swALo9CX5HGv%j zdLrDwD_mkHN|YjvWD|CmgF%@8`a375T$)1Vu{NjM{9^I8AN%Ri^7vtzZUCU$G)Lv` zQ$Wn$2$n%AQVSNR)r5s&2^)}Dq767k$%u%pw$IXbC#|m;@=$J3pi>k`6FVkqSS`V( zvV#~SpW=F-5cE@!LS-*VmoUaAoV1|D2JVKP_%3E&WIHFZr!M%zf0|}dMChC=ksbe6 z?$KsNAmb3oR6b!`g0ZeR&Fm56-Luu=MzN&|8!_j1u_HVF3te1A9`l0qA|T0!TM#Sa zO;O71(tZCmfcuN6w4n}(ecTM5kH+9}8j4jMz z)22@?hkjxvocLPgVcmQ!Z&?4k`2X836S3a*!-*L?ykxnUc3x%|HWYkx`|5*BSt$)n zG5Mb?nK{%Gbj1Itu&htf;{Mma+Lr5TpieaW|MeSWPYa}+;cTw|HBH@VN3UkGVg2mx zTbJtp|FhRiFRXd-bfZpc@Tc{_Y|12XP5yfA-qHu@*RB|Av}NoEM$jWr_}etF^16k; z%jamxb?wwWvxkBEZ%LbtU;{@@gCI9>pU0O;r~Hm-YG=*bv)bCU9;oa4kL;@Bdv;2$ z^lmlH%HF!}&v8wy&}p)P3JX0}co<2tG&xLgVBk(E)JRy6+S<=?R*plDgQfS;H8#Pl ztmN~8PQ^TP{`16&K3UMT(*EJL^1kP)M&196SuL6r**-muxwf$R|NrQ-e{ZHVt9;o1 z|4-JeUuQDRnpfz(yilQ4q5i92a`OLw*CH4NS~;8*S`0bdghOx6UL)D-vL>nbs(!#K zAC{}p|Nk~~nKDM4{{Lk~pvnQ?(Ek6u%!Vttj)len|Nr6Dxqn{OzYco|?Qr?LWcecHqdA|} N2}Z*YrwFA8003%SKhyvK literal 0 HcmV?d00001 diff --git a/src/sound/screen_share_started.ogg b/src/sound/screen_share_started.ogg new file mode 100644 index 0000000000000000000000000000000000000000..1a3f0c1d77f90d5af2a680921e1a98aaac7e8195 GIT binary patch literal 16737 zcmeIZc{o+y`!{~?b2!GsG0!=Q454F4l;IE!N@Qq2D1?lWDPb3tBuOesIx3P*l+XjYmLcgFx#R$R5wCXQq#G=T_y48 z3tFjoJjW`Pq@$l{wIAd7%n~x&>TH3M$>c&e_47^DC&uBjwmQ{kmZ7x6+Z0ENCywB~^9tFyAN?#uFVlXr0fV8D&) zZA`qeG5PbxRK;DXN`LPDllkgzivHZ%e?H#`V6%XxEcD1IXe?`yb}i! zlDXrL-yr}FfP_WSU1w*wA!l z7fPhP!2iW$T+&kD8c%^icV-`Bmq3Q)eFM47jgKNzFDI563}lAXzv|D_sz<47nY;Ki zP`!c77mQuJe^bi$BO5c+7RwIQe|5_gsz#~h1(7KkryrpdXMs<0#^(DdwXrPH_VVV% zvXI55{ye_D{3@F%vY5>)FS~HL@g+)GSAXrwr2JQvKlT1F8PQ9p96!CMQIQWf56sK`7gr>K<8FCCThF!Uyr>B3dbdbU#s3^ z9JN%tm3J*k`;Gd8x<8LK-|svSSj(^Vg0gN!!3$eE|5eR9eSa7XWW+t(?&w?a$ktLd zC(V}k5C5o$_huw1kCbhTE$>ZGy_p%ztCshdozz9q09cR7z7vxB_x)40K}czvFuFB9 zXs`NUXWWLtS4p%}>#^Na(Vx&g9lB@d1DX+5ZxvS}hq;XE3Ok zM)?<+NT3iTy5Y}!+f<~u`Mu)X_v+T;y4E5_+e9rs=sLU;+r4eI|293(536?D>Fsvd z?!V)Lzf*B&$3@SMsp#(ixOa2?AyF7$P3kh$)TOGaefr6Yo9N!PYCtC~uE@k*mE=DC zRK-oHNTZ<+;hyUGW^+DH41TmHeQZPuN*lB1~XYia--1~n2 zZH7C)?f0Df8`ZoXmAuwECi%!k`b63`O4Kby_e9e=jT?=s%L|(A&5nuQNOxBgvlXyK z!aD|(42%^dOD|GK_aDvxr09|x4FwBz1^>w_S`pQ)iMkEMfAas6ANqS;`nVyw|7iqu zG-@a`YA*CoUcG^+`;KV14QY@6@%8`gs}S{NF4SoFAAO;Y4B!3#LD&Cyu>ZG#|I;}@ zL8gv{{@fHqrHhtAf(Qg{6jtO(<# zdQ^N>1Q$3P4e?wIQG+V0ERL?w)Nbzq94USRYy%*@ysvI0Vv%~oCqp?=anlDwYf+z! zfygYM=i`QpWMA{npjd3vwMx(R$ycLUIfx;Dg|*1`xZD@LaP0UU4lpBtY~tQs8U2x2 z%89wRGXAz=@lMyu&S6t(Ze$j6mV7dD^NZB2#tj!ul)Zz)v44v5^S_~vtVL06ho;b; z#THPH`QIM@>GXrWl|$%mYGSTWMt*+&T|RSbQPk${me3;uC$IVB=ih#;NwHdNE_C-U z(&7m7hhA&b9Z*ZVcU-_0KN)&l#Bbx!g5F>7gvFft8^m=1S>$^sG0r8aohp16&nHOF zR#-v6RREZhxuSNjY0DLEP^7CB<3-JuE9Jbm&8Ob5wN(|1x3^SNx}IjcU)6zPt9mPq z*Gx_6ye&ZM5hD6KX5(FJ2~_TTA3AZM9TYimx|S&PjWZ{38+Mf&bz5_1b=pWu|}FZHoba zvil;t5vMLF{*jhSM(*-We+7{L>Rc4?jAd(h^_hXLajQ>;BvKCEb11G#*O2C%xo$_3+ckZQoC>=3eHcuF>S^ORJXr zhIOCL-@pQYbx>mC@KzJMx%#WVdxubYRESV%BT_g;MZ&V7JBxuf{S#iTQ$pFm? z0Wr>`yAi_S-)xilyq6#V-~^B-Na_KW{0PDmgbq|B0Ax z-AG$Z*_t70k)Zz6Q@VjX+{H5PY$QBO)nn+hoHRtTYL2iak5as_t*UB{s3o@odWp*H zEqSuzh0)|(e|$jU8|rz$L6rij$|-;kb)0|&=nk7`kab8!5P*_r=1 zVT&>QV!7JM0|~O4tMv>F_1VOq6TjJn$zN=kV++o)Mc5K-(S@Y?f{viUPL;&|va8Wy zTHi@KRVcXB%C%OfZV#20eUd$Q{fB?U5Id@~%zcHdm~M;ChD7nEDD$c-cIT_Aq}Q3> z>Mf3L2(#U@U+Zf5+t8Z3-3B$;eY2V0ry@seGe{+F8A%fyMDy~047_>U&$%xoY=8dGOV5YP z=X+aSidEM6n+(g6uQs&z4pepQU>j6;T#JtFp6$*L_aCdjdt~U)sqW;jfs&YW-}s|< zE1r(MYn%=KmVIWQrnCxtC|*75G9K)+Qa&X1irvKV?ygt%L3xvG|3_jzS@{KB3)e$5 z4m9n<4Ew^9yzl;eT|oLY+g%yXf137|!1~d<5WO9f)fY^;f-?`0GGYIwTz!5eYv!+{eUo)JY~KbP^{kh|$(GwbsHiz9xm-CY;nJ_<98 zx;~Md^G!x2U`KD=2)`)rm!@st=+(Fhf?OsI`=4E^6z|@XEX|&e=JKkTFO>k6DktOY zd_@+P-u~;_o@9gmFFg8DTFtaNYu9jKeGCUYHa1Z5Ped+DDu^Mv ze2SK}e3IMwbyLOk%cHW&MJu(|U$?T1VQeV2QlX`~9W3^?xhYtp#hGEvFZM!+g{f=1 zNXuyVW^T)en6llCXLnJ^GW*YDcgPsiKQ`dX9|d9$TaiZ3vwLsL0bFgs7Hs_SWrh*G za(p(1*Gq=o5Jw=r1#8{#z5#w>tl(jO+Shw4KwW8N1h{!fq_Za>W#Ssw(u>*EIz0IN z`njjTjBHv3xc5?S5QzDCkg%rGgaB@HPrm}VN`uYeL!|Gq68QX=DJ;*G%$l4~#y>iN z&BQQQP$fGGd1WWaF!Q^H)Yxo|AGKD8J8n)e!G=xc#2cy%6GjWuU;pUd$V}lbSW2s= zjbEob)IOxgC7rw}D3+mJ@Rs)Rv>z=Xu+ZlTL>yW^x0?}NG)^prY#~ynTM}q6IAp&%G@EZzC4OguORt*_!l9v#{ zTYfFrxXgc*1=hd;B7XSSWdX23*1yxWfQaj~fMA0NJVgr2aBfDR)PDe=hYRT6Oz2;_ z0SZWP2UT@gP47N_SBdX1A1H0fdA3VGdlpvh#C2G+9;;j!fUMDOhC-LzXeXbi!Lwc) z2Mge!cX7~T1({DCDAVuG{UCzp_)@^nsEfk%Hzi&;_#qr1YQANeuqm`>9XR2XdmO^< zzOni+g%##K%gL_e(t)5TRu=L5&o5|AUFwc{im|5qOqkOHPceF5)iokrNDP=Jkhce4 zK#K3fWF!Xl3jiVPIYF9>i9Aq^0m2GNptm3eDbFQfBjy;V_QWzya}GSAZZFXEoE$O3 z<>%qJsFlGA7O$?4m$WSN$OapcRzEJYGc2gM6wQ*eG%+93ICsUD>r$JYe8K8k^6HOE z*o)Yx@dIe+u9lT0$(Q$3pVaVwaw$s0-9Zco$p><*emSNT7go#f>krd~^BDB_mk)y* zV=|R+aNBO+$eq!(twlA(0`A`e(Dv@`$=v#KJA^aWjD z77T|2bv%dwulr_!K3}N>NiE>k^9EGp-vd5Yr9hTs8$)_`3*dUQa=@A=z(yJTwKXoo zO~4>olUTbSvy=yT1$mW_prDCW*VPj0Wp_8HEEd7;p9g(Z@**p_9t-SqnZW-ysA65#qm_2>?yr0;qUK~x16+fa1a8) zubZm2*}Z$bRT535iK#a`x+PpY8n52X-_-O-i6gkaW76GaYk9fD+v1S5HDz{|zImr( zE1T?nSwmH~*3^W#RvZvGJhSF)WMy~B?25uq>|R=CN9+fz*7cIWLp}L9ZkFNw)k*y$ z#MT{A+r=WDb3^T*wvNs^p{cK=yoEaW^kyl3>5@_RkrI>CPUom|j(q(1QVbre1G52} z&a!nlR!OiiHZe1NBWc2TV!B45n)fYUtR|VcXVuPJ)krUI+Hn>7zFB>}F5ZfF8u1H^ zvh2x-*Pq^t>@-1oy(Ulzd;59ar#BpZK0j6$G-=h>mZzB}IG~CCu~Bh$+5CKDchvFd z!)YJtm=LoY6 zTJ_;v;DuPIx^b@aNLTK_eCQE@lAfnnEE^1o<>!;P%pcqh^bHP1yUu;th{04;8JpqFTa3Odl3_x>A)NPTMHD=8;#H=@>na$5($8 zU<0u3XU;~IWycD~IF^!P?;kxe*%s|rwER|nBB(&{AT}L*_q3qX&nN!eAsbJrd{|d~ ztLM`vJ)k%A-}FAU4)2sZbZ1G&EAeumYwVgI(Ok>q3)5lUnf0iia$W7L&HR}8K@b?T zHH83~>~#>t)*cf{KQTW|a_#A44}Fz{u%HSl=Jz>5=M}aIjL$Y|%41_~{0~dI(`KZrGMs*>^!+l zDnoxcGo}0^|J_g@lJ?c5x?7kQSl8FxuU6!?Z@zTgsdMRi|MXW^UKqHWrF8Dwe-dWEX=ZtnsqnMC4i3Nz_eFs@|8!ROaPSVpm;FI;1N(C#7({%_aInx- z($ZSZX((3rT6d!ay?CSFI76@mA_3S$CA2l`veVD z=ttJZ#a(GjWmdD0R&WYq1^+ zy5UZg0_yMA=N!2{AIQ4BV>I+btCZH3)r3adGZ%a?`2N`Y6#)(pok7aW_S9tjd+f(+ zT688Ru-2xYw10%hgT2}WgM~AI*Zdq;melDu^aPUl8e@N0y(PO>9PET$(L|dGA-eqn zr>gKVf&*I__ky`NfOs=H?}SLsJgHV*3vdm98(g@R2}PExhuh-SIv)U z*Z1>znPQnLoO^zJ$(UMoC(2b#FKb=n;PuMR;gK0zUb^wS2Q^#E56!gpY4)vymfs5^ zmsU3r+(y3lwDh+2R~3$o$V_+S9GSl1l=kFleC0eSE!!6MBa@38fkgE)TK1VfhTm92XnOLZO&1Zg%Rc{Z+^p6&C>rGtF zpSU1o^=Kmm1XZ`zxyQeresjIfbq`4A zKH^ig*_S}U$6gn0paLa{aQn0Y2URBCkln@RQu*?f4-QQ>ls`c`07F;jpp3~Oq063^ zWVj`bf0;M_5h&u;#hzmWDN1Ib=cbl&J3k(17|`HL#>S>A+? z-t#-3%%B@htl-2CwMhcyc&k}|!zmOzwxWkyo(LrS;!Z1(9Z!%4Zf`bI^5Jj%xPH1( zm~dlsyb-nW;}No^T$fbVZ;gmK{?hEQ(yzPAjLNCP!^hkETI6^7i1bv-r@uLNJWFK zSFsfLqdbUzuWvCa24-SUUFridmEDt~Kfi_Ud5?JrLQLeId}z#WiHESx1{cq|a*I7R z-R#C!h>G?>cIqhr?UI;rRj^r;L*G1mW8D@0Wg$VoCpx5}*0?;2aQ+>VOy-5p)-kK3 zfT?|}g-F%fqI(K}c4P$s;Qoz!i>BvZP#UHR5JZYz?9`2_S1xd2{(S)^_vZpMt<5nCQ@4 zj!btR_Ix9!%XEVJOzF(>i$-O>SC69=qYm1ST7*sdd(&StwaVKmT!aCr;G8FrPcMHJniI?Zhnf|H&|3DV^;3XF;}$B@7K z-7#L8+YY}}r`Rak&#@8X8CBKgqtS(2c$SoDtoz87de6dH#(w{Xv5m6k6uA>gpI(>% z&W<|8oKPP%wC{G4cKbo7uV5Vuw+KXYMvLM{uUnsuj8iAH*cY8j_Ty(kRv(0P2 zImPmTn_Fah?>U!~^7a6>hpRQ^=qhWI?+Rk0b@uWT`x}Y5cFNE$0F2jM?g(GCtCPPi zgUjY&TkZuEyec5NCD+6{xjojB{5?B+R|lK>*)a^YIWhq)F*yHt#k1etRj2)+qKr*Q zNts&dYlD3oI5F0fMz{P}*?dsvaT;ZB!wH(wf2E9zKY+tDn?p_~R!!RzAshzzw26iDaGa>VS^_)OG&_9>e(9OjQ zja+UAd{3`(CU;gJo-12YHEaCg2rcpMm7_kgg$-rwC$sCe<(SQ1-Wz&aCVOdqo-3v^ z)1mgc21TELhppu@i-OP4gW;$ItuGcx2zU@c5#wmow+Wu??fy0 z!ciUvAwmO2rJUGH9KF)TvwFw-_JH&$I2~v}ggbNcTnA4an_HVn00W6FC-ml<7(qdv zhLUZq9__Dx{b+t-9VIF6*jNx=AGryueG@rrPaELET?Zbm-E0XSGwFf!%3Bw)$FcMr zVD9@l@lc?F40O4j&Ohe)MQee6+NHUP9jb-3U z04Mc#Y|mAUF>M=L@ob-@u{J;vR+zPvpM-(=dN)6S#wHY_NV*UyQG7CW8VJ#47#tae zOK34^tYKm|KIBuG*6*HalEFna>%7LLl&g>92EQ&%EY-{WytP?)WkPO`2ev-Zwq5+q+MuVSDu(MR@z=!4 zlCR~H+;mdy5ElW`1KsSNlE5vn!qBjse+hu0cM-Y_P~-I zQ)nej-fVx=+-4Qsa#IpY>D)s5xzG`f9SfmJbSyt6dd8JN$I4w33493Xb6t_r0jd@>uGvf{f5$p&fa)>s71e+1mxJRyAuqH5T-wic{7bD2>{TMbC4UNh`HSuFczh471v@adoCC6w4 zDly$*NQ8+r_)t^P^M$mQ1+*{K^^BB~FNPypd)MAdB&{2jLDEHDrXnzLn+69prSF@8 z`nhLf2S&}QeE{iVK44=^faTfS-s2z7^TG>!bm)P!9|Dw|s8r}0)cB?)B4Ds7`0~p~ zRT~2CPbQe@K1&li`NyAMnPtGvrs<8oTA~}V(8GDot?#XAP_Hvt-~F6SSDmKRe!FMC zL~!QA=&}qePHmRE%!-BhHHU;*XQXcv5caa7B1!S7<_e(GgAWNU_ySyv_(H_rZr|>8 z$RbMqj007MF)_RD9_=ogF5mVL@v2#VA}f-Lgx>gc>K+^fw{y;`&kM!Yz=ELu$ciqS zADx)qu(iFbi_V3&u#N6Xy4@aNE8!!&VEmIxF66*R8$uOyPTVU%u!H1{sRnKieA`bx z5&~b4-lrw3^aqfkx2RE_bQ??y!T$VVRfG=1f{K(O=MrM~!}m55t2jj=OWck4T@W~z zl*yepBGkq&JHpUA{5dS@B)_>W`QnjnYv<4iVfynX3i-=bqN2W(?&K$5DD5G9Iq5%r zTA0NZlh8;@+a$Y%h~rjUfHvaMU3vURF45-65dyGc!xbWwciW*2#(Y^i+hPX@f&(X> zP+Ty1AFCbc{TltUR&#^!UCx!lb~oh|Irht6cVr0A>@vtOz$1u{3qtttT!|iq08Eaw zcgmejh}5Tg!(Rlu5y&^s58q?wj+4{ccVP@HXRhUw1>$P^N&Y$& zob&` zHZ}JNWqh0<$YHgwX!Q|(bb9UFLGPmN0M`J6&)mN(9f|NV>vu{7vG&5h6Uxig~AX`+TX+Fj88!swMKkR5eKE4NAn5od8@H778# zHgQdFN52(FEFnyIAsL53gaF{5ee>=SR6u?!-VTb0*%c9T!#ca^2ldrHZdv+d_paV! zdDm2RQk##nQBzQfcoo?DNi2eOS(>H!BA~NT(?4lvEj=Nw)*#zk8lCuA4z2hrQsj0- zk840Xb<}Tc*WhxrTuvRich#RjJ7R0CLm#ZR+Ki{18t!~6#Yoax2A_*~#+l~5wkOu! z4SF>E_2CO1?A`FEj&(KuPj;1>Ud$w(@%r-e2#++&d^xZe9( z=)m4Y02K9s4(aoS}Fvsgp`l5 z_Q;ey&F_%mNjK!g$rXCmLj>j)9{Bc(Kzod)3-`y1if&k=13qJmqPf}+X}nXeKvi!2J#Xz@rATdW{U%E`x0kzgwsi9E-oxov zM0v)H4~>w4S&30^HH1PjFo>Rq8wCB0 zk%__UXVJ-Fdn__H@Rc0E{-F)>u^tN+xz{Gy)fC6u~yNdN698 zb&>#iBrv}x$>7v><$zMNY)%}E^@p1?@5Z~(c8hcGS32FEEBlUgmgc!Wcz9GEag_CG z|9QoVtDk5$Ic^%IZT362Y-d?MH;NW}Q&z*ll1&l9pFKaobN!yM71=1l%)HHqxw$@j z>d<*qwQWRiwVwzPir;=vLxGRsA=oLfYo*RSYWU4R@y+RAR!BuhE&PB;;S z!L3_Ig((bzu68`51HJ?t4|G_{fY%qfk-?%aA;a^dxBzF>9X+NTiMF}5GqG_AH1kFl zcof6b4X|cDz8@ZFezXf^k4t3~4$kw-Nz zd>xV>Cg)unCL}ul2k{{>Y8X*Se_c@0|q;LWZGrjG;AraxOeTu^{&CIVS;pGJ@I*y03dvcv)j;=m4CFrpZ zxJu{mktY{?NQ`%q3?g$y30F@~?9~G>KG8Dsh5)VBftL@k$8|x(fkDIKQOp_16k{sT3GgdQuTT)^T`?=%ei?x%KAnuw2$TV|_Mt|I^`0w1wec_r zG7Yr9@=7}G2|tgIBs9Lqn{O9Jae(p0D`~4ZujOYsE-lcLy^}nd_9b4dW|w-)dbA(5 zFq-ePFnY!lGak9p34Ky3`0N2JhLszcRAVtb4-b zS<;GiqsdkXR;gfL`c)|oR4%A>+0TJS*x`4H;|^CJ!NcsQLU)(=D|mW6^CFq9&w7xv zDNL5m3*PMFGEiCVmxAF7);x%bYltOckhR1WE14fB-z0%?bb0J!e*u`CKQPe`qmOvG zF_F9_$?)`tohGhxM(ux9>xH#cHd$FmYbf z1N`QX_OKq_3fZo;rtRa=FYP@D)ca)8Jooe7Y4S8D*u)t`wOuE#U8#2QHn$-cZXWaX z^ti(%!sze>0X%Boc>x{}ydc0Pb3$AD$Ip|gS8JwzM>y&`^!xqZ8_Ugzoz2FODfFBg zLV644C!^OUJyj;c{AyOkFH&K|<}hBs5B3kCffi0TcPL*biQ>CWXzVhq!Y~#FY7AKe zm_S{ndKU)ZA2NiLDjqGRQY1H>%ex5`nFb9ZNSqXay#Nr$oiTX|OT5;chxrZ*#|oDb zc#@Yf%!r-j)jybH6t+bnyk+`I zV8poZ^)|N!K46f-pM+d|zIDZh;Ja#Y8t}&+FQ>iap|vlcs5g3hnK2R4%I}qjtOCl! zkdCyP{B(Fvs8f_D*V*zG2hPdqfj3NbX6D{$P2_fW&dqD=T*Cq3?JZ>87B6h})Da9a zt*@9M1vzqgM;t$J)!m+d-6{ef2ZmH(Zou`#3{u?D7178>-t50;9S+l-w=g+i-1AE+ z;i%gIHec933r)9S>W^CsUH4P@aLD5#8j^5+Kh-v~Dtd*&fSR8$#TdUJX1t)hds@UE zQS7vydRMO6;7Vw{*E)N@S061G5D%fNd$-ZM3=!9_g@OBRw)zw#mgQ^n;66Z!u&gGz zJuZoO@@DN<85kvtJbxc3i1%IBX@}28uRNV7IKHe|%5#H%o8(rfo_M!&9T#2!JegMx z8I^=ul6QcsX1@%>>-Fz5Qh4g)1qE?2g zAjUde8Qi-t-sy(_9PfGRKM0VvV4S}t>JU!^@4Hc(3A<-ofMH&ANN zz#rf`cH!u!fFyFKtJX8AoDcqzYTF$+8A8CLe9WeO-FiI5^+#vPJIlJ+Z@EM)=3p%! zJU5bBd%o@9>GmQ~9Ba8mjY$cnIb&q54s`s}kY5cVGRE-0QG3dcF`pBnl+&lQ87vbrqMVvjB zZoBwQ#=dHP9hXFh_}1)#Ik)?LOPTsM5q6{dUZ++c|KvAqcK+?wyX16kn_pN3m(`q} z4#l)c$!=}uspL6fS)riK=Kj-MU^5q2x?FrT`IVy9ik|Nxr?k@S9mFu?0I9DW4=;+@ zC`Io+zsgxiK7{0**}DvC*XIy2g6>|lLuVXEPv4uuT{B5|stzbkv~eR(SO033sgEG0 zKRq)~s$SS&jR!A0L>7Lzi*_jrpdfSH=o$vp*?0VkmHHTCpDGLro>{eSp^yx;gEEkG z;%a0BU)@43`Mo0P1<_<;atGwq+MIY@tV1C#5SY#4t;?}qP64Unw!PZkVjJoGHqVq(|Sold13%BG+j;vX$1uZfgZt1Ug1+?@GGTe0W!B3D0t2P36d6xEvI4X~|~ z+Ju6=4q^(8+&H~*EWA2PH8iV$Z*4Zf+_k@A0Xg6J_JtWL zT7}~uPS4LP1D*XI7@D6}b#?)ajlYQ{0xM#78T40~7vnc1Y{6!wrY#H!A%b&BX=SSX zCMZOsl}Iwz;|HnzxX~uOY=c`3@!7}M{E%xnU2OqOH05MRUm918SCo#OKUp}o>W|&RUA!z>aY-Z5urG~$DWJ0%pzp* zBM1F@yCe7e&)8UmU;&CR0QW6GPn)5}%13@ACbM@cT6GXn>5_G(1i4=fjoucrcL$m} z;!t}}9dkobS8n-tFZ?4VFTIz6#yWQ?US!^1SNseU5d8Fb_tUpn!GStKjY zZ|VJf?js0umhB_rBNBz*E>DRt?Sql}`Lb_COh@BT8uA*1sj_zw{Bmz{6B-Pn#C1Aj zI`jsa17^HteDBF;Nj7({jNX6lSd0w)aOM{jEVN*Zn4g~AsR%WqnJhdc!YDy+<@};c z&d75y9!BT!fKh&kr?AB3II4}$4Bh7iYV5>qXqVuGl$jMs1)RWQGRUJ&M~?CW2i^v) zyf^r1GAutln~+Az3*`luDd#4G^VA0tTO@3=!_tfIY!}RasCHR6!S^4ddi@a3(|KdJ zt(*ak%+@5%>T@>d?H%IL)(s_ca0F6rf63%4;^%|A>)Qk$A~a%M^=03aAeq6@4*Cbz z^vQj4T)4FKP~dL=y?O-Zp3p`Nyc~>eb5)t@iaBLC4!aqAzyfAUa2vB$G49ZWmUkAnC5@5{v!vsg#`Zp(|jjlr2 z$*W7W;iDjY#tFU=rjR>j+>-fG3E>caQfKq@Qj0U2q=(FhGy-b2{41zEcA2VOvo)T8BmB1Qr^0e7r`{4kuOwmL;%=0?L0foJk(bkQCP4LVa_=RNuc}K&?Mc6XsVvH7=r;X73 z2J?1Gsp(z_aYG?g=zRo3ibL?U9rZ8J?9-2!UR*6W5C+wA9_>;C2qPDA$|HJQPSskcB6gc;q>q18%6_+ABdH78=Z+|bfUSTNy51gb=TZa9eM zB^Egzd>g_EbhhehMiTOnq$@LZ78!8Z$u)nf1f_%pfrP)lC(f8ZuYz{yrnfOFd09gA zCZe+;aspQ}8G@sH-sc1u9O)d-$#weBRs4M}Rh#?xu(s%{_C2k^CCdxHZWwuO%~eh> z_~-EAR5;)CY_}c_M&G1IHM`k~ujdbUu*io_PCE7eH%Rvm-*mTdjE31DpY&-oD@JiA z3VtJwc_NgwKHd4}!n^qK-0|ab%}~g`yA2osW#=x9JnmivG(P>6E&}#Mde_ggGBkD+ zlO^k$9U8uZw~4syD`{u{6J-Sr9bnqH0i!0V?JgN{k5e$Q!wH?-cu@vy z(S&IZ{8S==!tZe$uEJI&6lG45YlFqWF8Kc-qx-N;O8pHc{$MdShl0 zhX;T1U)g*^?=QIF9D9|z#6u|@@*-@Z*O%4V(p2m%kKU_G17(!+v$V;*opBijgfp5D2es0jEm;#K$dFYm`&)$N<@GF#Q^9nY z=C`X@>9Z zl>)|Stn=nd4g&1ivn#6O1ePJVcjDT*vrcH=?6(lO9e!mz#S#?@{z9clu8m@yDBPkUIRf{zI30BJ z2pyzR43=m&UNdv6r|MSi`#!|Uh}a?u#wE_RtGQ!KPhIMIW2!FNlH~IyZmq&AiA|~| zn)=I~R~XB%etkKt@_Y&3vah7=cQ%Tdf?`YRjLvG`wVF!9-K*=%t&@$NDq>cLJulr6 z8u!jole$*(9Y#}V|OV_h*ZcMuEuDv95ZTwKEaLHtqt3DLrp n9DWVC{B>BP8l0jL8`ZjmcXlzeu0N^&Ky>6RF8M4j>J9%3;jZ}4 literal 0 HcmV?d00001 diff --git a/src/state/CallViewModel.ts b/src/state/CallViewModel.ts index 36cbbac8..5f1526fd 100644 --- a/src/state/CallViewModel.ts +++ b/src/state/CallViewModel.ts @@ -1170,6 +1170,21 @@ export class CallViewModel extends ViewModel { }), this.scope.state(), ); + /** + * Emits an event every time a new screenshare is started in + * the call. + */ + public readonly newScreenShare$ = this.screenShares$.pipe( + map((v) => v.length), + scan( + (acc, newValue) => ({ + value: newValue, + playSounds: newValue > acc.value, + }), + { value: 0, playSounds: false }, + ), + filter((v) => v.playSounds), + ); public constructor( // A call is permanently tied to a single Matrix room and LiveKit room From abf2ecd5217a584d5f32de12f492e7a742f20758 Mon Sep 17 00:00:00 2001 From: Will Hunt Date: Thu, 19 Dec 2024 15:54:28 +0000 Subject: [PATCH 05/11] Refactor reactions / hand raised to use rxjs and start ordering tiles based on hand raised. (#2885) * Add support for using CallViewModel for reactions sounds. * Drop setting * Convert reaction sounds to call view model / rxjs * Use call view model for hand raised reactions * Support raising reactions for matrix rtc members. * Tie up last bits of useReactions * linting * Update calleventaudiorenderer * Update reaction audio renderer * more test bits * All the test bits and pieces * More refactors * Refactor reactions into a sender and receiver. * Fixup reaction toggle button * Adapt reactions test * Tests all pass. * lint * fix a couple of bugs * remove unused helper file * lint * finnish notation * Add tests for useReactionsReader * remove mistaken vitest file * fix * filter * invert * fixup tests with fake timers * Port useReactionsReader hook to ReactionsReader class. * lint * exclude some files from coverage * Add screen share sound effect. * cancel sub on destroy * tidy tidy --- src/button/ReactionToggleButton.test.tsx | 168 +++--- src/button/ReactionToggleButton.tsx | 28 +- .../ReactionToggleButton.test.tsx.snap | 20 +- src/reactions/ReactionsReader.test.tsx | 515 ++++++++++++++++++ src/reactions/ReactionsReader.ts | 339 ++++++++++++ src/reactions/index.ts | 20 + src/reactions/useReactionsSender.tsx | 174 ++++++ src/room/CallEventAudioRenderer.test.tsx | 180 +++--- src/room/CallEventAudioRenderer.tsx | 21 +- src/room/GroupCallView.test.tsx | 7 + src/room/GroupCallView.tsx | 2 +- src/room/InCallView.tsx | 28 +- src/room/ReactionAudioRenderer.test.tsx | 100 ++-- src/room/ReactionAudioRenderer.tsx | 45 +- src/room/ReactionsOverlay.test.tsx | 123 ++--- src/room/ReactionsOverlay.tsx | 28 +- src/state/CallViewModel.test.ts | 72 ++- src/state/CallViewModel.ts | 113 +++- src/state/MediaViewModel.ts | 27 +- src/tile/GridTile.test.tsx | 12 +- src/tile/GridTile.tsx | 18 +- src/useReactions.test.tsx | 173 ------ src/useReactions.tsx | 405 -------------- src/utils/test-fixtures.ts | 24 + src/utils/test-viewmodel.ts | 150 +++++ src/utils/test.ts | 6 + src/utils/testReactions.tsx | 214 -------- vitest.config.js | 7 +- 28 files changed, 1835 insertions(+), 1184 deletions(-) create mode 100644 src/reactions/ReactionsReader.test.tsx create mode 100644 src/reactions/ReactionsReader.ts create mode 100644 src/reactions/useReactionsSender.tsx delete mode 100644 src/useReactions.test.tsx delete mode 100644 src/useReactions.tsx create mode 100644 src/utils/test-fixtures.ts create mode 100644 src/utils/test-viewmodel.ts delete mode 100644 src/utils/testReactions.tsx diff --git a/src/button/ReactionToggleButton.test.tsx b/src/button/ReactionToggleButton.test.tsx index 72437825..da3b6fc6 100644 --- a/src/button/ReactionToggleButton.test.tsx +++ b/src/button/ReactionToggleButton.test.tsx @@ -5,47 +5,47 @@ SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ -import { render } from "@testing-library/react"; +import { act, render } from "@testing-library/react"; import { expect, test } from "vitest"; import { TooltipProvider } from "@vector-im/compound-web"; import { userEvent } from "@testing-library/user-event"; import { type ReactNode } from "react"; +import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; -import { - MockRoom, - MockRTCSession, - TestReactionsWrapper, -} from "../utils/testReactions"; import { ReactionToggleButton } from "./ReactionToggleButton"; import { ElementCallReactionEventType } from "../reactions"; +import { type CallViewModel } from "../state/CallViewModel"; +import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel"; +import { alice, local, localRtcMember } from "../utils/test-fixtures"; +import { type MockRTCSession } from "../utils/test"; +import { ReactionsSenderProvider } from "../reactions/useReactionsSender"; -const memberUserIdAlice = "@alice:example.org"; -const memberEventAlice = "$membership-alice:example.org"; - -const membership: Record = { - [memberEventAlice]: memberUserIdAlice, -}; +const localIdent = `${localRtcMember.sender}:${localRtcMember.deviceId}`; function TestComponent({ rtcSession, + vm, }: { rtcSession: MockRTCSession; + vm: CallViewModel; }): ReactNode { return ( - - - + + + ); } test("Can open menu", async () => { const user = userEvent.setup(); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); + const { vm, rtcSession } = getBasicCallViewModelEnvironment([alice]); const { getByLabelText, container } = render( - , + , ); await user.click(getByLabelText("common.reactions")); expect(container).toMatchSnapshot(); @@ -53,102 +53,120 @@ test("Can open menu", async () => { test("Can raise hand", async () => { const user = userEvent.setup(); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); + const { vm, rtcSession, handRaisedSubject$ } = + getBasicCallViewModelEnvironment([local, alice]); const { getByLabelText, container } = render( - , + , ); await user.click(getByLabelText("common.reactions")); await user.click(getByLabelText("action.raise_hand")); - expect(room.testSentEvents).toEqual([ - [ - undefined, - "m.reaction", - { - "m.relates_to": { - event_id: memberEventAlice, - key: "🖐️", - rel_type: "m.annotation", - }, + expect(rtcSession.room.client.sendEvent).toHaveBeenCalledWith( + rtcSession.room.roomId, + "m.reaction", + { + "m.relates_to": { + event_id: localRtcMember.eventId, + key: "🖐️", + rel_type: "m.annotation", }, - ], - ]); + }, + ); + act(() => { + // Mock receiving a reaction. + handRaisedSubject$.next({ + [localIdent]: { + time: new Date(), + reactionEventId: "", + membershipEventId: localRtcMember.eventId!, + }, + }); + }); expect(container).toMatchSnapshot(); }); test("Can lower hand", async () => { + const reactionEventId = "$my-reaction-event:example.org"; const user = userEvent.setup(); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); + const { vm, rtcSession, handRaisedSubject$ } = + getBasicCallViewModelEnvironment([local, alice]); const { getByLabelText, container } = render( - , + , ); - const reactionEvent = room.testSendHandRaise(memberEventAlice, membership); + await user.click(getByLabelText("common.reactions")); + await user.click(getByLabelText("action.raise_hand")); + act(() => { + handRaisedSubject$.next({ + [localIdent]: { + time: new Date(), + reactionEventId, + membershipEventId: localRtcMember.eventId!, + }, + }); + }); await user.click(getByLabelText("common.reactions")); await user.click(getByLabelText("action.lower_hand")); - expect(room.testRedactedEvents).toEqual([[undefined, reactionEvent]]); + expect(rtcSession.room.client.redactEvent).toHaveBeenCalledWith( + rtcSession.room.roomId, + reactionEventId, + ); + act(() => { + // Mock receiving a redacted reaction. + handRaisedSubject$.next({}); + }); expect(container).toMatchSnapshot(); }); test("Can react with emoji", async () => { const user = userEvent.setup(); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); + const { vm, rtcSession } = getBasicCallViewModelEnvironment([local, alice]); const { getByLabelText, getByText } = render( - , + , ); await user.click(getByLabelText("common.reactions")); await user.click(getByText("🐶")); - expect(room.testSentEvents).toEqual([ - [ - undefined, - ElementCallReactionEventType, - { - "m.relates_to": { - event_id: memberEventAlice, - rel_type: "m.reference", - }, - name: "dog", - emoji: "🐶", + expect(rtcSession.room.client.sendEvent).toHaveBeenCalledWith( + rtcSession.room.roomId, + ElementCallReactionEventType, + { + "m.relates_to": { + event_id: localRtcMember.eventId, + rel_type: "m.reference", }, - ], - ]); + name: "dog", + emoji: "🐶", + }, + ); }); test("Can fully expand emoji picker", async () => { const user = userEvent.setup(); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - const { getByText, container, getByLabelText } = render( - , + const { vm, rtcSession } = getBasicCallViewModelEnvironment([local, alice]); + const { getByLabelText, container, getByText } = render( + , ); await user.click(getByLabelText("common.reactions")); await user.click(getByLabelText("action.show_more")); expect(container).toMatchSnapshot(); await user.click(getByText("🦗")); - - expect(room.testSentEvents).toEqual([ - [ - undefined, - ElementCallReactionEventType, - { - "m.relates_to": { - event_id: memberEventAlice, - rel_type: "m.reference", - }, - name: "crickets", - emoji: "🦗", + expect(rtcSession.room.client.sendEvent).toHaveBeenCalledWith( + rtcSession.room.roomId, + ElementCallReactionEventType, + { + "m.relates_to": { + event_id: localRtcMember.eventId, + rel_type: "m.reference", }, - ], - ]); + name: "crickets", + emoji: "🦗", + }, + ); }); test("Can close reaction dialog", async () => { const user = userEvent.setup(); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); + const { vm, rtcSession } = getBasicCallViewModelEnvironment([local, alice]); const { getByLabelText, container } = render( - , + , ); await user.click(getByLabelText("common.reactions")); await user.click(getByLabelText("action.show_more")); diff --git a/src/button/ReactionToggleButton.tsx b/src/button/ReactionToggleButton.tsx index 7f231d30..e01d06e8 100644 --- a/src/button/ReactionToggleButton.tsx +++ b/src/button/ReactionToggleButton.tsx @@ -24,8 +24,10 @@ import { import { useTranslation } from "react-i18next"; import { logger } from "matrix-js-sdk/src/logger"; import classNames from "classnames"; +import { useObservableState } from "observable-hooks"; +import { map } from "rxjs"; -import { useReactions } from "../useReactions"; +import { useReactionsSender } from "../reactions/useReactionsSender"; import styles from "./ReactionToggleButton.module.css"; import { type ReactionOption, @@ -33,6 +35,7 @@ import { ReactionsRowSize, } from "../reactions"; import { Modal } from "../Modal"; +import { type CallViewModel } from "../state/CallViewModel"; interface InnerButtonProps extends ComponentPropsWithoutRef<"button"> { raised: boolean; @@ -162,22 +165,27 @@ export function ReactionPopupMenu({ } interface ReactionToggleButtonProps extends ComponentPropsWithoutRef<"button"> { - userId: string; + identifier: string; + vm: CallViewModel; } export function ReactionToggleButton({ - userId, + identifier, + vm, ...props }: ReactionToggleButtonProps): ReactNode { const { t } = useTranslation(); - const { raisedHands, toggleRaisedHand, sendReaction, reactions } = - useReactions(); + const { toggleRaisedHand, sendReaction } = useReactionsSender(); const [busy, setBusy] = useState(false); const [showReactionsMenu, setShowReactionsMenu] = useState(false); const [errorText, setErrorText] = useState(); - const isHandRaised = !!raisedHands[userId]; - const canReact = !reactions[userId]; + const isHandRaised = useObservableState( + vm.handsRaised$.pipe(map((v) => !!v[identifier])), + ); + const canReact = useObservableState( + vm.reactions$.pipe(map((v) => !v[identifier])), + ); useEffect(() => { // Clear whenever the reactions menu state changes. @@ -223,7 +231,7 @@ export function ReactionToggleButton({ setShowReactionsMenu((show) => !show)} - raised={isHandRaised} + raised={!!isHandRaised} open={showReactionsMenu} {...props} /> @@ -237,8 +245,8 @@ export function ReactionToggleButton({ > void sendRelation(reaction)} toggleRaisedHand={wrappedToggleRaisedHand} /> diff --git a/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap b/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap index dd4227e1..4937bae3 100644 --- a/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap +++ b/src/button/__snapshots__/ReactionToggleButton.test.tsx.snap @@ -9,7 +9,7 @@ exports[`Can close reaction dialog 1`] = ` aria-disabled="false" aria-expanded="true" aria-haspopup="true" - aria-labelledby=":r9l:" + aria-labelledby=":rav:" class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59" data-kind="primary" data-size="lg" @@ -43,7 +43,7 @@ exports[`Can fully expand emoji picker 1`] = ` aria-disabled="false" aria-expanded="true" aria-haspopup="true" - aria-labelledby=":r6c:" + aria-labelledby=":r7m:" class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59" data-kind="primary" data-size="lg" @@ -75,8 +75,8 @@ exports[`Can lower hand 1`] = ` aria-expanded="false" aria-haspopup="true" aria-labelledby=":r36:" - class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59" - data-kind="primary" + class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59" + data-kind="secondary" data-size="lg" role="button" tabindex="0" @@ -90,7 +90,9 @@ exports[`Can lower hand 1`] = ` xmlns="http://www.w3.org/2000/svg" > @@ -138,8 +140,8 @@ exports[`Can raise hand 1`] = ` aria-expanded="false" aria-haspopup="true" aria-labelledby=":r1j:" - class="_button_i91xf_17 _has-icon_i91xf_66 _icon-only_i91xf_59" - data-kind="secondary" + class="_button_i91xf_17 raisedButton _has-icon_i91xf_66 _icon-only_i91xf_59" + data-kind="primary" data-size="lg" role="button" tabindex="0" @@ -153,9 +155,7 @@ exports[`Can raise hand 1`] = ` xmlns="http://www.w3.org/2000/svg" > diff --git a/src/reactions/ReactionsReader.test.tsx b/src/reactions/ReactionsReader.test.tsx new file mode 100644 index 00000000..b66550f7 --- /dev/null +++ b/src/reactions/ReactionsReader.test.tsx @@ -0,0 +1,515 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { renderHook } from "@testing-library/react"; +import { afterEach, test, vitest } from "vitest"; +import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc"; +import { + RoomEvent as MatrixRoomEvent, + MatrixEvent, + type IRoomTimelineData, + EventType, + MatrixEventEvent, +} from "matrix-js-sdk/src/matrix"; + +import { ReactionsReader, REACTION_ACTIVE_TIME_MS } from "./ReactionsReader"; +import { + alice, + aliceRtcMember, + local, + localRtcMember, +} from "../utils/test-fixtures"; +import { getBasicRTCSession } from "../utils/test-viewmodel"; +import { withTestScheduler } from "../utils/test"; +import { ElementCallReactionEventType, ReactionSet } from "."; + +afterEach(() => { + vitest.useRealTimers(); +}); + +test("handles a hand raised reaction", () => { + const { rtcSession } = getBasicRTCSession([local, alice]); + const reactionEventId = "$my_event_id:example.org"; + const localTimestamp = new Date(); + withTestScheduler(({ schedule, expectObservable }) => { + renderHook(() => { + const { raisedHands$ } = new ReactionsReader( + rtcSession as unknown as MatrixRTCSession, + ); + schedule("ab", { + a: () => {}, + b: () => { + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: EventType.Reaction, + origin_server_ts: localTimestamp.getTime(), + content: { + "m.relates_to": { + event_id: localRtcMember.eventId, + key: "🖐️", + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + }); + expectObservable(raisedHands$).toBe("ab", { + a: {}, + b: { + [`${localRtcMember.sender}:${localRtcMember.deviceId}`]: { + reactionEventId, + membershipEventId: localRtcMember.eventId, + time: localTimestamp, + }, + }, + }); + }); + }); +}); + +test("handles a redaction", () => { + const { rtcSession } = getBasicRTCSession([local, alice]); + const reactionEventId = "$my_event_id:example.org"; + const localTimestamp = new Date(); + withTestScheduler(({ schedule, expectObservable }) => { + renderHook(() => { + const { raisedHands$ } = new ReactionsReader( + rtcSession as unknown as MatrixRTCSession, + ); + schedule("abc", { + a: () => {}, + b: () => { + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: EventType.Reaction, + origin_server_ts: localTimestamp.getTime(), + content: { + "m.relates_to": { + event_id: localRtcMember.eventId, + key: "🖐️", + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + c: () => { + rtcSession.room.emit( + MatrixRoomEvent.Redaction, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: EventType.RoomRedaction, + redacts: reactionEventId, + }), + rtcSession.room, + undefined, + ); + }, + }); + expectObservable(raisedHands$).toBe("abc", { + a: {}, + b: { + [`${localRtcMember.sender}:${localRtcMember.deviceId}`]: { + reactionEventId, + membershipEventId: localRtcMember.eventId, + time: localTimestamp, + }, + }, + c: {}, + }); + }); + }); +}); + +test("handles waiting for event decryption", () => { + const { rtcSession } = getBasicRTCSession([local, alice]); + const reactionEventId = "$my_event_id:example.org"; + const localTimestamp = new Date(); + withTestScheduler(({ schedule, expectObservable }) => { + renderHook(() => { + const { raisedHands$ } = new ReactionsReader( + rtcSession as unknown as MatrixRTCSession, + ); + schedule("abc", { + a: () => {}, + b: () => { + const encryptedEvent = new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: EventType.Reaction, + origin_server_ts: localTimestamp.getTime(), + content: { + "m.relates_to": { + event_id: localRtcMember.eventId, + key: "🖐️", + }, + }, + }); + // Should ignore encrypted events that are still encrypting + encryptedEvent["decryptionPromise"] = Promise.resolve(); + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + encryptedEvent, + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + c: () => { + rtcSession.room.client.emit( + MatrixEventEvent.Decrypted, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: EventType.Reaction, + origin_server_ts: localTimestamp.getTime(), + content: { + "m.relates_to": { + event_id: localRtcMember.eventId, + key: "🖐️", + }, + }, + }), + ); + }, + }); + expectObservable(raisedHands$).toBe("a-c", { + a: {}, + c: { + [`${localRtcMember.sender}:${localRtcMember.deviceId}`]: { + reactionEventId, + membershipEventId: localRtcMember.eventId, + time: localTimestamp, + }, + }, + }); + }); + }); +}); + +test("hands rejecting events without a proper membership", () => { + const { rtcSession } = getBasicRTCSession([local, alice]); + const reactionEventId = "$my_event_id:example.org"; + const localTimestamp = new Date(); + withTestScheduler(({ schedule, expectObservable }) => { + renderHook(() => { + const { raisedHands$ } = new ReactionsReader( + rtcSession as unknown as MatrixRTCSession, + ); + schedule("ab", { + a: () => {}, + b: () => { + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: EventType.Reaction, + origin_server_ts: localTimestamp.getTime(), + content: { + "m.relates_to": { + event_id: "$not-this-one:example.org", + key: "🖐️", + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + }); + expectObservable(raisedHands$).toBe("a-", { + a: {}, + }); + }); + }); +}); + +test("handles a reaction", () => { + const { rtcSession } = getBasicRTCSession([local, alice]); + const reactionEventId = "$my_event_id:example.org"; + const reaction = ReactionSet[1]; + + vitest.useFakeTimers(); + vitest.setSystemTime(0); + + withTestScheduler(({ schedule, time, expectObservable }) => { + renderHook(() => { + const { reactions$ } = new ReactionsReader( + rtcSession as unknown as MatrixRTCSession, + ); + schedule(`abc`, { + a: () => {}, + b: () => { + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: ElementCallReactionEventType, + content: { + emoji: reaction.emoji, + name: reaction.name, + "m.relates_to": { + event_id: localRtcMember.eventId, + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + c: () => { + vitest.advanceTimersByTime(REACTION_ACTIVE_TIME_MS); + }, + }); + expectObservable(reactions$).toBe( + `ab ${REACTION_ACTIVE_TIME_MS - 1}ms c`, + { + a: {}, + b: { + [`${localRtcMember.sender}:${localRtcMember.deviceId}`]: { + reactionOption: reaction, + expireAfter: new Date(REACTION_ACTIVE_TIME_MS), + }, + }, + // Expect reaction to expire. + c: {}, + }, + ); + }); + }); +}); + +test("ignores bad reaction events", () => { + const { rtcSession } = getBasicRTCSession([local, alice]); + const reactionEventId = "$my_event_id:example.org"; + const reaction = ReactionSet[1]; + + vitest.setSystemTime(0); + + withTestScheduler(({ schedule, expectObservable }) => { + renderHook(() => { + const { reactions$ } = new ReactionsReader( + rtcSession as unknown as MatrixRTCSession, + ); + schedule("ab", { + a: () => {}, + b: () => { + // Missing content + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: ElementCallReactionEventType, + content: {}, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + // Wrong relates event + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: ElementCallReactionEventType, + content: { + emoji: reaction.emoji, + name: reaction.name, + "m.relates_to": { + event_id: "wrong-event", + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + // Wrong rtc member event + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: aliceRtcMember.sender, + type: ElementCallReactionEventType, + content: { + emoji: reaction.emoji, + name: reaction.name, + "m.relates_to": { + event_id: localRtcMember.eventId, + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + // No emoji + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: ElementCallReactionEventType, + content: { + name: reaction.name, + "m.relates_to": { + event_id: localRtcMember.eventId, + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + // Invalid emoji + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: ElementCallReactionEventType, + content: { + emoji: " ", + name: reaction.name, + "m.relates_to": { + event_id: localRtcMember.eventId, + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + }); + expectObservable(reactions$).toBe("a-", { + a: {}, + }); + }); + }); +}); + +test("that reactions cannot be spammed", () => { + const { rtcSession } = getBasicRTCSession([local, alice]); + const reactionEventId = "$my_event_id:example.org"; + const reactionA = ReactionSet[1]; + const reactionB = ReactionSet[2]; + + vitest.useFakeTimers(); + vitest.setSystemTime(0); + + withTestScheduler(({ schedule, expectObservable }) => { + renderHook(() => { + const { reactions$ } = new ReactionsReader( + rtcSession as unknown as MatrixRTCSession, + ); + schedule("abcd", { + a: () => {}, + b: () => { + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: ElementCallReactionEventType, + content: { + emoji: reactionA.emoji, + name: reactionA.name, + "m.relates_to": { + event_id: localRtcMember.eventId, + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + c: () => { + rtcSession.room.emit( + MatrixRoomEvent.Timeline, + new MatrixEvent({ + room_id: rtcSession.room.roomId, + event_id: reactionEventId, + sender: localRtcMember.sender, + type: ElementCallReactionEventType, + content: { + emoji: reactionB.emoji, + name: reactionB.name, + "m.relates_to": { + event_id: localRtcMember.eventId, + }, + }, + }), + rtcSession.room, + undefined, + false, + {} as IRoomTimelineData, + ); + }, + d: () => { + vitest.advanceTimersByTime(REACTION_ACTIVE_TIME_MS); + }, + }); + expectObservable(reactions$).toBe( + `ab- ${REACTION_ACTIVE_TIME_MS - 2}ms d`, + { + a: {}, + b: { + [`${localRtcMember.sender}:${localRtcMember.deviceId}`]: { + reactionOption: reactionA, + expireAfter: new Date(REACTION_ACTIVE_TIME_MS), + }, + }, + d: {}, + }, + ); + }); + }); +}); diff --git a/src/reactions/ReactionsReader.ts b/src/reactions/ReactionsReader.ts new file mode 100644 index 00000000..c0c1009d --- /dev/null +++ b/src/reactions/ReactionsReader.ts @@ -0,0 +1,339 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { + type CallMembership, + MatrixRTCSessionEvent, + type MatrixRTCSession, +} from "matrix-js-sdk/src/matrixrtc"; +import { logger } from "matrix-js-sdk/src/logger"; +import { type MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/matrix"; +import { type ReactionEventContent } from "matrix-js-sdk/src/types"; +import { + RelationType, + EventType, + RoomEvent as MatrixRoomEvent, +} from "matrix-js-sdk/src/matrix"; +import { BehaviorSubject, delay, type Subscription } from "rxjs"; + +import { + ElementCallReactionEventType, + type ECallReactionEventContent, + GenericReaction, + ReactionSet, + type RaisedHandInfo, + type ReactionInfo, +} from "."; + +export const REACTION_ACTIVE_TIME_MS = 3000; + +/** + * Listens for reactions from a RTCSession and populates subjects + * for consumption by the CallViewModel. + * @param rtcSession + */ +export class ReactionsReader { + private readonly raisedHandsSubject$ = new BehaviorSubject< + Record + >({}); + private readonly reactionsSubject$ = new BehaviorSubject< + Record + >({}); + + /** + * The latest set of raised hands. + */ + public readonly raisedHands$ = this.raisedHandsSubject$.asObservable(); + + /** + * The latest set of reactions. + */ + public readonly reactions$ = this.reactionsSubject$.asObservable(); + + private readonly reactionsSub: Subscription; + + public constructor(private readonly rtcSession: MatrixRTCSession) { + // Hide reactions after a given time. + this.reactionsSub = this.reactionsSubject$ + .pipe(delay(REACTION_ACTIVE_TIME_MS)) + .subscribe((reactions) => { + const date = new Date(); + const nextEntries = Object.fromEntries( + Object.entries(reactions).filter(([_, hr]) => hr.expireAfter > date), + ); + if (Object.keys(reactions).length === Object.keys(nextEntries).length) { + return; + } + this.reactionsSubject$.next(nextEntries); + }); + + this.rtcSession.room.on(MatrixRoomEvent.Timeline, this.handleReactionEvent); + this.rtcSession.room.on( + MatrixRoomEvent.Redaction, + this.handleReactionEvent, + ); + this.rtcSession.room.client.on( + MatrixEventEvent.Decrypted, + this.handleReactionEvent, + ); + + // We listen for a local echo to get the real event ID, as timeline events + // may still be sending. + this.rtcSession.room.on( + MatrixRoomEvent.LocalEchoUpdated, + this.handleReactionEvent, + ); + + rtcSession.on( + MatrixRTCSessionEvent.MembershipsChanged, + this.onMembershipsChanged, + ); + + // Run this once to ensure we have fetched the state from the call. + this.onMembershipsChanged([]); + } + + /** + * Fetchest any hand wave reactions by the given sender on the given + * membership event. + * @param membershipEventId + * @param expectedSender + * @returns A MatrixEvent if one was found. + */ + private getLastReactionEvent( + membershipEventId: string, + expectedSender: string, + ): MatrixEvent | undefined { + const relations = this.rtcSession.room.relations.getChildEventsForEvent( + membershipEventId, + RelationType.Annotation, + EventType.Reaction, + ); + const allEvents = relations?.getRelations() ?? []; + return allEvents.find( + (reaction) => + reaction.event.sender === expectedSender && + reaction.getType() === EventType.Reaction && + reaction.getContent()?.["m.relates_to"]?.key === "🖐️", + ); + } + + /** + * Will remove any hand raises by old members, and look for any + * existing hand raises by new members. + * @param oldMemberships Any members who have left the call. + */ + private onMembershipsChanged = (oldMemberships: CallMembership[]): void => { + // Remove any raised hands for users no longer joined to the call. + for (const identifier of Object.keys(this.raisedHandsSubject$.value).filter( + (rhId) => oldMemberships.find((u) => u.sender == rhId), + )) { + this.removeRaisedHand(identifier); + } + + // For each member in the call, check to see if a reaction has + // been raised and adjust. + for (const m of this.rtcSession.memberships) { + if (!m.sender || !m.eventId) { + continue; + } + const identifier = `${m.sender}:${m.deviceId}`; + if ( + this.raisedHandsSubject$.value[identifier] && + this.raisedHandsSubject$.value[identifier].membershipEventId !== + m.eventId + ) { + // Membership event for sender has changed since the hand + // was raised, reset. + this.removeRaisedHand(identifier); + } + const reaction = this.getLastReactionEvent(m.eventId, m.sender); + if (reaction) { + const eventId = reaction?.getId(); + if (!eventId) { + continue; + } + this.addRaisedHand(`${m.sender}:${m.deviceId}`, { + membershipEventId: m.eventId, + reactionEventId: eventId, + time: new Date(reaction.localTimestamp), + }); + } + } + }; + + /** + * Add a raised hand + * @param identifier A userId:deviceId combination. + * @param info The event information. + */ + private addRaisedHand(identifier: string, info: RaisedHandInfo): void { + this.raisedHandsSubject$.next({ + ...this.raisedHandsSubject$.value, + [identifier]: info, + }); + } + + /** + * Remove a raised hand + * @param identifier A userId:deviceId combination. + */ + private removeRaisedHand(identifier: string): void { + this.raisedHandsSubject$.next( + Object.fromEntries( + Object.entries(this.raisedHandsSubject$.value).filter( + ([uId]) => uId !== identifier, + ), + ), + ); + } + + /** + * Handle a new reaction event, validating it's contents and potentially + * updating the hand raise or reaction observers. + * @param event The incoming matrix event, which may or may not be decrypted. + */ + private handleReactionEvent = (event: MatrixEvent): void => { + const room = this.rtcSession.room; + // Decrypted events might come from a different room + if (event.getRoomId() !== room.roomId) return; + // Skip any events that are still sending. + if (event.isSending()) return; + + const sender = event.getSender(); + const reactionEventId = event.getId(); + // Skip any event without a sender or event ID. + if (!sender || !reactionEventId) return; + + room.client + .decryptEventIfNeeded(event) + .catch((e) => logger.warn(`Failed to decrypt ${event.getId()}`, e)); + if (event.isBeingDecrypted() || event.isDecryptionFailure()) return; + + if (event.getType() === ElementCallReactionEventType) { + const content: ECallReactionEventContent = event.getContent(); + + const membershipEventId = content?.["m.relates_to"]?.event_id; + const membershipEvent = this.rtcSession.memberships.find( + (e) => e.eventId === membershipEventId && e.sender === sender, + ); + // Check to see if this reaction was made to a membership event (and the + // sender of the reaction matches the membership) + if (!membershipEvent) { + logger.warn( + `Reaction target was not a membership event for ${sender}, ignoring`, + ); + return; + } + const identifier = `${membershipEvent.sender}:${membershipEvent.deviceId}`; + + if (!content.emoji) { + logger.warn(`Reaction had no emoji from ${reactionEventId}`); + return; + } + + const segment = new Intl.Segmenter(undefined, { + granularity: "grapheme", + }) + .segment(content.emoji) + [Symbol.iterator](); + const emoji = segment.next().value?.segment; + + if (!emoji?.trim()) { + logger.warn( + `Reaction had no emoji from ${reactionEventId} after splitting`, + ); + return; + } + + // One of our custom reactions + const reaction = { + ...GenericReaction, + emoji, + // If we don't find a reaction, we can fallback to the generic sound. + ...ReactionSet.find((r) => r.name === content.name), + }; + + const currentReactions = this.reactionsSubject$.value; + if (currentReactions[identifier]) { + // We've still got a reaction from this user, ignore it to prevent spamming + logger.warn(`Got reaction from ${identifier} but one is still playing`); + return; + } + this.reactionsSubject$.next({ + ...currentReactions, + [identifier]: { + reactionOption: reaction, + expireAfter: new Date(Date.now() + REACTION_ACTIVE_TIME_MS), + }, + }); + } else if (event.getType() === EventType.Reaction) { + const content = event.getContent() as ReactionEventContent; + const membershipEventId = content["m.relates_to"].event_id; + + // Check to see if this reaction was made to a membership event (and the + // sender of the reaction matches the membership) + const membershipEvent = this.rtcSession.memberships.find( + (e) => e.eventId === membershipEventId && e.sender === sender, + ); + if (!membershipEvent) { + logger.warn( + `Reaction target was not a membership event for ${sender}, ignoring`, + ); + return; + } + + if (content?.["m.relates_to"].key === "🖐️") { + this.addRaisedHand( + `${membershipEvent.sender}:${membershipEvent.deviceId}`, + { + reactionEventId, + membershipEventId, + time: new Date(event.localTimestamp), + }, + ); + } + } else if (event.getType() === EventType.RoomRedaction) { + const targetEvent = event.event.redacts; + const targetUser = Object.entries(this.raisedHandsSubject$.value).find( + ([_u, r]) => r.reactionEventId === targetEvent, + )?.[0]; + if (!targetUser) { + // Reaction target was not for us, ignoring + return; + } + this.removeRaisedHand(targetUser); + } + }; + + /** + * Stop listening for events. + */ + public destroy(): void { + this.rtcSession.off( + MatrixRTCSessionEvent.MembershipsChanged, + this.onMembershipsChanged, + ); + this.rtcSession.room.off( + MatrixRoomEvent.Timeline, + this.handleReactionEvent, + ); + this.rtcSession.room.off( + MatrixRoomEvent.Redaction, + this.handleReactionEvent, + ); + this.rtcSession.room.client.off( + MatrixEventEvent.Decrypted, + this.handleReactionEvent, + ); + this.rtcSession.room.off( + MatrixRoomEvent.LocalEchoUpdated, + this.handleReactionEvent, + ); + this.reactionsSub.unsubscribe(); + } +} diff --git a/src/reactions/index.ts b/src/reactions/index.ts index f8253c81..f20b9340 100644 --- a/src/reactions/index.ts +++ b/src/reactions/index.ts @@ -181,3 +181,23 @@ export const ReactionSet: ReactionOption[] = [ }, }, ]; + +export interface RaisedHandInfo { + /** + * Call membership event that was reacted to. + */ + membershipEventId: string; + /** + * Event ID of the reaction itself. + */ + reactionEventId: string; + /** + * The time when the reaction was raised. + */ + time: Date; +} + +export interface ReactionInfo { + expireAfter: Date; + reactionOption: ReactionOption; +} diff --git a/src/reactions/useReactionsSender.tsx b/src/reactions/useReactionsSender.tsx new file mode 100644 index 00000000..cb70bd87 --- /dev/null +++ b/src/reactions/useReactionsSender.tsx @@ -0,0 +1,174 @@ +/* +Copyright 2024 Milton Moura + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { EventType, RelationType } from "matrix-js-sdk/src/matrix"; +import { + createContext, + useContext, + type ReactNode, + useCallback, + useMemo, +} from "react"; +import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; +import { logger } from "matrix-js-sdk/src/logger"; +import { useObservableEagerState } from "observable-hooks"; + +import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships"; +import { useClientState } from "../ClientContext"; +import { ElementCallReactionEventType, type ReactionOption } from "."; +import { type CallViewModel } from "../state/CallViewModel"; + +interface ReactionsSenderContextType { + supportsReactions: boolean; + toggleRaisedHand: () => Promise; + sendReaction: (reaction: ReactionOption) => Promise; +} + +const ReactionsSenderContext = createContext< + ReactionsSenderContextType | undefined +>(undefined); + +export const useReactionsSender = (): ReactionsSenderContextType => { + const context = useContext(ReactionsSenderContext); + if (!context) { + throw new Error("useReactions must be used within a ReactionsProvider"); + } + return context; +}; + +/** + * Provider that handles sending a reaction or hand raised event to a call. + */ +export const ReactionsSenderProvider = ({ + children, + rtcSession, + vm, +}: { + children: ReactNode; + rtcSession: MatrixRTCSession; + vm: CallViewModel; +}): JSX.Element => { + const memberships = useMatrixRTCSessionMemberships(rtcSession); + const clientState = useClientState(); + const supportsReactions = + clientState?.state === "valid" && clientState.supportedFeatures.reactions; + const room = rtcSession.room; + const myUserId = room.client.getUserId(); + const myDeviceId = room.client.getDeviceId(); + + const myMembershipEvent = useMemo( + () => + memberships.find( + (m) => m.sender === myUserId && m.deviceId === myDeviceId, + )?.eventId, + [memberships, myUserId, myDeviceId], + ); + const myMembershipIdentifier = useMemo(() => { + const membership = memberships.find((m) => m.sender === myUserId); + return membership + ? `${membership.sender}:${membership.deviceId}` + : undefined; + }, [memberships, myUserId]); + + const reactions = useObservableEagerState(vm.reactions$); + const myReaction = useMemo( + () => + myMembershipIdentifier !== undefined + ? reactions[myMembershipIdentifier] + : undefined, + [myMembershipIdentifier, reactions], + ); + + const handsRaised = useObservableEagerState(vm.handsRaised$); + const myRaisedHand = useMemo( + () => + myMembershipIdentifier !== undefined + ? handsRaised[myMembershipIdentifier] + : undefined, + [myMembershipIdentifier, handsRaised], + ); + + const toggleRaisedHand = useCallback(async () => { + if (!myMembershipIdentifier) { + return; + } + const myReactionId = myRaisedHand?.reactionEventId; + + if (!myReactionId) { + try { + if (!myMembershipEvent) { + throw new Error("Cannot find own membership event"); + } + const reaction = await room.client.sendEvent( + rtcSession.room.roomId, + EventType.Reaction, + { + "m.relates_to": { + rel_type: RelationType.Annotation, + event_id: myMembershipEvent, + key: "🖐️", + }, + }, + ); + logger.debug("Sent raise hand event", reaction.event_id); + } catch (ex) { + logger.error("Failed to send raised hand", ex); + } + } else { + try { + await room.client.redactEvent(rtcSession.room.roomId, myReactionId); + logger.debug("Redacted raise hand event"); + } catch (ex) { + logger.error("Failed to redact reaction event", myReactionId, ex); + throw ex; + } + } + }, [ + myMembershipEvent, + myMembershipIdentifier, + myRaisedHand, + rtcSession, + room, + ]); + + const sendReaction = useCallback( + async (reaction: ReactionOption) => { + if (!myMembershipIdentifier || myReaction) { + // We're still reacting + return; + } + if (!myMembershipEvent) { + throw new Error("Cannot find own membership event"); + } + await room.client.sendEvent( + rtcSession.room.roomId, + ElementCallReactionEventType, + { + "m.relates_to": { + rel_type: RelationType.Reference, + event_id: myMembershipEvent, + }, + emoji: reaction.emoji, + name: reaction.name, + }, + ); + }, + [myMembershipEvent, myReaction, room, myMembershipIdentifier, rtcSession], + ); + + return ( + + {children} + + ); +}; diff --git a/src/room/CallEventAudioRenderer.test.tsx b/src/room/CallEventAudioRenderer.test.tsx index cc7f4eea..10fcbecf 100644 --- a/src/room/CallEventAudioRenderer.test.tsx +++ b/src/room/CallEventAudioRenderer.test.tsx @@ -15,43 +15,23 @@ import { vitest, afterEach, } from "vitest"; -import { type MatrixClient } from "matrix-js-sdk/src/client"; -import { ConnectionState } from "livekit-client"; -import { BehaviorSubject, of } from "rxjs"; -import { act, type ReactNode } from "react"; -import { - type CallMembership, - type MatrixRTCSession, -} from "matrix-js-sdk/src/matrixrtc"; -import { type RoomMember } from "matrix-js-sdk/src/matrix"; +import { act } from "react"; +import { type CallMembership } from "matrix-js-sdk/src/matrixrtc"; -import { - mockLivekitRoom, - mockLocalParticipant, - mockMatrixRoom, - mockMatrixRoomMember, - mockRemoteParticipant, - mockRtcMembership, - MockRTCSession, -} from "../utils/test"; -import { E2eeType } from "../e2ee/e2eeType"; -import { CallViewModel } from "../state/CallViewModel"; +import { mockRtcMembership } from "../utils/test"; import { CallEventAudioRenderer, MAX_PARTICIPANT_COUNT_FOR_SOUND, } from "./CallEventAudioRenderer"; import { useAudioContext } from "../useAudioContext"; -import { TestReactionsWrapper } from "../utils/testReactions"; import { prefetchSounds } from "../soundUtils"; - -const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC"); -const local = mockMatrixRoomMember(localRtcMember); -const aliceRtcMember = mockRtcMembership("@alice:example.org", "AAAA"); -const alice = mockMatrixRoomMember(aliceRtcMember); -const bobRtcMember = mockRtcMembership("@bob:example.org", "BBBB"); -const localParticipant = mockLocalParticipant({ identity: "" }); -const aliceId = `${alice.userId}:${aliceRtcMember.deviceId}`; -const aliceParticipant = mockRemoteParticipant({ identity: aliceId }); +import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel"; +import { + alice, + aliceRtcMember, + bobRtcMember, + local, +} from "../utils/test-fixtures"; vitest.mock("../useAudioContext"); vitest.mock("../soundUtils"); @@ -78,66 +58,6 @@ beforeEach(() => { }); }); -function TestComponent({ - rtcSession, - vm, -}: { - rtcSession: MockRTCSession; - vm: CallViewModel; -}): ReactNode { - return ( - - - - ); -} - -function getMockEnv( - members: RoomMember[], - initialRemoteRtcMemberships: CallMembership[] = [aliceRtcMember], -): { - vm: CallViewModel; - session: MockRTCSession; - remoteRtcMemberships$: BehaviorSubject; -} { - const matrixRoomMembers = new Map(members.map((p) => [p.userId, p])); - const remoteParticipants$ = of([aliceParticipant]); - const liveKitRoom = mockLivekitRoom( - { localParticipant }, - { remoteParticipants$ }, - ); - const matrixRoom = mockMatrixRoom({ - client: { - getUserId: () => localRtcMember.sender, - getDeviceId: () => localRtcMember.deviceId, - on: vitest.fn(), - off: vitest.fn(), - } as Partial as MatrixClient, - getMember: (userId) => matrixRoomMembers.get(userId) ?? null, - }); - - const remoteRtcMemberships$ = new BehaviorSubject( - initialRemoteRtcMemberships, - ); - - const session = new MockRTCSession( - matrixRoom, - localRtcMember, - ).withMemberships(remoteRtcMemberships$); - - const vm = new CallViewModel( - session as unknown as MatrixRTCSession, - liveKitRoom, - { - kind: E2eeType.PER_PARTICIPANT, - }, - of(ConnectionState.Connected), - ); - return { vm, session, remoteRtcMemberships$ }; -} - /** * We don't want to play a sound when loading the call state * because typically this occurs in two stages. We first join @@ -146,8 +66,12 @@ function getMockEnv( * a noise every time. */ test("plays one sound when entering a call", () => { - const { session, vm, remoteRtcMemberships$ } = getMockEnv([local, alice]); - render(); + const { vm, remoteRtcMemberships$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + render(); + // Joining a call usually means remote participants are added later. act(() => { remoteRtcMemberships$.next([aliceRtcMember, bobRtcMember]); @@ -155,10 +79,12 @@ test("plays one sound when entering a call", () => { expect(playSound).toHaveBeenCalledOnce(); }); -// TODO: Same test? test("plays a sound when a user joins", () => { - const { session, vm, remoteRtcMemberships$ } = getMockEnv([local, alice]); - render(); + const { vm, remoteRtcMemberships$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + render(); act(() => { remoteRtcMemberships$.next([aliceRtcMember, bobRtcMember]); @@ -168,8 +94,11 @@ test("plays a sound when a user joins", () => { }); test("plays a sound when a user leaves", () => { - const { session, vm, remoteRtcMemberships$ } = getMockEnv([local, alice]); - render(); + const { vm, remoteRtcMemberships$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + render(); act(() => { remoteRtcMemberships$.next([]); @@ -185,12 +114,12 @@ test("plays no sound when the participant list is more than the maximum size", ( ); } - const { session, vm, remoteRtcMemberships$ } = getMockEnv( + const { vm, remoteRtcMemberships$ } = getBasicCallViewModelEnvironment( [local, alice], mockRtcMemberships, ); - render(); + render(); expect(playSound).not.toBeCalled(); act(() => { remoteRtcMemberships$.next( @@ -199,3 +128,56 @@ test("plays no sound when the participant list is more than the maximum size", ( }); expect(playSound).toBeCalledWith("left"); }); + +test("plays one sound when a hand is raised", () => { + const { vm, handRaisedSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + render(); + + act(() => { + handRaisedSubject$.next({ + [bobRtcMember.callId]: { + time: new Date(), + membershipEventId: "", + reactionEventId: "", + }, + }); + }); + expect(playSound).toBeCalledWith("raiseHand"); +}); + +test("should not play a sound when a hand raise is retracted", () => { + const { vm, handRaisedSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + render(); + + act(() => { + handRaisedSubject$.next({ + ["foo"]: { + time: new Date(), + membershipEventId: "", + reactionEventId: "", + }, + ["bar"]: { + time: new Date(), + membershipEventId: "", + reactionEventId: "", + }, + }); + }); + expect(playSound).toHaveBeenCalledTimes(2); + act(() => { + handRaisedSubject$.next({ + ["foo"]: { + time: new Date(), + membershipEventId: "", + reactionEventId: "", + }, + }); + }); + expect(playSound).toHaveBeenCalledTimes(2); +}); diff --git a/src/room/CallEventAudioRenderer.tsx b/src/room/CallEventAudioRenderer.tsx index 97270791..afc5132b 100644 --- a/src/room/CallEventAudioRenderer.tsx +++ b/src/room/CallEventAudioRenderer.tsx @@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ -import { type ReactNode, useDeferredValue, useEffect, useMemo } from "react"; +import { type ReactNode, useEffect } from "react"; import { filter, interval, throttle } from "rxjs"; import { type CallViewModel } from "../state/CallViewModel"; @@ -19,7 +19,6 @@ import screenShareStartedOgg from "../sound/screen_share_started.ogg"; import screenShareStartedMp3 from "../sound/screen_share_started.mp3"; import { useAudioContext } from "../useAudioContext"; import { prefetchSounds } from "../soundUtils"; -import { useReactions } from "../useReactions"; import { useLatest } from "../useLatest"; // Do not play any sounds if the participant count has exceeded this @@ -57,19 +56,6 @@ export function CallEventAudioRenderer({ }); const audioEngineRef = useLatest(audioEngineCtx); - const { raisedHands } = useReactions(); - const raisedHandCount = useMemo( - () => Object.keys(raisedHands).length, - [raisedHands], - ); - const previousRaisedHandCount = useDeferredValue(raisedHandCount); - - useEffect(() => { - if (audioEngineRef.current && previousRaisedHandCount < raisedHandCount) { - void audioEngineRef.current.playSound("raiseHand"); - } - }, [audioEngineRef, previousRaisedHandCount, raisedHandCount]); - useEffect(() => { const joinSub = vm.memberChanges$ .pipe( @@ -95,6 +81,10 @@ export function CallEventAudioRenderer({ void audioEngineRef.current?.playSound("left"); }); + const handRaisedSub = vm.newHandRaised$.subscribe(() => { + void audioEngineRef.current?.playSound("raiseHand"); + }); + const screenshareSub = vm.newScreenShare$.subscribe(() => { void audioEngineRef.current?.playSound("screenshareStarted"); }); @@ -102,6 +92,7 @@ export function CallEventAudioRenderer({ return (): void => { joinSub.unsubscribe(); leftSub.unsubscribe(); + handRaisedSub.unsubscribe(); screenshareSub.unsubscribe(); }; }, [audioEngineRef, vm]); diff --git a/src/room/GroupCallView.test.tsx b/src/room/GroupCallView.test.tsx index ea2cc5cf..b1cb53f0 100644 --- a/src/room/GroupCallView.test.tsx +++ b/src/room/GroupCallView.test.tsx @@ -14,6 +14,7 @@ import { JoinRule, type RoomState } from "matrix-js-sdk/src/matrix"; import { Router } from "react-router-dom"; import { createBrowserHistory } from "history"; import userEvent from "@testing-library/user-event"; +import { type RelationsContainer } from "matrix-js-sdk/src/models/relations-container"; import { type MuteStates } from "./MuteStates"; import { prefetchSounds } from "../soundUtils"; @@ -85,6 +86,12 @@ function createGroupCallView(widget: WidgetHelpers | null): { getRoom: (rId) => (rId === roomId ? room : null), } as Partial as MatrixClient; const room = mockMatrixRoom({ + relations: { + getChildEventsForEvent: () => + vitest.mocked({ + getRelations: () => [], + }), + } as unknown as RelationsContainer, client, roomId, getMember: (userId) => roomMembers.get(userId) ?? null, diff --git a/src/room/GroupCallView.tsx b/src/room/GroupCallView.tsx index 3ea6a9c2..cf587fcd 100644 --- a/src/room/GroupCallView.tsx +++ b/src/room/GroupCallView.tsx @@ -366,7 +366,7 @@ export const GroupCallView: FC = ({ = (props) => { useEffect(() => { if (livekitRoom !== undefined) { + const reactionsReader = new ReactionsReader(props.rtcSession); const vm = new CallViewModel( props.rtcSession, livekitRoom, props.e2eeSystem, connStateObservable$, + reactionsReader.raisedHands$, + reactionsReader.reactions$, ); setVm(vm); - return (): void => vm.destroy(); + return (): void => { + vm.destroy(); + reactionsReader.destroy(); + }; } }, [props.rtcSession, livekitRoom, props.e2eeSystem, connStateObservable$]); @@ -142,14 +152,14 @@ export const ActiveCall: FC = (props) => { return ( - + - + ); }; @@ -182,7 +192,8 @@ export const InCallView: FC = ({ connState, onShareClick, }) => { - const { supportsReactions, sendReaction, toggleRaisedHand } = useReactions(); + const { supportsReactions, sendReaction, toggleRaisedHand } = + useReactionsSender(); useWakeLock(); @@ -551,9 +562,10 @@ export const InCallView: FC = ({ if (supportsReactions) { buttons.push( , ); @@ -653,8 +665,8 @@ export const InCallView: FC = ({ {renderContent()} - - + + {footer} {layout.type !== "pip" && ( <> diff --git a/src/room/ReactionAudioRenderer.test.tsx b/src/room/ReactionAudioRenderer.test.tsx index afa2c6ff..ec71571c 100644 --- a/src/room/ReactionAudioRenderer.test.tsx +++ b/src/room/ReactionAudioRenderer.test.tsx @@ -19,11 +19,6 @@ import { import { TooltipProvider } from "@vector-im/compound-web"; import { act, type ReactNode } from "react"; -import { - MockRoom, - MockRTCSession, - TestReactionsWrapper, -} from "../utils/testReactions"; import { ReactionsAudioRenderer } from "./ReactionAudioRenderer"; import { playReactionsSound, @@ -32,30 +27,20 @@ import { import { useAudioContext } from "../useAudioContext"; import { GenericReaction, ReactionSet } from "../reactions"; import { prefetchSounds } from "../soundUtils"; +import { type CallViewModel } from "../state/CallViewModel"; +import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel"; +import { + alice, + aliceRtcMember, + bobRtcMember, + local, + localRtcMember, +} from "../utils/test-fixtures"; -const memberUserIdAlice = "@alice:example.org"; -const memberUserIdBob = "@bob:example.org"; -const memberUserIdCharlie = "@charlie:example.org"; -const memberEventAlice = "$membership-alice:example.org"; -const memberEventBob = "$membership-bob:example.org"; -const memberEventCharlie = "$membership-charlie:example.org"; - -const membership: Record = { - [memberEventAlice]: memberUserIdAlice, - [memberEventBob]: memberUserIdBob, - [memberEventCharlie]: memberUserIdCharlie, -}; - -function TestComponent({ - rtcSession, -}: { - rtcSession: MockRTCSession; -}): ReactNode { +function TestComponent({ vm }: { vm: CallViewModel }): ReactNode { return ( - - - + ); } @@ -88,20 +73,19 @@ beforeEach(() => { }); test("preloads all audio elements", () => { + const { vm } = getBasicCallViewModelEnvironment([local, alice]); playReactionsSound.setValue(true); - const rtcSession = new MockRTCSession( - new MockRoom(memberUserIdAlice), - membership, - ); - render(); + render(); expect(prefetchSounds).toHaveBeenCalledOnce(); }); test("will play an audio sound when there is a reaction", () => { + const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); playReactionsSound.setValue(true); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - render(); + render(); // Find the first reaction with a sound effect const chosenReaction = ReactionSet.find((r) => !!r.sound); @@ -111,16 +95,23 @@ test("will play an audio sound when there is a reaction", () => { ); } act(() => { - room.testSendReaction(memberEventAlice, chosenReaction, membership); + reactionsSubject$.next({ + [aliceRtcMember.deviceId]: { + reactionOption: chosenReaction, + expireAfter: new Date(0), + }, + }); }); expect(playSound).toHaveBeenCalledWith(chosenReaction.name); }); test("will play the generic audio sound when there is soundless reaction", () => { + const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); playReactionsSound.setValue(true); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - render(); + render(); // Find the first reaction with a sound effect const chosenReaction = ReactionSet.find((r) => !r.sound); @@ -130,17 +121,23 @@ test("will play the generic audio sound when there is soundless reaction", () => ); } act(() => { - room.testSendReaction(memberEventAlice, chosenReaction, membership); + reactionsSubject$.next({ + [aliceRtcMember.deviceId]: { + reactionOption: chosenReaction, + expireAfter: new Date(0), + }, + }); }); expect(playSound).toHaveBeenCalledWith(GenericReaction.name); }); test("will play multiple audio sounds when there are multiple different reactions", () => { + const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); playReactionsSound.setValue(true); - - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - render(); + render(); // Find the first reaction with a sound effect const [reaction1, reaction2] = ReactionSet.filter((r) => !!r.sound); @@ -150,9 +147,20 @@ test("will play multiple audio sounds when there are multiple different reaction ); } act(() => { - room.testSendReaction(memberEventAlice, reaction1, membership); - room.testSendReaction(memberEventBob, reaction2, membership); - room.testSendReaction(memberEventCharlie, reaction1, membership); + reactionsSubject$.next({ + [aliceRtcMember.deviceId]: { + reactionOption: reaction1, + expireAfter: new Date(0), + }, + [bobRtcMember.deviceId]: { + reactionOption: reaction2, + expireAfter: new Date(0), + }, + [localRtcMember.deviceId]: { + reactionOption: reaction1, + expireAfter: new Date(0), + }, + }); }); expect(playSound).toHaveBeenCalledWith(reaction1.name); expect(playSound).toHaveBeenCalledWith(reaction2.name); diff --git a/src/room/ReactionAudioRenderer.tsx b/src/room/ReactionAudioRenderer.tsx index be24a5d6..1b33d65a 100644 --- a/src/room/ReactionAudioRenderer.tsx +++ b/src/room/ReactionAudioRenderer.tsx @@ -5,14 +5,14 @@ SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ -import { type ReactNode, useDeferredValue, useEffect, useState } from "react"; +import { type ReactNode, useEffect, useState } from "react"; -import { useReactions } from "../useReactions"; import { playReactionsSound, useSetting } from "../settings/settings"; import { GenericReaction, ReactionSet } from "../reactions"; import { useAudioContext } from "../useAudioContext"; import { prefetchSounds } from "../soundUtils"; import { useLatest } from "../useLatest"; +import { type CallViewModel } from "../state/CallViewModel"; const soundMap = Object.fromEntries([ ...ReactionSet.filter((v) => v.sound !== undefined).map((v) => [ @@ -22,8 +22,11 @@ const soundMap = Object.fromEntries([ [GenericReaction.name, GenericReaction.sound], ]); -export function ReactionsAudioRenderer(): ReactNode { - const { reactions } = useReactions(); +export function ReactionsAudioRenderer({ + vm, +}: { + vm: CallViewModel; +}): ReactNode { const [shouldPlay] = useSetting(playReactionsSound); const [soundCache, setSoundCache] = useState { if (!shouldPlay || soundCache) { @@ -46,26 +48,19 @@ export function ReactionsAudioRenderer(): ReactNode { }, [soundCache, shouldPlay]); useEffect(() => { - if (!shouldPlay || !audioEngineRef.current) { - return; - } - const oldReactionSet = new Set( - Object.values(oldReactions).map((r) => r.name), - ); - for (const reactionName of new Set( - Object.values(reactions).map((r) => r.name), - )) { - if (oldReactionSet.has(reactionName)) { - // Don't replay old reactions - return; + const sub = vm.audibleReactions$.subscribe((newReactions) => { + for (const reactionName of newReactions) { + if (soundMap[reactionName]) { + void audioEngineRef.current?.playSound(reactionName); + } else { + // Fallback sounds. + void audioEngineRef.current?.playSound("generic"); + } } - if (soundMap[reactionName]) { - void audioEngineRef.current.playSound(reactionName); - } else { - // Fallback sounds. - void audioEngineRef.current.playSound("generic"); - } - } - }, [audioEngineRef, shouldPlay, oldReactions, reactions]); + }); + return (): void => { + sub.unsubscribe(); + }; + }, [vm, audioEngineRef]); return null; } diff --git a/src/room/ReactionsOverlay.test.tsx b/src/room/ReactionsOverlay.test.tsx index 5c3f8bf9..77ec77f8 100644 --- a/src/room/ReactionsOverlay.test.tsx +++ b/src/room/ReactionsOverlay.test.tsx @@ -7,44 +7,18 @@ Please see LICENSE in the repository root for full details. import { render } from "@testing-library/react"; import { expect, test, afterEach } from "vitest"; -import { TooltipProvider } from "@vector-im/compound-web"; -import { act, type ReactNode } from "react"; +import { act } from "react"; -import { - MockRoom, - MockRTCSession, - TestReactionsWrapper, -} from "../utils/testReactions"; import { showReactions } from "../settings/settings"; import { ReactionsOverlay } from "./ReactionsOverlay"; import { ReactionSet } from "../reactions"; - -const memberUserIdAlice = "@alice:example.org"; -const memberUserIdBob = "@bob:example.org"; -const memberUserIdCharlie = "@charlie:example.org"; -const memberEventAlice = "$membership-alice:example.org"; -const memberEventBob = "$membership-bob:example.org"; -const memberEventCharlie = "$membership-charlie:example.org"; - -const membership: Record = { - [memberEventAlice]: memberUserIdAlice, - [memberEventBob]: memberUserIdBob, - [memberEventCharlie]: memberUserIdCharlie, -}; - -function TestComponent({ - rtcSession, -}: { - rtcSession: MockRTCSession; -}): ReactNode { - return ( - - - - - - ); -} +import { + local, + alice, + aliceRtcMember, + bobRtcMember, +} from "../utils/test-fixtures"; +import { getBasicCallViewModelEnvironment } from "../utils/test-viewmodel"; afterEach(() => { showReactions.setValue(showReactions.defaultValue); @@ -52,22 +26,26 @@ afterEach(() => { test("defaults to showing no reactions", () => { showReactions.setValue(true); - const rtcSession = new MockRTCSession( - new MockRoom(memberUserIdAlice), - membership, - ); - const { container } = render(); + const { vm } = getBasicCallViewModelEnvironment([local, alice]); + const { container } = render(); expect(container.getElementsByTagName("span")).toHaveLength(0); }); test("shows a reaction when sent", () => { showReactions.setValue(true); + const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + const { getByRole } = render(); const reaction = ReactionSet[0]; - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - const { getByRole } = render(); act(() => { - room.testSendReaction(memberEventAlice, reaction, membership); + reactionsSubject$.next({ + [aliceRtcMember.deviceId]: { + reactionOption: reaction, + expireAfter: new Date(0), + }, + }); }); const span = getByRole("presentation"); expect(getByRole("presentation")).toBeTruthy(); @@ -77,29 +55,45 @@ test("shows a reaction when sent", () => { test("shows two of the same reaction when sent", () => { showReactions.setValue(true); const reaction = ReactionSet[0]; - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - const { getAllByRole } = render(); + const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + const { getAllByRole } = render(); act(() => { - room.testSendReaction(memberEventAlice, reaction, membership); - }); - act(() => { - room.testSendReaction(memberEventBob, reaction, membership); + reactionsSubject$.next({ + [aliceRtcMember.deviceId]: { + reactionOption: reaction, + expireAfter: new Date(0), + }, + [bobRtcMember.deviceId]: { + reactionOption: reaction, + expireAfter: new Date(0), + }, + }); }); expect(getAllByRole("presentation")).toHaveLength(2); }); test("shows two different reactions when sent", () => { showReactions.setValue(true); - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); const [reactionA, reactionB] = ReactionSet; - const { getAllByRole } = render(); + const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + const { getAllByRole } = render(); act(() => { - room.testSendReaction(memberEventAlice, reactionA, membership); - }); - act(() => { - room.testSendReaction(memberEventBob, reactionB, membership); + reactionsSubject$.next({ + [aliceRtcMember.deviceId]: { + reactionOption: reactionA, + expireAfter: new Date(0), + }, + [bobRtcMember.deviceId]: { + reactionOption: reactionB, + expireAfter: new Date(0), + }, + }); }); const [reactionElementA, reactionElementB] = getAllByRole("presentation"); expect(reactionElementA.innerHTML).toEqual(reactionA.emoji); @@ -109,11 +103,18 @@ test("shows two different reactions when sent", () => { test("hides reactions when reaction animations are disabled", () => { showReactions.setValue(false); const reaction = ReactionSet[0]; - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); + const { vm, reactionsSubject$ } = getBasicCallViewModelEnvironment([ + local, + alice, + ]); + const { container } = render(); act(() => { - room.testSendReaction(memberEventAlice, reaction, membership); + reactionsSubject$.next({ + [aliceRtcMember.deviceId]: { + reactionOption: reaction, + expireAfter: new Date(0), + }, + }); }); - const { container } = render(); expect(container.getElementsByTagName("span")).toHaveLength(0); }); diff --git a/src/room/ReactionsOverlay.tsx b/src/room/ReactionsOverlay.tsx index 2f8daba5..e642a16c 100644 --- a/src/room/ReactionsOverlay.tsx +++ b/src/room/ReactionsOverlay.tsx @@ -5,33 +5,17 @@ SPDX-License-Identifier: AGPL-3.0-only Please see LICENSE in the repository root for full details. */ -import { type ReactNode, useMemo } from "react"; +import { type ReactNode } from "react"; +import { useObservableState } from "observable-hooks"; -import { useReactions } from "../useReactions"; -import { - showReactions as showReactionsSetting, - useSetting, -} from "../settings/settings"; import styles from "./ReactionsOverlay.module.css"; +import { type CallViewModel } from "../state/CallViewModel"; -export function ReactionsOverlay(): ReactNode { - const { reactions } = useReactions(); - const [showReactions] = useSetting(showReactionsSetting); - const reactionsIcons = useMemo( - () => - showReactions - ? Object.entries(reactions).map(([sender, { emoji }]) => ({ - sender, - emoji, - startX: Math.ceil(Math.random() * 80) + 10, - })) - : [], - [showReactions, reactions], - ); - +export function ReactionsOverlay({ vm }: { vm: CallViewModel }): ReactNode { + const reactionsIcons = useObservableState(vm.visibleReactions$); return (

- {reactionsIcons.map(({ sender, emoji, startX }) => ( + {reactionsIcons?.map(({ sender, emoji, startX }) => ( []>, connectionState$: Observable, speaking: Map>, - continuation: (vm: CallViewModel) => void, + continuation: ( + vm: CallViewModel, + subjects: { raisedHands$: BehaviorSubject> }, + ) => void, ): void { const room = mockMatrixRoom({ client: { @@ -235,6 +240,8 @@ function withCallViewModel( { remoteParticipants$ }, ); + const raisedHands$ = new BehaviorSubject>({}); + const vm = new CallViewModel( rtcSession as unknown as MatrixRTCSession, liveKitRoom, @@ -242,6 +249,8 @@ function withCallViewModel( kind: E2eeType.PER_PARTICIPANT, }, connectionState$, + raisedHands$, + new BehaviorSubject({}), ); onTestFinished(() => { @@ -252,7 +261,7 @@ function withCallViewModel( roomEventSelectorSpy!.mockRestore(); }); - continuation(vm); + continuation(vm, { raisedHands$: raisedHands$ }); } test("participants are retained during a focus switch", () => { @@ -782,3 +791,62 @@ it("should show at least one tile per MatrixRTCSession", () => { ); }); }); + +it("should rank raised hands above video feeds and below speakers and presenters", () => { + withTestScheduler(({ schedule, expectObservable }) => { + // There should always be one tile for each MatrixRTCSession + const expectedLayoutMarbles = "ab"; + + withCallViewModel( + of([aliceParticipant, bobParticipant]), + of([aliceRtcMember, bobRtcMember]), + of(ConnectionState.Connected), + new Map(), + (vm, { raisedHands$ }) => { + schedule("ab", { + a: () => { + // We imagine that only two tiles (the first two) will be visible on screen at a time + vm.layout$.subscribe((layout) => { + if (layout.type === "grid") { + layout.setVisibleTiles(2); + } + }); + }, + b: () => { + raisedHands$.next({ + [`${bobRtcMember.sender}:${bobRtcMember.deviceId}`]: { + time: new Date(), + reactionEventId: "", + membershipEventId: "", + }, + }); + }, + }); + expectObservable(summarizeLayout$(vm.layout$)).toBe( + expectedLayoutMarbles, + { + a: { + type: "grid", + spotlight: undefined, + grid: [ + "local:0", + "@alice:example.org:AAAA:0", + "@bob:example.org:BBBB:0", + ], + }, + b: { + type: "grid", + spotlight: undefined, + grid: [ + "local:0", + // Bob shifts up! + "@bob:example.org:BBBB:0", + "@alice:example.org:AAAA:0", + ], + }, + }, + ); + }, + ); + }); +}); diff --git a/src/state/CallViewModel.ts b/src/state/CallViewModel.ts index 5f1526fd..0c3b80db 100644 --- a/src/state/CallViewModel.ts +++ b/src/state/CallViewModel.ts @@ -69,7 +69,12 @@ import { } from "./MediaViewModel"; import { accumulate, finalizeValue } from "../utils/observable"; import { ObservableScope } from "./ObservableScope"; -import { duplicateTiles, showNonMemberTiles } from "../settings/settings"; +import { + duplicateTiles, + playReactionsSound, + showReactions, + showNonMemberTiles, +} from "../settings/settings"; import { isFirefox } from "../Platform"; import { setPipEnabled$ } from "../controls"; import { @@ -82,6 +87,11 @@ import { spotlightExpandedLayout } from "./SpotlightExpandedLayout"; import { oneOnOneLayout } from "./OneOnOneLayout"; import { pipLayout } from "./PipLayout"; import { type EncryptionSystem } from "../e2ee/sharedKeyManagement"; +import { + type RaisedHandInfo, + type ReactionInfo, + type ReactionOption, +} from "../reactions"; import { observeSpeaker$ } from "./observeSpeaker"; import { shallowEquals } from "../utils/array"; @@ -210,6 +220,10 @@ enum SortingBin { * Participants that have been speaking recently. */ Speakers, + /** + * Participants that have their hand raised. + */ + HandRaised, /** * Participants with video. */ @@ -244,6 +258,8 @@ class UserMedia { participant: LocalParticipant | RemoteParticipant | undefined, encryptionSystem: EncryptionSystem, livekitRoom: LivekitRoom, + handRaised$: Observable, + reaction$: Observable, ) { this.participant$ = new BehaviorSubject(participant); @@ -254,6 +270,8 @@ class UserMedia { this.participant$.asObservable() as Observable, encryptionSystem, livekitRoom, + handRaised$, + reaction$, ); } else { this.vm = new RemoteUserMediaViewModel( @@ -264,6 +282,8 @@ class UserMedia { >, encryptionSystem, livekitRoom, + handRaised$, + reaction$, ); } @@ -473,6 +493,8 @@ export class CallViewModel extends ViewModel { let livekitParticipantId = rtcMember.sender + ":" + rtcMember.deviceId; + const matrixIdentifier = `${rtcMember.sender}:${rtcMember.deviceId}`; + let participant: | LocalParticipant | RemoteParticipant @@ -522,6 +544,12 @@ export class CallViewModel extends ViewModel { participant, this.encryptionSystem, this.livekitRoom, + this.handsRaised$.pipe( + map((v) => v[matrixIdentifier]?.time ?? null), + ), + this.reactions$.pipe( + map((v) => v[matrixIdentifier] ?? undefined), + ), ), ]; @@ -574,6 +602,8 @@ export class CallViewModel extends ViewModel { participant, this.encryptionSystem, this.livekitRoom, + of(null), + of(null), ), ]; } @@ -681,11 +711,12 @@ export class CallViewModel extends ViewModel { m.speaker$, m.presenter$, m.vm.videoEnabled$, + m.vm.handRaised$, m.vm instanceof LocalUserMediaViewModel ? m.vm.alwaysShow$ : of(false), ], - (speaker, presenter, video, alwaysShow) => { + (speaker, presenter, video, handRaised, alwaysShow) => { let bin: SortingBin; if (m.vm.local) bin = alwaysShow @@ -693,6 +724,7 @@ export class CallViewModel extends ViewModel { : SortingBin.SelfNotAlwaysShown; else if (presenter) bin = SortingBin.Presenters; else if (speaker) bin = SortingBin.Speakers; + else if (handRaised) bin = SortingBin.HandRaised; else if (video) bin = SortingBin.Video; else bin = SortingBin.NoVideo; @@ -1170,6 +1202,77 @@ export class CallViewModel extends ViewModel { }), this.scope.state(), ); + + public readonly reactions$ = this.reactionsSubject$.pipe( + map((v) => + Object.fromEntries( + Object.entries(v).map(([a, { reactionOption }]) => [a, reactionOption]), + ), + ), + ); + + public readonly handsRaised$ = this.handsRaisedSubject$.pipe(); + + /** + * Emits an array of reactions that should be visible on the screen. + */ + public readonly visibleReactions$ = showReactions.value$.pipe( + switchMap((show) => (show ? this.reactions$ : of({}))), + scan< + Record, + { sender: string; emoji: string; startX: number }[] + >((acc, latest) => { + const newSet: { sender: string; emoji: string; startX: number }[] = []; + for (const [sender, reaction] of Object.entries(latest)) { + const startX = + acc.find((v) => v.sender === sender && v.emoji)?.startX ?? + Math.ceil(Math.random() * 80) + 10; + newSet.push({ sender, emoji: reaction.emoji, startX }); + } + return newSet; + }, []), + ); + + /** + * Emits an array of reactions that should be played. + */ + public readonly audibleReactions$ = playReactionsSound.value$.pipe( + switchMap((show) => + show ? this.reactions$ : of>({}), + ), + map((reactions) => Object.values(reactions).map((v) => v.name)), + scan( + (acc, latest) => { + return { + playing: latest.filter( + (v) => acc.playing.includes(v) || acc.newSounds.includes(v), + ), + newSounds: latest.filter( + (v) => !acc.playing.includes(v) && !acc.newSounds.includes(v), + ), + }; + }, + { playing: [], newSounds: [] }, + ), + map((v) => v.newSounds), + ); + + /** + * Emits an event every time a new hand is raised in + * the call. + */ + public readonly newHandRaised$ = this.handsRaised$.pipe( + map((v) => Object.keys(v).length), + scan( + (acc, newValue) => ({ + value: newValue, + playSounds: newValue > acc.value, + }), + { value: 0, playSounds: false }, + ), + filter((v) => v.playSounds), + ); + /** * Emits an event every time a new screenshare is started in * the call. @@ -1192,6 +1295,12 @@ export class CallViewModel extends ViewModel { private readonly livekitRoom: LivekitRoom, private readonly encryptionSystem: EncryptionSystem, private readonly connectionState$: Observable, + private readonly handsRaisedSubject$: Observable< + Record + >, + private readonly reactionsSubject$: Observable< + Record + >, ) { super(); } diff --git a/src/state/MediaViewModel.ts b/src/state/MediaViewModel.ts index 8100a50d..b57b6f15 100644 --- a/src/state/MediaViewModel.ts +++ b/src/state/MediaViewModel.ts @@ -51,6 +51,7 @@ import { alwaysShowSelf } from "../settings/settings"; import { accumulate } from "../utils/observable"; import { type EncryptionSystem } from "../e2ee/sharedKeyManagement"; import { E2eeType } from "../e2ee/e2eeType"; +import { type ReactionOption } from "../reactions"; // TODO: Move this naming logic into the view model export function useDisplayName(vm: MediaViewModel): string { @@ -371,6 +372,8 @@ abstract class BaseUserMediaViewModel extends BaseMediaViewModel { participant$: Observable, encryptionSystem: EncryptionSystem, livekitRoom: LivekitRoom, + public readonly handRaised$: Observable, + public readonly reaction$: Observable, ) { super( id, @@ -437,8 +440,18 @@ export class LocalUserMediaViewModel extends BaseUserMediaViewModel { participant$: Observable, encryptionSystem: EncryptionSystem, livekitRoom: LivekitRoom, + handRaised$: Observable, + reaction$: Observable, ) { - super(id, member, participant$, encryptionSystem, livekitRoom); + super( + id, + member, + participant$, + encryptionSystem, + livekitRoom, + handRaised$, + reaction$, + ); } } @@ -498,8 +511,18 @@ export class RemoteUserMediaViewModel extends BaseUserMediaViewModel { participant$: Observable, encryptionSystem: EncryptionSystem, livekitRoom: LivekitRoom, + handRaised$: Observable, + reaction$: Observable, ) { - super(id, member, participant$, encryptionSystem, livekitRoom); + super( + id, + member, + participant$, + encryptionSystem, + livekitRoom, + handRaised$, + reaction$, + ); // Sync the local volume with LiveKit combineLatest([ diff --git a/src/tile/GridTile.test.tsx b/src/tile/GridTile.test.tsx index d7edf3b3..16875c33 100644 --- a/src/tile/GridTile.test.tsx +++ b/src/tile/GridTile.test.tsx @@ -15,7 +15,8 @@ import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSess import { GridTile } from "./GridTile"; import { mockRtcMembership, withRemoteMedia } from "../utils/test"; import { GridTileViewModel } from "../state/TileViewModel"; -import { ReactionsProvider } from "../useReactions"; +import { ReactionsSenderProvider } from "../reactions/useReactionsSender"; +import type { CallViewModel } from "../state/CallViewModel"; global.IntersectionObserver = class MockIntersectionObserver { public observe(): void {} @@ -44,14 +45,19 @@ test("GridTile is accessible", async () => { off: () => {}, client: { getUserId: () => null, + getDeviceId: () => null, on: () => {}, off: () => {}, }, }, memberships: [], } as unknown as MatrixRTCSession; + const cVm = { + reactions$: of({}), + handsRaised$: of({}), + } as Partial as CallViewModel; const { container } = render( - + {}} @@ -59,7 +65,7 @@ test("GridTile is accessible", async () => { targetHeight={200} showSpeakingIndicators /> - , + , ); expect(await axe(container)).toHaveNoViolations(); // Name should be visible diff --git a/src/tile/GridTile.tsx b/src/tile/GridTile.tsx index 8c6b2d9b..9eb775d0 100644 --- a/src/tile/GridTile.tsx +++ b/src/tile/GridTile.tsx @@ -34,7 +34,7 @@ import { ToggleMenuItem, Menu, } from "@vector-im/compound-web"; -import { useObservableEagerState } from "observable-hooks"; +import { useObservableEagerState, useObservableState } from "observable-hooks"; import styles from "./GridTile.module.css"; import { @@ -48,8 +48,7 @@ import { MediaView } from "./MediaView"; import { useLatest } from "../useLatest"; import { type GridTileViewModel } from "../state/TileViewModel"; import { useMergedRefs } from "../useMergedRefs"; -import { useReactions } from "../useReactions"; -import { type ReactionOption } from "../reactions"; +import { useReactionsSender } from "../reactions/useReactionsSender"; interface TileProps { className?: string; @@ -82,6 +81,7 @@ const UserMediaTile = forwardRef( }, ref, ) => { + const { toggleRaisedHand } = useReactionsSender(); const { t } = useTranslation(); const video = useObservableEagerState(vm.video$); const unencryptedWarning = useObservableEagerState(vm.unencryptedWarning$); @@ -97,7 +97,8 @@ const UserMediaTile = forwardRef( }, [vm], ); - const { raisedHands, toggleRaisedHand, reactions } = useReactions(); + const handRaised = useObservableState(vm.handRaised$); + const reaction = useObservableState(vm.reaction$); const AudioIcon = locallyMuted ? VolumeOffSolidIcon @@ -124,9 +125,6 @@ const UserMediaTile = forwardRef( ); - const handRaised: Date | undefined = raisedHands[vm.member?.userId ?? ""]; - const currentReaction: ReactionOption | undefined = - reactions[vm.member?.userId ?? ""]; const raisedHandOnClick = vm.local ? (): void => void toggleRaisedHand() : undefined; @@ -144,7 +142,7 @@ const UserMediaTile = forwardRef( videoFit={cropVideo ? "cover" : "contain"} className={classNames(className, styles.tile, { [styles.speaking]: showSpeaking, - [styles.handRaised]: !showSpeaking && !!handRaised, + [styles.handRaised]: !showSpeaking && handRaised, })} nameTagLeadingIcon={ ( {menu} } - raisedHandTime={handRaised} - currentReaction={currentReaction} + raisedHandTime={handRaised ?? undefined} + currentReaction={reaction ?? undefined} raisedHandOnClick={raisedHandOnClick} localParticipant={vm.local} {...props} diff --git a/src/useReactions.test.tsx b/src/useReactions.test.tsx deleted file mode 100644 index 56edd7e1..00000000 --- a/src/useReactions.test.tsx +++ /dev/null @@ -1,173 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only -Please see LICENSE in the repository root for full details. -*/ - -import { render } from "@testing-library/react"; -import { act, type FC } from "react"; -import { describe, expect, test } from "vitest"; -import { RoomEvent } from "matrix-js-sdk/src/matrix"; - -import { useReactions } from "./useReactions"; -import { - createHandRaisedReaction, - createRedaction, - MockRoom, - MockRTCSession, - TestReactionsWrapper, -} from "./utils/testReactions"; - -const memberUserIdAlice = "@alice:example.org"; -const memberEventAlice = "$membership-alice:example.org"; -const memberUserIdBob = "@bob:example.org"; -const memberEventBob = "$membership-bob:example.org"; - -const membership: Record = { - [memberEventAlice]: memberUserIdAlice, - [memberEventBob]: memberUserIdBob, - "$membership-charlie:example.org": "@charlie:example.org", -}; - -/** - * Test explanation. - * This test suite checks that the useReactions hook appropriately reacts - * to new reactions, redactions and membership changesin the room. There is - * a large amount of test structure used to construct a mock environment. - */ - -const TestComponent: FC = () => { - const { raisedHands } = useReactions(); - return ( -
-
    - {Object.entries(raisedHands).map(([userId, date]) => ( -
  • - {userId} - -
  • - ))} -
-
- ); -}; - -describe("useReactions", () => { - test("starts with an empty list", () => { - const rtcSession = new MockRTCSession( - new MockRoom(memberUserIdAlice), - membership, - ); - const { queryByRole } = render( - - - , - ); - expect(queryByRole("list")?.children).to.have.lengthOf(0); - }); - test("handles incoming raised hand", async () => { - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - const { queryByRole } = render( - - - , - ); - await act(() => room.testSendHandRaise(memberEventAlice, membership)); - expect(queryByRole("list")?.children).to.have.lengthOf(1); - await act(() => room.testSendHandRaise(memberEventBob, membership)); - expect(queryByRole("list")?.children).to.have.lengthOf(2); - }); - test("handles incoming unraised hand", async () => { - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - const { queryByRole } = render( - - - , - ); - const reactionEventId = await act(() => - room.testSendHandRaise(memberEventAlice, membership), - ); - expect(queryByRole("list")?.children).to.have.lengthOf(1); - await act(() => - room.emit( - RoomEvent.Redaction, - createRedaction(memberUserIdAlice, reactionEventId), - room, - undefined, - ), - ); - expect(queryByRole("list")?.children).to.have.lengthOf(0); - }); - test("handles loading prior raised hand events", () => { - const room = new MockRoom(memberUserIdAlice, [ - createHandRaisedReaction(memberEventAlice, membership), - ]); - const rtcSession = new MockRTCSession(room, membership); - const { queryByRole } = render( - - - , - ); - expect(queryByRole("list")?.children).to.have.lengthOf(1); - }); - // If the membership event changes for a user, we want to remove - // the raised hand event. - test("will remove reaction when a member leaves the call", () => { - const room = new MockRoom(memberUserIdAlice, [ - createHandRaisedReaction(memberEventAlice, membership), - ]); - const rtcSession = new MockRTCSession(room, membership); - const { queryByRole } = render( - - - , - ); - expect(queryByRole("list")?.children).to.have.lengthOf(1); - act(() => rtcSession.testRemoveMember(memberUserIdAlice)); - expect(queryByRole("list")?.children).to.have.lengthOf(0); - }); - test("will remove reaction when a member joins via a new event", () => { - const room = new MockRoom(memberUserIdAlice, [ - createHandRaisedReaction(memberEventAlice, membership), - ]); - const rtcSession = new MockRTCSession(room, membership); - const { queryByRole } = render( - - - , - ); - expect(queryByRole("list")?.children).to.have.lengthOf(1); - // Simulate leaving and rejoining - act(() => { - rtcSession.testRemoveMember(memberUserIdAlice); - rtcSession.testAddMember(memberUserIdAlice); - }); - expect(queryByRole("list")?.children).to.have.lengthOf(0); - }); - test("ignores invalid sender for historic event", () => { - const room = new MockRoom(memberUserIdAlice, [ - createHandRaisedReaction(memberEventAlice, memberUserIdBob), - ]); - const rtcSession = new MockRTCSession(room, membership); - const { queryByRole } = render( - - - , - ); - expect(queryByRole("list")?.children).to.have.lengthOf(0); - }); - test("ignores invalid sender for new event", async () => { - const room = new MockRoom(memberUserIdAlice); - const rtcSession = new MockRTCSession(room, membership); - const { queryByRole } = render( - - - , - ); - await act(() => room.testSendHandRaise(memberEventAlice, memberUserIdBob)); - expect(queryByRole("list")?.children).to.have.lengthOf(0); - }); -}); diff --git a/src/useReactions.tsx b/src/useReactions.tsx deleted file mode 100644 index 7289187a..00000000 --- a/src/useReactions.tsx +++ /dev/null @@ -1,405 +0,0 @@ -/* -Copyright 2024 Milton Moura - -SPDX-License-Identifier: AGPL-3.0-only -Please see LICENSE in the repository root for full details. -*/ - -import { - EventType, - type MatrixEvent, - RelationType, - RoomEvent as MatrixRoomEvent, - MatrixEventEvent, -} from "matrix-js-sdk/src/matrix"; -import { type ReactionEventContent } from "matrix-js-sdk/src/types"; -import { - createContext, - useContext, - useState, - type ReactNode, - useCallback, - useEffect, - useMemo, -} from "react"; -import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession"; -import { logger } from "matrix-js-sdk/src/logger"; - -import { useMatrixRTCSessionMemberships } from "./useMatrixRTCSessionMemberships"; -import { useClientState } from "./ClientContext"; -import { - type ECallReactionEventContent, - ElementCallReactionEventType, - GenericReaction, - type ReactionOption, - ReactionSet, -} from "./reactions"; -import { useLatest } from "./useLatest"; - -interface ReactionsContextType { - raisedHands: Record; - supportsReactions: boolean; - reactions: Record; - toggleRaisedHand: () => Promise; - sendReaction: (reaction: ReactionOption) => Promise; -} - -const ReactionsContext = createContext( - undefined, -); - -interface RaisedHandInfo { - /** - * Call membership event that was reacted to. - */ - membershipEventId: string; - /** - * Event ID of the reaction itself. - */ - reactionEventId: string; - /** - * The time when the reaction was raised. - */ - time: Date; -} - -const REACTION_ACTIVE_TIME_MS = 3000; - -export const useReactions = (): ReactionsContextType => { - const context = useContext(ReactionsContext); - if (!context) { - throw new Error("useReactions must be used within a ReactionsProvider"); - } - return context; -}; - -/** - * Provider that handles raised hand reactions for a given `rtcSession`. - */ -export const ReactionsProvider = ({ - children, - rtcSession, -}: { - children: ReactNode; - rtcSession: MatrixRTCSession; -}): JSX.Element => { - const [raisedHands, setRaisedHands] = useState< - Record - >({}); - const memberships = useMatrixRTCSessionMemberships(rtcSession); - const clientState = useClientState(); - const supportsReactions = - clientState?.state === "valid" && clientState.supportedFeatures.reactions; - const room = rtcSession.room; - const myUserId = room.client.getUserId(); - - const [reactions, setReactions] = useState>( - {}, - ); - - // Reduce the data down for the consumers. - const resultRaisedHands = useMemo( - () => - Object.fromEntries( - Object.entries(raisedHands).map(([uid, data]) => [uid, data.time]), - ), - [raisedHands], - ); - const addRaisedHand = useCallback((userId: string, info: RaisedHandInfo) => { - setRaisedHands((prevRaisedHands) => ({ - ...prevRaisedHands, - [userId]: info, - })); - }, []); - - const removeRaisedHand = useCallback((userId: string) => { - setRaisedHands( - ({ [userId]: _removed, ...remainingRaisedHands }) => remainingRaisedHands, - ); - }, []); - - // This effect will check the state whenever the membership of the session changes. - useEffect(() => { - // Fetches the first reaction for a given event. - const getLastReactionEvent = ( - eventId: string, - expectedSender: string, - ): MatrixEvent | undefined => { - const relations = room.relations.getChildEventsForEvent( - eventId, - RelationType.Annotation, - EventType.Reaction, - ); - const allEvents = relations?.getRelations() ?? []; - return allEvents.find( - (reaction) => - reaction.event.sender === expectedSender && - reaction.getType() === EventType.Reaction && - reaction.getContent()?.["m.relates_to"]?.key === "🖐️", - ); - }; - - // Remove any raised hands for users no longer joined to the call. - for (const userId of Object.keys(raisedHands).filter( - (rhId) => !memberships.find((u) => u.sender == rhId), - )) { - removeRaisedHand(userId); - } - - // For each member in the call, check to see if a reaction has - // been raised and adjust. - for (const m of memberships) { - if (!m.sender || !m.eventId) { - continue; - } - if ( - raisedHands[m.sender] && - raisedHands[m.sender].membershipEventId !== m.eventId - ) { - // Membership event for sender has changed since the hand - // was raised, reset. - removeRaisedHand(m.sender); - } - const reaction = getLastReactionEvent(m.eventId, m.sender); - if (reaction) { - const eventId = reaction?.getId(); - if (!eventId) { - continue; - } - addRaisedHand(m.sender, { - membershipEventId: m.eventId, - reactionEventId: eventId, - time: new Date(reaction.localTimestamp), - }); - } - } - // Ignoring raisedHands here because we don't want to trigger each time the raised - // hands set is updated. - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [room, memberships, myUserId, addRaisedHand, removeRaisedHand]); - - const latestMemberships = useLatest(memberships); - const latestRaisedHands = useLatest(raisedHands); - - const myMembership = useMemo( - () => memberships.find((m) => m.sender === myUserId)?.eventId, - [memberships, myUserId], - ); - - // This effect handles any *live* reaction/redactions in the room. - useEffect(() => { - const reactionTimeouts = new Set(); - const handleReactionEvent = (event: MatrixEvent): void => { - // Decrypted events might come from a different room - if (event.getRoomId() !== room.roomId) return; - // Skip any events that are still sending. - if (event.isSending()) return; - - const sender = event.getSender(); - const reactionEventId = event.getId(); - // Skip any event without a sender or event ID. - if (!sender || !reactionEventId) return; - - room.client - .decryptEventIfNeeded(event) - .catch((e) => logger.warn(`Failed to decrypt ${event.getId()}`, e)); - if (event.isBeingDecrypted() || event.isDecryptionFailure()) return; - - if (event.getType() === ElementCallReactionEventType) { - const content: ECallReactionEventContent = event.getContent(); - - const membershipEventId = content?.["m.relates_to"]?.event_id; - // Check to see if this reaction was made to a membership event (and the - // sender of the reaction matches the membership) - if ( - !latestMemberships.current.some( - (e) => e.eventId === membershipEventId && e.sender === sender, - ) - ) { - logger.warn( - `Reaction target was not a membership event for ${sender}, ignoring`, - ); - return; - } - - if (!content.emoji) { - logger.warn(`Reaction had no emoji from ${reactionEventId}`); - return; - } - - const segment = new Intl.Segmenter(undefined, { - granularity: "grapheme", - }) - .segment(content.emoji) - [Symbol.iterator](); - const emoji = segment.next().value?.segment; - - if (!emoji) { - logger.warn( - `Reaction had no emoji from ${reactionEventId} after splitting`, - ); - return; - } - - // One of our custom reactions - const reaction = { - ...GenericReaction, - emoji, - // If we don't find a reaction, we can fallback to the generic sound. - ...ReactionSet.find((r) => r.name === content.name), - }; - - setReactions((reactions) => { - if (reactions[sender]) { - // We've still got a reaction from this user, ignore it to prevent spamming - return reactions; - } - const timeout = window.setTimeout(() => { - // Clear the reaction after some time. - setReactions(({ [sender]: _unused, ...remaining }) => remaining); - reactionTimeouts.delete(timeout); - }, REACTION_ACTIVE_TIME_MS); - reactionTimeouts.add(timeout); - return { - ...reactions, - [sender]: reaction, - }; - }); - } else if (event.getType() === EventType.Reaction) { - const content = event.getContent() as ReactionEventContent; - const membershipEventId = content["m.relates_to"].event_id; - - // Check to see if this reaction was made to a membership event (and the - // sender of the reaction matches the membership) - if ( - !latestMemberships.current.some( - (e) => e.eventId === membershipEventId && e.sender === sender, - ) - ) { - logger.warn( - `Reaction target was not a membership event for ${sender}, ignoring`, - ); - return; - } - - if (content?.["m.relates_to"].key === "🖐️") { - addRaisedHand(sender, { - reactionEventId, - membershipEventId, - time: new Date(event.localTimestamp), - }); - } - } else if (event.getType() === EventType.RoomRedaction) { - const targetEvent = event.event.redacts; - const targetUser = Object.entries(latestRaisedHands.current).find( - ([_u, r]) => r.reactionEventId === targetEvent, - )?.[0]; - if (!targetUser) { - // Reaction target was not for us, ignoring - return; - } - removeRaisedHand(targetUser); - } - }; - - room.on(MatrixRoomEvent.Timeline, handleReactionEvent); - room.on(MatrixRoomEvent.Redaction, handleReactionEvent); - room.client.on(MatrixEventEvent.Decrypted, handleReactionEvent); - - // We listen for a local echo to get the real event ID, as timeline events - // may still be sending. - room.on(MatrixRoomEvent.LocalEchoUpdated, handleReactionEvent); - - return (): void => { - room.off(MatrixRoomEvent.Timeline, handleReactionEvent); - room.off(MatrixRoomEvent.Redaction, handleReactionEvent); - room.client.off(MatrixEventEvent.Decrypted, handleReactionEvent); - room.off(MatrixRoomEvent.LocalEchoUpdated, handleReactionEvent); - reactionTimeouts.forEach((t) => clearTimeout(t)); - // If we're clearing timeouts, we also clear all reactions. - setReactions({}); - }; - }, [ - room, - addRaisedHand, - removeRaisedHand, - latestMemberships, - latestRaisedHands, - ]); - - const toggleRaisedHand = useCallback(async () => { - if (!myUserId) { - return; - } - const myReactionId = raisedHands[myUserId]?.reactionEventId; - - if (!myReactionId) { - try { - if (!myMembership) { - throw new Error("Cannot find own membership event"); - } - const reaction = await room.client.sendEvent( - rtcSession.room.roomId, - EventType.Reaction, - { - "m.relates_to": { - rel_type: RelationType.Annotation, - event_id: myMembership, - key: "🖐️", - }, - }, - ); - logger.debug("Sent raise hand event", reaction.event_id); - } catch (ex) { - logger.error("Failed to send raised hand", ex); - } - } else { - try { - await room.client.redactEvent(rtcSession.room.roomId, myReactionId); - logger.debug("Redacted raise hand event"); - } catch (ex) { - logger.error("Failed to redact reaction event", myReactionId, ex); - throw ex; - } - } - }, [myMembership, myUserId, raisedHands, rtcSession, room]); - - const sendReaction = useCallback( - async (reaction: ReactionOption) => { - if (!myUserId || reactions[myUserId]) { - // We're still reacting - return; - } - if (!myMembership) { - throw new Error("Cannot find own membership event"); - } - await room.client.sendEvent( - rtcSession.room.roomId, - ElementCallReactionEventType, - { - "m.relates_to": { - rel_type: RelationType.Reference, - event_id: myMembership, - }, - emoji: reaction.emoji, - name: reaction.name, - }, - ); - }, - [myMembership, reactions, room, myUserId, rtcSession], - ); - - return ( - - {children} - - ); -}; diff --git a/src/utils/test-fixtures.ts b/src/utils/test-fixtures.ts new file mode 100644 index 00000000..a105b5f7 --- /dev/null +++ b/src/utils/test-fixtures.ts @@ -0,0 +1,24 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { + mockRtcMembership, + mockMatrixRoomMember, + mockRemoteParticipant, + mockLocalParticipant, +} from "./test"; + +export const aliceRtcMember = mockRtcMembership("@alice:example.org", "AAAA"); +export const alice = mockMatrixRoomMember(aliceRtcMember); +export const aliceId = `${alice.userId}:${aliceRtcMember.deviceId}`; +export const aliceParticipant = mockRemoteParticipant({ identity: aliceId }); + +export const localRtcMember = mockRtcMembership("@carol:example.org", "CCCC"); +export const local = mockMatrixRoomMember(localRtcMember); +export const localParticipant = mockLocalParticipant({ identity: "" }); + +export const bobRtcMember = mockRtcMembership("@bob:example.org", "BBBB"); diff --git a/src/utils/test-viewmodel.ts b/src/utils/test-viewmodel.ts new file mode 100644 index 00000000..799ea1a1 --- /dev/null +++ b/src/utils/test-viewmodel.ts @@ -0,0 +1,150 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { ConnectionState } from "livekit-client"; +import { type MatrixClient } from "matrix-js-sdk/src/client"; +import { type RoomMember } from "matrix-js-sdk/src/matrix"; +import { + type CallMembership, + type MatrixRTCSession, +} from "matrix-js-sdk/src/matrixrtc"; +import { BehaviorSubject, of } from "rxjs"; +import { vitest } from "vitest"; +import { type RelationsContainer } from "matrix-js-sdk/src/models/relations-container"; +import EventEmitter from "events"; + +import { E2eeType } from "../e2ee/e2eeType"; +import { CallViewModel } from "../state/CallViewModel"; +import { mockLivekitRoom, mockMatrixRoom, MockRTCSession } from "./test"; +import { + aliceRtcMember, + aliceParticipant, + localParticipant, + localRtcMember, +} from "./test-fixtures"; +import { type RaisedHandInfo, type ReactionInfo } from "../reactions"; + +export function getBasicRTCSession( + members: RoomMember[], + initialRemoteRtcMemberships: CallMembership[] = [aliceRtcMember], +): { + rtcSession: MockRTCSession; + remoteRtcMemberships$: BehaviorSubject; +} { + const matrixRoomId = "!myRoomId:example.com"; + const matrixRoomMembers = new Map(members.map((p) => [p.userId, p])); + + const roomEmitter = new EventEmitter(); + const clientEmitter = new EventEmitter(); + const matrixRoom = mockMatrixRoom({ + relations: { + getChildEventsForEvent: vitest.fn(), + } as Partial as RelationsContainer, + client: { + getUserId: () => localRtcMember.sender, + getDeviceId: () => localRtcMember.deviceId, + sendEvent: vitest.fn().mockResolvedValue({ event_id: "$fake:event" }), + redactEvent: vitest.fn().mockResolvedValue({ event_id: "$fake:event" }), + decryptEventIfNeeded: vitest.fn().mockResolvedValue(undefined), + on: vitest + .fn() + .mockImplementation( + (eventName: string, fn: (...args: unknown[]) => void) => { + clientEmitter.on(eventName, fn); + }, + ), + emit: (eventName: string, ...args: unknown[]) => + clientEmitter.emit(eventName, ...args), + off: vitest + .fn() + .mockImplementation( + (eventName: string, fn: (...args: unknown[]) => void) => { + clientEmitter.off(eventName, fn); + }, + ), + } as Partial as MatrixClient, + getMember: (userId) => matrixRoomMembers.get(userId) ?? null, + roomId: matrixRoomId, + on: vitest + .fn() + .mockImplementation( + (eventName: string, fn: (...args: unknown[]) => void) => { + roomEmitter.on(eventName, fn); + }, + ), + emit: (eventName: string, ...args: unknown[]) => + roomEmitter.emit(eventName, ...args), + off: vitest + .fn() + .mockImplementation( + (eventName: string, fn: (...args: unknown[]) => void) => { + roomEmitter.off(eventName, fn); + }, + ), + }); + + const remoteRtcMemberships$ = new BehaviorSubject( + initialRemoteRtcMemberships, + ); + + const rtcSession = new MockRTCSession( + matrixRoom, + localRtcMember, + ).withMemberships(remoteRtcMemberships$); + + return { + rtcSession, + remoteRtcMemberships$, + }; +} + +/** + * Construct a basic CallViewModel to test components that make use of it. + * @param members + * @param initialRemoteRtcMemberships + * @returns + */ +export function getBasicCallViewModelEnvironment( + members: RoomMember[], + initialRemoteRtcMemberships: CallMembership[] = [aliceRtcMember], +): { + vm: CallViewModel; + remoteRtcMemberships$: BehaviorSubject; + rtcSession: MockRTCSession; + handRaisedSubject$: BehaviorSubject>; + reactionsSubject$: BehaviorSubject>; +} { + const { rtcSession, remoteRtcMemberships$ } = getBasicRTCSession( + members, + initialRemoteRtcMemberships, + ); + const handRaisedSubject$ = new BehaviorSubject({}); + const reactionsSubject$ = new BehaviorSubject({}); + + const remoteParticipants$ = of([aliceParticipant]); + const liveKitRoom = mockLivekitRoom( + { localParticipant }, + { remoteParticipants$ }, + ); + const vm = new CallViewModel( + rtcSession as unknown as MatrixRTCSession, + liveKitRoom, + { + kind: E2eeType.PER_PARTICIPANT, + }, + of(ConnectionState.Connected), + handRaisedSubject$, + reactionsSubject$, + ); + return { + vm, + remoteRtcMemberships$, + rtcSession, + handRaisedSubject$: handRaisedSubject$, + reactionsSubject$: reactionsSubject$, + }; +} diff --git a/src/utils/test.ts b/src/utils/test.ts index db0d8959..41e85ba3 100644 --- a/src/utils/test.ts +++ b/src/utils/test.ts @@ -28,6 +28,7 @@ import { type RemoteTrackPublication, type Room as LivekitRoom, } from "livekit-client"; +import { randomUUID } from "crypto"; import { LocalUserMediaViewModel, @@ -132,6 +133,7 @@ export function mockRtcMembership( }; const event = new MatrixEvent({ sender: typeof user === "string" ? user : user.userId, + event_id: `$-ev-${randomUUID()}:example.org`, }); return new CallMembership(event, data); } @@ -203,6 +205,8 @@ export async function withLocalMedia( kind: E2eeType.PER_PARTICIPANT, }, mockLivekitRoom({ localParticipant }), + of(null), + of(null), ); try { await continuation(vm); @@ -239,6 +243,8 @@ export async function withRemoteMedia( kind: E2eeType.PER_PARTICIPANT, }, mockLivekitRoom({}, { remoteParticipants$: of([remoteParticipant]) }), + of(null), + of(null), ); try { await continuation(vm); diff --git a/src/utils/testReactions.tsx b/src/utils/testReactions.tsx deleted file mode 100644 index 6fad030c..00000000 --- a/src/utils/testReactions.tsx +++ /dev/null @@ -1,214 +0,0 @@ -/* -Copyright 2024 New Vector Ltd. - -SPDX-License-Identifier: AGPL-3.0-only -Please see LICENSE in the repository root for full details. -*/ - -import { type PropsWithChildren, type ReactNode } from "react"; -import { randomUUID } from "crypto"; -import EventEmitter from "events"; -import { type MatrixClient } from "matrix-js-sdk/src/client"; -import { EventType, RoomEvent, RelationType } from "matrix-js-sdk/src/matrix"; -import { - MatrixEvent, - EventTimeline, - EventTimelineSet, - type Room, -} from "matrix-js-sdk/src/matrix"; -import { - type MatrixRTCSession, - MatrixRTCSessionEvent, -} from "matrix-js-sdk/src/matrixrtc"; - -import { ReactionsProvider } from "../useReactions"; -import { - type ECallReactionEventContent, - ElementCallReactionEventType, - type ReactionOption, -} from "../reactions"; - -export const TestReactionsWrapper = ({ - rtcSession, - children, -}: PropsWithChildren<{ - rtcSession: MockRTCSession | MatrixRTCSession; -}>): ReactNode => { - return ( - - {children} - - ); -}; - -export class MockRTCSession extends EventEmitter { - public memberships: { - sender: string; - eventId: string; - createdTs: () => Date; - }[]; - - public constructor( - public readonly room: MockRoom, - membership: Record, - ) { - super(); - this.memberships = Object.entries(membership).map(([eventId, sender]) => ({ - sender, - eventId, - createdTs: (): Date => new Date(), - })); - } - - public testRemoveMember(userId: string): void { - this.memberships = this.memberships.filter((u) => u.sender !== userId); - this.emit(MatrixRTCSessionEvent.MembershipsChanged); - } - - public testAddMember(sender: string): void { - this.memberships.push({ - sender, - eventId: `!fake-${randomUUID()}:event`, - createdTs: (): Date => new Date(), - }); - this.emit(MatrixRTCSessionEvent.MembershipsChanged); - } -} - -export function createHandRaisedReaction( - parentMemberEvent: string, - membershipOrOverridenSender: Record | string, -): MatrixEvent { - return new MatrixEvent({ - sender: - typeof membershipOrOverridenSender === "string" - ? membershipOrOverridenSender - : membershipOrOverridenSender[parentMemberEvent], - type: EventType.Reaction, - origin_server_ts: new Date().getTime(), - content: { - "m.relates_to": { - key: "🖐️", - event_id: parentMemberEvent, - }, - }, - event_id: randomUUID(), - }); -} - -export function createRedaction( - sender: string, - reactionEventId: string, -): MatrixEvent { - return new MatrixEvent({ - sender, - type: EventType.RoomRedaction, - origin_server_ts: new Date().getTime(), - redacts: reactionEventId, - content: {}, - event_id: randomUUID(), - }); -} - -export class MockRoom extends EventEmitter { - public readonly testSentEvents: Parameters[] = []; - public readonly testRedactedEvents: Parameters< - MatrixClient["redactEvent"] - >[] = []; - - public constructor( - private readonly ownUserId: string, - private readonly existingRelations: MatrixEvent[] = [], - ) { - super(); - } - - public get client(): MatrixClient { - return { - getUserId: (): string => this.ownUserId, - sendEvent: async ( - ...props: Parameters - ): ReturnType => { - this.testSentEvents.push(props); - return Promise.resolve({ event_id: randomUUID() }); - }, - redactEvent: async ( - ...props: Parameters - ): ReturnType => { - this.testRedactedEvents.push(props); - return Promise.resolve({ event_id: randomUUID() }); - }, - decryptEventIfNeeded: async () => {}, - on() { - return this; - }, - off() { - return this; - }, - } as unknown as MatrixClient; - } - - public get relations(): Room["relations"] { - return { - getChildEventsForEvent: (membershipEventId: string) => ({ - getRelations: (): MatrixEvent[] => { - return this.existingRelations.filter( - (r) => - r.getContent()["m.relates_to"]?.event_id === membershipEventId, - ); - }, - }), - } as unknown as Room["relations"]; - } - - public testSendHandRaise( - parentMemberEvent: string, - membershipOrOverridenSender: Record | string, - ): string { - const evt = createHandRaisedReaction( - parentMemberEvent, - membershipOrOverridenSender, - ); - this.emit(RoomEvent.Timeline, evt, this, undefined, false, { - timeline: new EventTimeline(new EventTimelineSet(undefined)), - }); - return evt.getId()!; - } - - public testSendReaction( - parentMemberEvent: string, - reaction: ReactionOption, - membershipOrOverridenSender: Record | string, - ): string { - const evt = new MatrixEvent({ - sender: - typeof membershipOrOverridenSender === "string" - ? membershipOrOverridenSender - : membershipOrOverridenSender[parentMemberEvent], - type: ElementCallReactionEventType, - origin_server_ts: new Date().getTime(), - content: { - "m.relates_to": { - rel_type: RelationType.Reference, - event_id: parentMemberEvent, - }, - emoji: reaction.emoji, - name: reaction.name, - } satisfies ECallReactionEventContent, - event_id: randomUUID(), - }); - - this.emit(RoomEvent.Timeline, evt, this, undefined, false, { - timeline: new EventTimeline(new EventTimelineSet(undefined)), - }); - return evt.getId()!; - } - - public getMember(): void { - return; - } - - public testGetAsMatrixRoom(): Room { - return this as unknown as Room; - } -} diff --git a/vitest.config.js b/vitest.config.js index 098a0b0c..68fef5be 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -16,7 +16,12 @@ export default defineConfig((configEnv) => coverage: { reporter: ["html", "json"], include: ["src/"], - exclude: ["src/**/*.{d,test}.{ts,tsx}", "src/utils/test.ts"], + exclude: [ + "src/**/*.{d,test}.{ts,tsx}", + "src/utils/test.ts", + "src/utils/test-viewmodel.ts", + "src/utils/test-fixtures.ts", + ], }, }, }), From 6776c2af351f4f8cf4cb3e9c8539f8ad7ba1724d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:00:32 +0100 Subject: [PATCH 06/11] Update Compound (#2895) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 279 ++++++++++++++++++++++-------------------------------- 1 file changed, 113 insertions(+), 166 deletions(-) diff --git a/yarn.lock b/yarn.lock index d3b8da40..419dc141 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1790,10 +1790,10 @@ dependencies: "@floating-ui/dom" "^1.0.0" -"@floating-ui/react@^0.26.24": - version "0.26.28" - resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.28.tgz#93f44ebaeb02409312e9df9507e83aab4a8c0dc7" - integrity sha512-yORQuuAtVpiRjpMhdc0wJj06b9JFjrYF4qp96j++v2NBpbi6SEGF7donUJ3TMieerQ6qVkAv1tgr7L4r5roTqw== +"@floating-ui/react@^0.27.0": + version "0.27.2" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.27.2.tgz#901a04e93061c427d45b69a29c99f641a8b3a7bc" + integrity sha512-k/yP6a9K9QwhLfIu87iUZxCH6XN5z5j/VUHHq0dEnbZYY2Y9jz68E/LXFtK8dkiaYltS2WYohnyKC0VcwVneVg== dependencies: "@floating-ui/react-dom" "^2.1.2" "@floating-ui/utils" "^0.2.8" @@ -2335,32 +2335,17 @@ resolved "https://registry.yarnpkg.com/@radix-ui/number/-/number-1.1.0.tgz#1e95610461a09cdf8bb05c152e76ca1278d5da46" integrity sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ== -"@radix-ui/primitive@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" - integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== - "@radix-ui/primitive@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3" integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA== -"@radix-ui/react-arrow@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a" - integrity sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw== +"@radix-ui/react-arrow@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.1.tgz#2103721933a8bfc6e53bbfbdc1aaad5fc8ba0dd7" + integrity sha512-NaVpZfmv8SKeZbn4ijN2V3jlHA9ngBG16VnIIm22nUR0Yk8KUALyBxT3KYEUnNuch9sTE8UTsS3whzBgKOL30w== dependencies: - "@radix-ui/react-primitive" "2.0.0" - -"@radix-ui/react-collection@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" - integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw== - dependencies: - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-context" "1.1.0" - "@radix-ui/react-primitive" "2.0.0" - "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-collection@1.1.1": version "1.1.1" @@ -2372,33 +2357,23 @@ "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-slot" "1.1.1" -"@radix-ui/react-compose-refs@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" - integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== - "@radix-ui/react-compose-refs@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec" integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw== "@radix-ui/react-context-menu@^2.2.1": - version "2.2.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.2.tgz#efcddc559fc3011721b65148f062d04027f76c7a" - integrity sha512-99EatSTpW+hRYHt7m8wdDlLtkmTovEe8Z/hnxUPV+SKuuNL5HWNhQI4QSdjZqNSgXHay2z4M3Dym73j9p2Gx5Q== + version "2.2.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.4.tgz#8fe70ffdfec25ada35a60d100496cace1b75a977" + integrity sha512-ap4wdGwK52rJxGkwukU1NrnEodsUFQIooANKu+ey7d6raQ2biTcEf8za1zr0mgFHieevRTB2nK4dJeN8pTAZGQ== dependencies: - "@radix-ui/primitive" "1.1.0" + "@radix-ui/primitive" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-menu" "2.1.2" - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-menu" "2.1.4" + "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" -"@radix-ui/react-context@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" - integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== - "@radix-ui/react-context@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.1.tgz#82074aa83a472353bb22e86f11bcbd1c61c4c71a" @@ -2429,17 +2404,6 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== -"@radix-ui/react-dismissable-layer@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.1.tgz#cbdcb739c5403382bdde5f9243042ba643883396" - integrity sha512-QSxg29lfr/xcev6kSz7MAlmDnzbP1eI/Dwn3Tp1ip0KT5CUELsxkekFEMVBEoykI3oV39hKT4TKZzBNMbcTZYQ== - dependencies: - "@radix-ui/primitive" "1.1.0" - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-primitive" "2.0.0" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-escape-keydown" "1.1.0" - "@radix-ui/react-dismissable-layer@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.2.tgz#771594b202f32bc8ffeb278c565f10c513814aee" @@ -2451,17 +2415,28 @@ "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-escape-keydown" "1.1.0" -"@radix-ui/react-dropdown-menu@^2.1.1": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.2.tgz#acc49577130e3c875ef0133bd1e271ea3392d924" - integrity sha512-GVZMR+eqK8/Kes0a36Qrv+i20bAPXSn8rCBTHx30w+3ECnR5o3xixAlqcVaYvLeyKUsm0aqyhWfmUcqufM8nYA== +"@radix-ui/react-dismissable-layer@1.1.3": + version "1.1.3" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz#4ee0f0f82d53bf5bd9db21665799bb0d1bad5ed8" + integrity sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg== dependencies: - "@radix-ui/primitive" "1.1.0" - "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-primitive" "2.0.1" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" + +"@radix-ui/react-dropdown-menu@^2.1.1": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.4.tgz#5e1f453296dd9ae99224a26c36851832d26cf507" + integrity sha512-iXU1Ab5ecM+yEepGAWK8ZhMyKX4ubFdCNtol4sT9D0OVErG9PNElfx3TQhjw7n7BC5nFVz68/5//clWy+8TXzA== + dependencies: + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-menu" "2.1.2" - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-menu" "2.1.4" + "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-use-controllable-state" "1.1.0" "@radix-ui/react-focus-guards@1.1.1": @@ -2469,15 +2444,6 @@ resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.1.tgz#8635edd346304f8b42cae86b05912b61aef27afe" integrity sha512-pSIwfrT1a6sIoDASCSpFwOasEwKTZWDw/iBdtnqKO7v6FeOzYJ7U53cPzYFVR3geGGXgVHaH+CdngrrAzqUGxg== -"@radix-ui/react-focus-scope@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz#ebe2891a298e0a33ad34daab2aad8dea31caf0b2" - integrity sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA== - dependencies: - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-primitive" "2.0.0" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-focus-scope@1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz#5c602115d1db1c4fcfa0fae4c3b09bb8919853cb" @@ -2488,16 +2454,16 @@ "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-form@^0.1.0": - version "0.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-form/-/react-form-0.1.0.tgz#7111a6aa54a2bde0d11fb72643f9ffc871ac58ad" - integrity sha512-1/oVYPDjbFILOLIarcGcMKo+y6SbTVT/iUKVEw59CF4offwZgBgC3ZOeSBewjqU0vdA6FWTPWTN63obj55S/tQ== + version "0.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-form/-/react-form-0.1.1.tgz#eb9241a02f8d43f3a7e9cb448ab99a5926a29690" + integrity sha512-Ah2TBvzl2trb4DL9DQtyUJgAUfq/djMN7j5CHzdpbdR3W7OL8N4JcJgE80cXMf3ssCE+8yg0zFQoJ0srxqfsFA== dependencies: - "@radix-ui/primitive" "1.1.0" - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-context" "1.1.0" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-label" "2.1.0" - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-label" "2.1.1" + "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-id@1.1.0": version "1.1.0" @@ -2506,61 +2472,53 @@ dependencies: "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/react-label@2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.0.tgz#3aa2418d70bb242be37c51ff5e51a2adcbc372e3" - integrity sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw== +"@radix-ui/react-label@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.1.1.tgz#f30bd577b26873c638006e4f65761d4c6b80566d" + integrity sha512-UUw5E4e/2+4kFMH7+YxORXGWggtY6sM8WIwh5RZchhLuUg2H1hc98Py+pr8HMz6rdaYrK2t296ZEjYLOCO5uUw== dependencies: - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-primitive" "2.0.1" -"@radix-ui/react-menu@2.1.2": - version "2.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.2.tgz#91f6815845a4298dde775563ed2d80b7ad667899" - integrity sha512-lZ0R4qR2Al6fZ4yCCZzu/ReTFrylHFxIqy7OezIpWF4bL0o9biKo0pFIvkaew3TyZ9Fy5gYVrR5zCGZBVbO1zg== +"@radix-ui/react-menu@2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.4.tgz#ac7aec296f29608206a7c6ef6335d8f102edaa95" + integrity sha512-BnOgVoL6YYdHAG6DtXONaR29Eq4nvbi8rutrV/xlr3RQCMMb3yqP85Qiw/3NReozrSW+4dfLkK+rc1hb4wPU/A== dependencies: - "@radix-ui/primitive" "1.1.0" - "@radix-ui/react-collection" "1.1.0" - "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" "@radix-ui/react-direction" "1.1.0" - "@radix-ui/react-dismissable-layer" "1.1.1" + "@radix-ui/react-dismissable-layer" "1.1.3" "@radix-ui/react-focus-guards" "1.1.1" - "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.1" "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-popper" "1.2.0" - "@radix-ui/react-portal" "1.1.2" - "@radix-ui/react-presence" "1.1.1" - "@radix-ui/react-primitive" "2.0.0" - "@radix-ui/react-roving-focus" "1.1.0" - "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-popper" "1.2.1" + "@radix-ui/react-portal" "1.1.3" + "@radix-ui/react-presence" "1.1.2" + "@radix-ui/react-primitive" "2.0.1" + "@radix-ui/react-roving-focus" "1.1.1" + "@radix-ui/react-slot" "1.1.1" "@radix-ui/react-use-callback-ref" "1.1.0" aria-hidden "^1.1.1" - react-remove-scroll "2.6.0" + react-remove-scroll "^2.6.1" -"@radix-ui/react-popper@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz#a3e500193d144fe2d8f5d5e60e393d64111f2a7a" - integrity sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg== +"@radix-ui/react-popper@1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.1.tgz#2fc66cfc34f95f00d858924e3bee54beae2dff0a" + integrity sha512-3kn5Me69L+jv82EKRuQCXdYyf1DqHwD2U/sxoNgBGCB7K9TRc3bQamQ+5EPM9EvyPdli0W41sROd+ZU1dTCztw== dependencies: "@floating-ui/react-dom" "^2.0.0" - "@radix-ui/react-arrow" "1.1.0" - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-context" "1.1.0" - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-arrow" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-use-rect" "1.1.0" "@radix-ui/react-use-size" "1.1.0" "@radix-ui/rect" "1.1.0" -"@radix-ui/react-portal@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.2.tgz#51eb46dae7505074b306ebcb985bf65cc547d74e" - integrity sha512-WeDYLGPxJb/5EGBoedyJbT0MpoULmwnIPMJMSldkuiMsBAv7N1cRdsTWZWht9vpPOiN3qyiGAtbK2is47/uMFg== - dependencies: - "@radix-ui/react-primitive" "2.0.0" - "@radix-ui/react-use-layout-effect" "1.1.0" - "@radix-ui/react-portal@1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.3.tgz#b0ea5141103a1671b715481b13440763d2ac4440" @@ -2569,14 +2527,6 @@ "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/react-presence@1.1.1": - version "1.1.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.1.tgz#98aba423dba5e0c687a782c0669dcd99de17f9b1" - integrity sha512-IeFXVi4YS1K0wVZzXNrbaaUvIJ3qdY+/Ih4eHFhWA9SwGR9UDX7Ck8abvL57C4cv3wwMvUE0OG69Qc3NCcTe/A== - dependencies: - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-use-layout-effect" "1.1.0" - "@radix-ui/react-presence@1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc" @@ -2585,13 +2535,6 @@ "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/react-primitive@2.0.0": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" - integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== - dependencies: - "@radix-ui/react-slot" "1.1.0" - "@radix-ui/react-primitive@2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz#6d9efc550f7520135366f333d1e820cf225fad9e" @@ -2600,34 +2543,34 @@ "@radix-ui/react-slot" "1.1.1" "@radix-ui/react-progress@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.1.0.tgz#28c267885ec154fc557ec7a66cb462787312f7e2" - integrity sha512-aSzvnYpP725CROcxAOEBVZZSIQVQdHgBr2QQFKySsaD14u8dNT0batuXI+AAGDdAHfXH8rbnHmjYFqVJ21KkRg== + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-progress/-/react-progress-1.1.1.tgz#af923714ba3723be9c510536749d6c530d8670e4" + integrity sha512-6diOawA84f/eMxFHcWut0aE1C2kyE9dOyCTQOMRR2C/qPiXz/X0SaiA/RLbapQaXUCmy0/hLMf9meSccD1N0pA== dependencies: - "@radix-ui/react-context" "1.1.0" - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-context" "1.1.1" + "@radix-ui/react-primitive" "2.0.1" -"@radix-ui/react-roving-focus@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e" - integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA== +"@radix-ui/react-roving-focus@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.1.tgz#3b3abb1e03646937f28d9ab25e96343667ca6520" + integrity sha512-QE1RoxPGJ/Nm8Qmk0PxP8ojmoaS67i0s7hVssS7KuI2FQoc/uzVlZsqKfQvxPE6D8hICCPHJ4D88zNhT3OOmkw== dependencies: - "@radix-ui/primitive" "1.1.0" - "@radix-ui/react-collection" "1.1.0" - "@radix-ui/react-compose-refs" "1.1.0" - "@radix-ui/react-context" "1.1.0" + "@radix-ui/primitive" "1.1.1" + "@radix-ui/react-collection" "1.1.1" + "@radix-ui/react-compose-refs" "1.1.1" + "@radix-ui/react-context" "1.1.1" "@radix-ui/react-direction" "1.1.0" "@radix-ui/react-id" "1.1.0" - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-controllable-state" "1.1.0" "@radix-ui/react-separator@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.0.tgz#ee0f4d86003b0e3ea7bc6ccab01ea0adee32663e" - integrity sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA== + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.1.tgz#dd60621553c858238d876be9b0702287424866d2" + integrity sha512-RRiNRSrD8iUiXriq/Y5n4/3iE8HzqgLHsusUSg5jVpU2+3tqcUFPJXHDymwEypunc2sWxDUS3UC+rkZRlHedsw== dependencies: - "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-primitive" "2.0.1" "@radix-ui/react-slider@^1.1.2": version "1.2.2" @@ -2646,14 +2589,7 @@ "@radix-ui/react-use-previous" "1.1.0" "@radix-ui/react-use-size" "1.1.0" -"@radix-ui/react-slot@1.1.0", "@radix-ui/react-slot@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" - integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== - dependencies: - "@radix-ui/react-compose-refs" "1.1.0" - -"@radix-ui/react-slot@1.1.1": +"@radix-ui/react-slot@1.1.1", "@radix-ui/react-slot@^1.1.0": version "1.1.1" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.1.tgz#ab9a0ffae4027db7dc2af503c223c978706affc3" integrity sha512-RApLLOcINYJA+dMVbOju7MYv1Mb2EBp2nH4HdDzXTSyaR5optlm6Otrz1euW3HbdOR8UmmFK06TD+A9frYWv+g== @@ -3602,16 +3538,16 @@ "@use-gesture/core" "10.3.1" "@vector-im/compound-design-tokens@^2.0.0": - version "2.1.1" - resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-2.1.1.tgz#d6175a99fe4b97688464126f255386990f3048d6" - integrity sha512-QnUi2K14D9KTXxcLQKUU3V75cforZLMwhaaJDNftT8F5mG86950hAM+qhgDNEpEU+pkTffQj0/g/5859YmqWzQ== + version "2.1.3" + resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-2.1.3.tgz#8205ffb455a09d71a02d838f3dbb8503c4e6ec27" + integrity sha512-U4UF7MVguENf0lQnkU2a9p/3llTsLXzbzmFFOxi0h6ny2igNxZj/kROP/jXTxxV9xD4TNn3z098Bos4J/qJpBA== "@vector-im/compound-web@^7.2.0": - version "7.4.0" - resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-7.4.0.tgz#a5af8af6346f8ff6c14c70f5d4eb2eab7357a7cc" - integrity sha512-ZRBUeEGNmj/fTkIRa8zGnyVN7ytowpfOtHChqNm+m/+OTJN3o/lOMuQHDV8jeSEW2YwPJqGvPuG/dRr89IcQkA== + version "7.6.1" + resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-7.6.1.tgz#c41fc8b2e4c5938041e1f0ff9792f8fbadd9ab87" + integrity sha512-LdHGFslkyky2aNPZwIOY9GgWn1VOUa2EBKHln8HBvpxnYPcs3/A2nb1+6SsJ7+Y0TzKc2HA0rZ3qPDhQ3hjZYQ== dependencies: - "@floating-ui/react" "^0.26.24" + "@floating-ui/react" "^0.27.0" "@radix-ui/react-context-menu" "^2.2.1" "@radix-ui/react-dropdown-menu" "^2.1.1" "@radix-ui/react-form" "^0.1.0" @@ -7481,7 +7417,7 @@ react-refresh@^0.14.2: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== -react-remove-scroll-bar@^2.3.6: +react-remove-scroll-bar@^2.3.6, react-remove-scroll-bar@^2.3.7: version "2.3.8" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== @@ -7500,6 +7436,17 @@ react-remove-scroll@2.6.0: use-callback-ref "^1.3.0" use-sidecar "^1.1.2" +react-remove-scroll@^2.6.1: + version "2.6.2" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz#2518d2c5112e71ea8928f1082a58459b5c7a2a97" + integrity sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw== + dependencies: + react-remove-scroll-bar "^2.3.7" + react-style-singleton "^2.2.1" + tslib "^2.1.0" + use-callback-ref "^1.3.3" + use-sidecar "^1.1.2" + react-router-dom@^5.2.0: version "5.3.4" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.3.4.tgz#2ed62ffd88cae6db134445f4a0c0ae8b91d2e5e6" @@ -8719,10 +8666,10 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -use-callback-ref@^1.3.0: - version "1.3.2" - resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.2.tgz#6134c7f6ff76e2be0b56c809b17a650c942b1693" - integrity sha512-elOQwe6Q8gqZgDA8mrh44qRTQqpIHDcZ3hXTLjBe1i4ph8XpNJnO+aQf3NaG+lriLopI4HMx9VjQLfPQ6vhnoA== +use-callback-ref@^1.3.0, use-callback-ref@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" + integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== dependencies: tslib "^2.0.0" From dc904fdbd2f2fc4ccd94194e3a3998e2eebb075b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:01:44 +0100 Subject: [PATCH 07/11] Update dependency @livekit/components-react to v2.6.10 (#2920) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index 419dc141..9e932ef7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1941,9 +1941,9 @@ rxjs "7.8.1" "@livekit/components-react@^2.0.0": - version "2.6.9" - resolved "https://registry.yarnpkg.com/@livekit/components-react/-/components-react-2.6.9.tgz#2ff4691dc2cae6ed4c4b2e586a255d00e494bf9c" - integrity sha512-j43i/Dm8dlI2jxv5wv0s+69QPVqVEjg0y2tyznfs/7RDcaIZsIIzNijPu1kLditerzvzQdRsOgFQ3UWONcTkGA== + version "2.6.10" + resolved "https://registry.yarnpkg.com/@livekit/components-react/-/components-react-2.6.10.tgz#949d6e65e8507e2d8a4c75bf190adf56f6358175" + integrity sha512-aR8rqCIEvT3QYHuVEm67THRmNd9x25FTmU3Phi928FhzQJXDBO0N1/5d6qEE/wuDOgXMOoBgA98qsdYDIi2f+g== dependencies: "@livekit/components-core" "0.11.10" clsx "2.1.1" From 89e33743ae923c2d6e5c07693b866774801c2a10 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 02:39:08 +0000 Subject: [PATCH 08/11] Update LiveKit components --- yarn.lock | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/yarn.lock b/yarn.lock index 9e932ef7..120058a1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1931,21 +1931,21 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@livekit/components-core@0.11.10", "@livekit/components-core@^0.11.0": - version "0.11.10" - resolved "https://registry.yarnpkg.com/@livekit/components-core/-/components-core-0.11.10.tgz#136de5f7df487c984b95cd23d15d271708b30de8" - integrity sha512-PvFlKq1W64b9GfFjG7L4/o7ulAl5yFFpDTvG+JHQiXkaPaecMPt/qPbs6zdvUlC7om1TGMuW/pIN7o585Xz9Fg== +"@livekit/components-core@0.11.11", "@livekit/components-core@^0.11.0": + version "0.11.11" + resolved "https://registry.yarnpkg.com/@livekit/components-core/-/components-core-0.11.11.tgz#010040c05e95b8fe2485f90bb6773031b94c95a7" + integrity sha512-r6VgeS7zq9lMKiNJHSKUHMbmuirksEvHXEGsUvecsHTkZD9nhbhCB/01qCVaCVHVnLXvAYycNXVD4qcepPOpFQ== dependencies: "@floating-ui/dom" "1.6.11" loglevel "1.9.1" rxjs "7.8.1" "@livekit/components-react@^2.0.0": - version "2.6.10" - resolved "https://registry.yarnpkg.com/@livekit/components-react/-/components-react-2.6.10.tgz#949d6e65e8507e2d8a4c75bf190adf56f6358175" - integrity sha512-aR8rqCIEvT3QYHuVEm67THRmNd9x25FTmU3Phi928FhzQJXDBO0N1/5d6qEE/wuDOgXMOoBgA98qsdYDIi2f+g== + version "2.6.11" + resolved "https://registry.yarnpkg.com/@livekit/components-react/-/components-react-2.6.11.tgz#b477ac8d5a2cb97cc27d4fe82f9e2d60522a9e52" + integrity sha512-33V5D2yyt4p9qqjHSMFeu0mUl0S0Qd3zl+x4in9jNl3ZMZBwds9aFx+BtgAGymlAbjbxWPWmHn/SDI3R5/hJRQ== dependencies: - "@livekit/components-core" "0.11.10" + "@livekit/components-core" "0.11.11" clsx "2.1.1" usehooks-ts "3.1.0" From 2c33d6582445c96391b9fb71bc5451a895bb7f2e Mon Sep 17 00:00:00 2001 From: Hugh Nimmo-Smith Date: Mon, 6 Jan 2025 09:47:39 +0000 Subject: [PATCH 09/11] Add developer mode option to show RTC connection statistics (#2904) * Add developer mode option to show RTC connection statistics * Add note about localization * Add titles to help explain what the numbers are * Workaround horizontal scrolling * Use modal to show detailed stats instead of alert * Changed styling and fixed fps = 0 (#2916) (React rendered 0 instead of for fps && {fps}) --------- Co-authored-by: Timo <16718859+toger5@users.noreply.github.com> --- locales/en/app.json | 1 + src/RTCConnectionStats.module.css | 20 ++++ src/RTCConnectionStats.tsx | 112 +++++++++++++++++++++ src/settings/DeveloperSettingsTab.tsx | 19 ++++ src/settings/settings.ts | 5 + src/state/MediaViewModel.ts | 139 ++++++++++++++++++++------ src/tile/GridTile.tsx | 8 ++ src/tile/MediaView.tsx | 11 ++ 8 files changed, 287 insertions(+), 28 deletions(-) create mode 100644 src/RTCConnectionStats.module.css create mode 100644 src/RTCConnectionStats.tsx diff --git a/locales/en/app.json b/locales/en/app.json index 0e71fd4e..f35c3579 100644 --- a/locales/en/app.json +++ b/locales/en/app.json @@ -73,6 +73,7 @@ "duplicate_tiles_label": "Number of additional tile copies per participant", "hostname": "Hostname: {{hostname}}", "matrix_id": "Matrix ID: {{id}}", + "show_connection_stats": "Show connection statistics", "show_non_member_tiles": "Show tiles for non-member media" }, "disconnected_banner": "Connectivity to the server has been lost.", diff --git a/src/RTCConnectionStats.module.css b/src/RTCConnectionStats.module.css new file mode 100644 index 00000000..0e29eaa9 --- /dev/null +++ b/src/RTCConnectionStats.module.css @@ -0,0 +1,20 @@ +/* +Copyright 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +.modal pre { + font-size: var(--font-size-micro); +} + +.statsPill { + border-radius: var(--media-view-border-radius); + grid-area: none; + position: absolute; + top: 0; + left: 0; + flex-direction: column; + align-items: flex-start; +} diff --git a/src/RTCConnectionStats.tsx b/src/RTCConnectionStats.tsx new file mode 100644 index 00000000..d092b677 --- /dev/null +++ b/src/RTCConnectionStats.tsx @@ -0,0 +1,112 @@ +/* +Copyright 2023, 2024 New Vector Ltd. + +SPDX-License-Identifier: AGPL-3.0-only +Please see LICENSE in the repository root for full details. +*/ + +import { useState, type FC } from "react"; +import { Button, Text } from "@vector-im/compound-web"; +import { + MicOnSolidIcon, + VideoCallSolidIcon, +} from "@vector-im/compound-design-tokens/assets/web/icons"; +import classNames from "classnames"; + +import { Modal } from "./Modal"; +import styles from "./RTCConnectionStats.module.css"; +import mediaViewStyles from "../src/tile/MediaView.module.css"; +interface Props { + audio?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; + video?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; +} + +// This is only used in developer mode for debugging purposes, so we don't need full localization +export const RTCConnectionStats: FC = ({ audio, video, ...rest }) => { + const [showModal, setShowModal] = useState(false); + const [modalContents, setModalContents] = useState< + "video" | "audio" | "none" + >("none"); + + const showFullModal = (contents: "video" | "audio"): void => { + setShowModal(true); + setModalContents(contents); + }; + + const onDismissModal = (): void => { + setShowModal(false); + setModalContents("none"); + }; + return ( +
+ +
+
+            {modalContents !== "none" &&
+              JSON.stringify(
+                modalContents === "video" ? video : audio,
+                null,
+                2,
+              )}
+          
+
+
+ {audio && ( +
+ +
+ )} + {video && ( +
+ +
+ )} +
+ ); +}; diff --git a/src/settings/DeveloperSettingsTab.tsx b/src/settings/DeveloperSettingsTab.tsx index 057b0b0c..96ab262f 100644 --- a/src/settings/DeveloperSettingsTab.tsx +++ b/src/settings/DeveloperSettingsTab.tsx @@ -14,6 +14,7 @@ import { duplicateTiles as duplicateTilesSetting, debugTileLayout as debugTileLayoutSetting, showNonMemberTiles as showNonMemberTilesSetting, + showConnectionStats as showConnectionStatsSetting, } from "./settings"; import type { MatrixClient } from "matrix-js-sdk/src/client"; @@ -31,6 +32,10 @@ export const DeveloperSettingsTab: FC = ({ client }) => { showNonMemberTilesSetting, ); + const [showConnectionStats, setShowConnectionStats] = useSetting( + showConnectionStatsSetting, + ); + return ( <>

@@ -103,6 +108,20 @@ export const DeveloperSettingsTab: FC = ({ client }) => { )} /> + + ): void => { + setShowConnectionStats(event.target.checked); + }, + [setShowConnectionStats], + )} + /> + ); }; diff --git a/src/settings/settings.ts b/src/settings/settings.ts index ebb5dffc..24657ac4 100644 --- a/src/settings/settings.ts +++ b/src/settings/settings.ts @@ -78,6 +78,11 @@ export const showNonMemberTiles = new Setting( ); export const debugTileLayout = new Setting("debug-tile-layout", false); +export const showConnectionStats = new Setting( + "show-connection-stats", + false, +); + export const audioInput = new Setting( "audio-input", undefined, diff --git a/src/state/MediaViewModel.ts b/src/state/MediaViewModel.ts index b57b6f15..19a71786 100644 --- a/src/state/MediaViewModel.ts +++ b/src/state/MediaViewModel.ts @@ -47,7 +47,7 @@ import { useEffect } from "react"; import { ViewModel } from "./ViewModel"; import { useReactiveState } from "../useReactiveState"; -import { alwaysShowSelf } from "../settings/settings"; +import { alwaysShowSelf, showConnectionStats } from "../settings/settings"; import { accumulate } from "../utils/observable"; import { type EncryptionSystem } from "../e2ee/sharedKeyManagement"; import { E2eeType } from "../e2ee/e2eeType"; @@ -97,6 +97,60 @@ export function observeTrackReference$( ); } +export function observeRtpStreamStats$( + participant: Participant, + source: Track.Source, + type: "inbound-rtp" | "outbound-rtp", +): Observable< + RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined +> { + return combineLatest([ + observeTrackReference$(of(participant), source), + interval(1000).pipe(startWith(0)), + ]).pipe( + switchMap(async ([trackReference]) => { + const track = trackReference?.publication?.track; + if ( + !track || + !(track instanceof RemoteTrack || track instanceof LocalTrack) + ) { + return undefined; + } + const report = await track.getRTCStatsReport(); + if (!report) { + return undefined; + } + + for (const v of report.values()) { + if (v.type === type) { + return v; + } + } + + return undefined; + }), + startWith(undefined), + ); +} + +export function observeInboundRtpStreamStats$( + participant: Participant, + source: Track.Source, +): Observable { + return observeRtpStreamStats$(participant, source, "inbound-rtp").pipe( + map((x) => x as RTCInboundRtpStreamStats | undefined), + ); +} + +export function observeOutboundRtpStreamStats$( + participant: Participant, + source: Track.Source, +): Observable { + return observeRtpStreamStats$(participant, source, "outbound-rtp").pipe( + map((x) => x as RTCOutboundRtpStreamStats | undefined), + ); +} + function observeRemoteTrackReceivingOkay$( participant: Participant, source: Track.Source, @@ -111,33 +165,15 @@ function observeRemoteTrackReceivingOkay$( framesReceived: undefined, }; - return combineLatest([ - observeTrackReference$(of(participant), source), - interval(1000).pipe(startWith(0)), - ]).pipe( - switchMap(async ([trackReference]) => { - const track = trackReference?.publication?.track; - if (!track || !(track instanceof RemoteTrack)) { - return undefined; - } - const report = await track.getRTCStatsReport(); - if (!report) { - return undefined; - } - - for (const v of report.values()) { - if (v.type === "inbound-rtp") { - const { framesDecoded, framesDropped, framesReceived } = - v as RTCInboundRtpStreamStats; - return { - framesDecoded, - framesDropped, - framesReceived, - }; - } - } - - return undefined; + return observeInboundRtpStreamStats$(participant, source).pipe( + map((stats) => { + if (!stats) return undefined; + const { framesDecoded, framesDropped, framesReceived } = stats; + return { + framesDecoded, + framesDropped, + framesReceived, + }; }), filter((newStats) => !!newStats), map((newStats): boolean | undefined => { @@ -404,6 +440,13 @@ abstract class BaseUserMediaViewModel extends BaseMediaViewModel { public get local(): boolean { return this instanceof LocalUserMediaViewModel; } + + public abstract get audioStreamStats$(): Observable< + RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined + >; + public abstract get videoStreamStats$(): Observable< + RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined + >; } /** @@ -453,6 +496,26 @@ export class LocalUserMediaViewModel extends BaseUserMediaViewModel { reaction$, ); } + + public audioStreamStats$ = combineLatest([ + this.participant$, + showConnectionStats.value$, + ]).pipe( + switchMap(([p, showConnectionStats]) => { + if (!p || !showConnectionStats) return of(undefined); + return observeOutboundRtpStreamStats$(p, Track.Source.Microphone); + }), + ); + + public videoStreamStats$ = combineLatest([ + this.participant$, + showConnectionStats.value$, + ]).pipe( + switchMap(([p, showConnectionStats]) => { + if (!p || !showConnectionStats) return of(undefined); + return observeOutboundRtpStreamStats$(p, Track.Source.Camera); + }), + ); } /** @@ -542,6 +605,26 @@ export class RemoteUserMediaViewModel extends BaseUserMediaViewModel { public commitLocalVolume(): void { this.localVolumeCommit$.next(); } + + public audioStreamStats$ = combineLatest([ + this.participant$, + showConnectionStats.value$, + ]).pipe( + switchMap(([p, showConnectionStats]) => { + if (!p || !showConnectionStats) return of(undefined); + return observeInboundRtpStreamStats$(p, Track.Source.Microphone); + }), + ); + + public videoStreamStats$ = combineLatest([ + this.participant$, + showConnectionStats.value$, + ]).pipe( + switchMap(([p, showConnectionStats]) => { + if (!p || !showConnectionStats) return of(undefined); + return observeInboundRtpStreamStats$(p, Track.Source.Camera); + }), + ); } /** diff --git a/src/tile/GridTile.tsx b/src/tile/GridTile.tsx index 9eb775d0..0d33ccd6 100644 --- a/src/tile/GridTile.tsx +++ b/src/tile/GridTile.tsx @@ -86,6 +86,12 @@ const UserMediaTile = forwardRef( const video = useObservableEagerState(vm.video$); const unencryptedWarning = useObservableEagerState(vm.unencryptedWarning$); const encryptionStatus = useObservableEagerState(vm.encryptionStatus$); + const audioStreamStats = useObservableEagerState< + RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined + >(vm.audioStreamStats$); + const videoStreamStats = useObservableEagerState< + RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats | undefined + >(vm.videoStreamStats$); const audioEnabled = useObservableEagerState(vm.audioEnabled$); const videoEnabled = useObservableEagerState(vm.videoEnabled$); const speaking = useObservableEagerState(vm.speaking$); @@ -174,6 +180,8 @@ const UserMediaTile = forwardRef( currentReaction={reaction ?? undefined} raisedHandOnClick={raisedHandOnClick} localParticipant={vm.local} + audioStreamStats={audioStreamStats} + videoStreamStats={videoStreamStats} {...props} /> ); diff --git a/src/tile/MediaView.tsx b/src/tile/MediaView.tsx index 0d5341a8..abc3904b 100644 --- a/src/tile/MediaView.tsx +++ b/src/tile/MediaView.tsx @@ -22,6 +22,7 @@ import { RaisedHandIndicator } from "../reactions/RaisedHandIndicator"; import { showHandRaisedTimer, useSetting } from "../settings/settings"; import { type ReactionOption } from "../reactions"; import { ReactionIndicator } from "../reactions/ReactionIndicator"; +import { RTCConnectionStats } from "../RTCConnectionStats"; interface Props extends ComponentProps { className?: string; @@ -42,6 +43,8 @@ interface Props extends ComponentProps { currentReaction?: ReactionOption; raisedHandOnClick?: () => void; localParticipant: boolean; + audioStreamStats?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; + videoStreamStats?: RTCInboundRtpStreamStats | RTCOutboundRtpStreamStats; } export const MediaView = forwardRef( @@ -65,6 +68,8 @@ export const MediaView = forwardRef( currentReaction, raisedHandOnClick, localParticipant, + audioStreamStats, + videoStreamStats, ...props }, ref, @@ -125,6 +130,12 @@ export const MediaView = forwardRef( {t("video_tile.waiting_for_media")}

)} + {(audioStreamStats || videoStreamStats) && ( + + )} {/* TODO: Bring this back once encryption status is less broken */} {/*encryptionStatus !== EncryptionStatus.Okay && (
From d6942bc71d058f1a97962c1ba11958f28ad98291 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 11:34:37 +0000 Subject: [PATCH 10/11] Update all non-major dependencies (#2924) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 2370 +++++++++++++++++++++++++------------------------- 2 files changed, 1201 insertions(+), 1171 deletions(-) diff --git a/package.json b/package.json index 4649ee9c..ac693368 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@livekit/components-react": "^2.0.0", "@opentelemetry/api": "^1.4.0", "@opentelemetry/core": "^1.25.1", - "@opentelemetry/exporter-trace-otlp-http": "^0.56.0", + "@opentelemetry/exporter-trace-otlp-http": "^0.57.0", "@opentelemetry/resources": "^1.25.1", "@opentelemetry/sdk-trace-base": "^1.25.1", "@opentelemetry/sdk-trace-web": "^1.9.1", diff --git a/yarn.lock b/yarn.lock index 120058a1..a74d404a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1014,10 +1014,10 @@ resolved "https://registry.yarnpkg.com/@bufbuild/protobuf/-/protobuf-1.10.0.tgz#1a67ac889c2d464a3492b3e54c38f80517963b16" integrity sha512-QDdVFLoN93Zjg36NoQPZfsVH9tZew7wKDKyV5qRdj8ntT4wQCOradQjRaTdwMhWUYsgKsvCINKKm87FdEk96Ag== -"@codecov/bundler-plugin-core@^1.6.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@codecov/bundler-plugin-core/-/bundler-plugin-core-1.6.0.tgz#59da9dc464752ac4ce6f1fa142261aa42f6a8092" - integrity sha512-x2M5P1NUk5lNW5slKY3jSb6Hpuie7bKaolDyZ7oWBHvBgtAJOeU7VrutdVhaiYoiQonM65JI2UAIWtw6mup/Yw== +"@codecov/bundler-plugin-core@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@codecov/bundler-plugin-core/-/bundler-plugin-core-1.7.0.tgz#5362cf332f38f2b9f1d30e81ce7fd47b531e3ebd" + integrity sha512-QsLwtwfy9KEe0CjqNE2Z/SPiCMn4CHAJ9cqTosZCX9YMKPi/WyFivv0pYE7CXA8ntG0l4Xc9kr36DUCuNRW0LQ== dependencies: "@actions/core" "^1.10.1" "@actions/github" "^6.0.0" @@ -1027,11 +1027,11 @@ zod "^3.22.4" "@codecov/vite-plugin@^1.3.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@codecov/vite-plugin/-/vite-plugin-1.6.0.tgz#5433600f1df8528d4ce693cc1ae9297b07b197d5" - integrity sha512-QwgFfF0FJMXovE/ZX33GqkBjkwUwzjPkWepwJizXiQD9emFS7iW82q1vPV9goiakJAvsCVm7Au9e7QnMBGJgvw== + version "1.7.0" + resolved "https://registry.yarnpkg.com/@codecov/vite-plugin/-/vite-plugin-1.7.0.tgz#5c584f5830a84af37cfd0974471f2999e7a92878" + integrity sha512-Cy/NxuEiGCf9X62dKewxnFf6Uv6CxfCCJAd8AfbOYbg96vwjwuq6BMoCIAk9gUFmwurw9EOKGPwoW0lIrUMIzA== dependencies: - "@codecov/bundler-plugin-core" "^1.6.0" + "@codecov/bundler-plugin-core" "^1.7.0" unplugin "^1.10.1" "@csstools/cascade-layer-name-parser@^2.0.4": @@ -1044,18 +1044,18 @@ resolved "https://registry.yarnpkg.com/@csstools/color-helpers/-/color-helpers-5.0.1.tgz#829f1c76f5800b79c51c709e2f36821b728e0e10" integrity sha512-MKtmkA0BX87PKaO1NFRTFH+UnkgnmySQOvNxJubsadusqPEC2aJ9MOQiMceZJJ6oitUl/i0L6u0M1IrmAOmgBA== -"@csstools/css-calc@^2.1.0": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.0.tgz#3f28b8f8f736b8f78abbc75eebd55c756207e773" - integrity sha512-X69PmFOrjTZfN5ijxtI8hZ9kRADFSLrmmQ6hgDJ272Il049WGKpDY64KhrFm/7rbWve0z81QepawzjkKlqkNGw== +"@csstools/css-calc@^2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@csstools/css-calc/-/css-calc-2.1.1.tgz#a7dbc66627f5cf458d42aed14bda0d3860562383" + integrity sha512-rL7kaUnTkL9K+Cvo2pnCieqNpTKgQzy5f+N+5Iuko9HAoasP+xgprVh7KN/MaJVvVL1l0EzQq2MoqBHKSrDrag== -"@csstools/css-color-parser@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.0.6.tgz#e646838f6aab4618aeea7ba0c4921a254e180276" - integrity sha512-S/IjXqTHdpI4EtzGoNCHfqraXF37x12ZZHA1Lk7zoT5pm2lMjFuqhX/89L7dqX4CcMacKK+6ZCs5TmEGb/+wKw== +"@csstools/css-color-parser@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@csstools/css-color-parser/-/css-color-parser-3.0.7.tgz#442d61d58e54ad258d52c309a787fceb33906484" + integrity sha512-nkMp2mTICw32uE5NN+EsJ4f5N+IGFeCFu4bGpiKgb2Pq/7J/MpyLBeQ5ry4KKtRFZaYs6sTmcMYrSRIyj5DFKA== dependencies: "@csstools/color-helpers" "^5.0.1" - "@csstools/css-calc" "^2.1.0" + "@csstools/css-calc" "^2.1.1" "@csstools/css-parser-algorithms@^3.0.4": version "3.0.4" @@ -1080,23 +1080,23 @@ "@csstools/selector-specificity" "^5.0.0" postcss-selector-parser "^7.0.0" -"@csstools/postcss-color-function@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-4.0.6.tgz#dabd1e516ccd4c7bd5803e37075a503b5f7f0ac4" - integrity sha512-EcvXfC60cTIumzpsxWuvVjb7rsJEHPvqn3jeMEBUaE3JSc4FRuP7mEQ+1eicxWmIrs3FtzMH9gR3sgA5TH+ebQ== +"@csstools/postcss-color-function@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-color-function/-/postcss-color-function-4.0.7.tgz#d31d2044d8a4f8b3154ac54ac77014879eae9f56" + integrity sha512-aDHYmhNIHR6iLw4ElWhf+tRqqaXwKnMl0YsQ/X105Zc4dQwe6yJpMrTN6BwOoESrkDjOYMOfORviSSLeDTJkdQ== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-color-mix-function@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.6.tgz#d971832ec30b3b60363bceddfeb4b90c7cc0f4b8" - integrity sha512-jVKdJn4+JkASYGhyPO+Wa5WXSx1+oUgaXb3JsjJn/BlrtFh5zjocCY7pwWi0nuP24V1fY7glQsxEYcYNy0dMFg== +"@csstools/postcss-color-mix-function@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-color-mix-function/-/postcss-color-mix-function-3.0.7.tgz#39735bbc84dc173061e4c2842ec656bb9bc6ed2e" + integrity sha512-e68Nev4CxZYCLcrfWhHH4u/N1YocOfTmw67/kVX5Rb7rnguqqLyxPjhHWjSBX8o4bmyuukmNf3wrUSU3//kT7g== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" @@ -1112,12 +1112,12 @@ "@csstools/postcss-progressive-custom-properties" "^4.0.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-exponential-functions@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.5.tgz#0c39f75df3357ee1e444b0aa0ede4e12aafea0e9" - integrity sha512-mi8R6dVfA2nDoKM3wcEi64I8vOYEgQVtVKCfmLHXupeLpACfGAided5ddMt5f+CnEodNu4DifuVwb0I6fQDGGQ== +"@csstools/postcss-exponential-functions@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@csstools/postcss-exponential-functions/-/postcss-exponential-functions-2.0.6.tgz#dcee86d22102576b13d8bea059125fbcf98e83cc" + integrity sha512-IgJA5DQsQLu/upA3HcdvC6xEMR051ufebBTIXZ5E9/9iiaA7juXWz1ceYj814lnDYP/7eWjZnw0grRJlX4eI6g== dependencies: - "@csstools/css-calc" "^2.1.0" + "@csstools/css-calc" "^2.1.1" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" @@ -1129,32 +1129,32 @@ "@csstools/utilities" "^2.0.0" postcss-value-parser "^4.2.0" -"@csstools/postcss-gamut-mapping@^2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.6.tgz#04ec6a50fdbca2a30dec56e6bb780c79621e47a7" - integrity sha512-0ke7fmXfc8H+kysZz246yjirAH6JFhyX9GTlyRnM0exHO80XcA9zeJpy5pOp5zo/AZiC/q5Pf+Hw7Pd6/uAoYA== +"@csstools/postcss-gamut-mapping@^2.0.7": + version "2.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-gamut-mapping/-/postcss-gamut-mapping-2.0.7.tgz#8aaa4b6ffb6e2187379a83d253607f988533be25" + integrity sha512-gzFEZPoOkY0HqGdyeBXR3JP218Owr683u7KOZazTK7tQZBE8s2yhg06W1tshOqk7R7SWvw9gkw2TQogKpIW8Xw== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" -"@csstools/postcss-gradients-interpolation-method@^5.0.6": - version "5.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.6.tgz#67fa61ada95e4534687fa76cd2d15ac74386560e" - integrity sha512-Itrbx6SLUzsZ6Mz3VuOlxhbfuyLTogG5DwEF1V8dAi24iMuvQPIHd7Ti+pNDp7j6WixndJGZaoNR0f9VSzwuTg== +"@csstools/postcss-gradients-interpolation-method@^5.0.7": + version "5.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-gradients-interpolation-method/-/postcss-gradients-interpolation-method-5.0.7.tgz#57e19d25e98aa028b98e22ef392ea24c3e61c568" + integrity sha512-WgEyBeg6glUeTdS2XT7qeTFBthTJuXlS9GFro/DVomj7W7WMTamAwpoP4oQCq/0Ki2gvfRYFi/uZtmRE14/DFA== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-hwb-function@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.6.tgz#c40f557a54ed45e75c601a9ba7a08d315f64dbd7" - integrity sha512-927Pqy3a1uBP7U8sTfaNdZVB0mNXzIrJO/GZ8us9219q9n06gOqCdfZ0E6d1P66Fm0fYHvxfDbfcUuwAn5UwhQ== +"@csstools/postcss-hwb-function@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-hwb-function/-/postcss-hwb-function-4.0.7.tgz#d09528098c4b99c49c76de686a4ae35585acc691" + integrity sha512-LKYqjO+wGwDCfNIEllessCBWfR4MS/sS1WXO+j00KKyOjm7jDW2L6jzUmqASEiv/kkJO39GcoIOvTTfB3yeBUA== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" @@ -1222,12 +1222,12 @@ "@csstools/css-tokenizer" "^3.0.3" "@csstools/utilities" "^2.0.0" -"@csstools/postcss-media-minmax@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.5.tgz#66970aa8d8057f84b88aff21f385194fbe03eb11" - integrity sha512-sdh5i5GToZOIAiwhdntRWv77QDtsxP2r2gXW/WbLSCoLr00KTq/yiF1qlQ5XX2+lmiFa8rATKMcbwl3oXDMNew== +"@csstools/postcss-media-minmax@^2.0.6": + version "2.0.6" + resolved "https://registry.yarnpkg.com/@csstools/postcss-media-minmax/-/postcss-media-minmax-2.0.6.tgz#427921c0f08033203810af16dfed0baedc538eab" + integrity sha512-J1+4Fr2W3pLZsfxkFazK+9kr96LhEYqoeBszLmFjb6AjYs+g9oDAw3J5oQignLKk3rC9XHW+ebPTZ9FaW5u5pg== dependencies: - "@csstools/css-calc" "^2.1.0" + "@csstools/css-calc" "^2.1.1" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/media-query-list-parser" "^4.0.2" @@ -1256,12 +1256,12 @@ dependencies: postcss-value-parser "^4.2.0" -"@csstools/postcss-oklab-function@^4.0.6": - version "4.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.6.tgz#17e8dfb6422dfd8d77256def5d5be8335ea7af34" - integrity sha512-Hptoa0uX+XsNacFBCIQKTUBrFKDiplHan42X73EklG6XmQLG7/aIvxoNhvZ7PvOWMt67Pw3bIlUY2nD6p5vL8A== +"@csstools/postcss-oklab-function@^4.0.7": + version "4.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-oklab-function/-/postcss-oklab-function-4.0.7.tgz#33b3322dfb27b0b5eb83a7ad36e67f08bc4e66cd" + integrity sha512-I6WFQIbEKG2IO3vhaMGZDkucbCaUSXMxvHNzDdnfsTCF5tc0UlV3Oe2AhamatQoKFjBi75dSEMrgWq3+RegsOQ== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" @@ -1274,21 +1274,21 @@ dependencies: postcss-value-parser "^4.2.0" -"@csstools/postcss-random-function@^1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@csstools/postcss-random-function/-/postcss-random-function-1.0.1.tgz#73a0b62b5dbbc03c25a28f085235eb61b09a2fb0" - integrity sha512-Ab/tF8/RXktQlFwVhiC70UNfpFQRhtE5fQQoP2pO+KCPGLsLdWFiOuHgSRtBOqEshCVAzR4H6o38nhvRZq8deA== +"@csstools/postcss-random-function@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@csstools/postcss-random-function/-/postcss-random-function-1.0.2.tgz#699702820f19bb6b9632966ff44d8957db6889d2" + integrity sha512-vBCT6JvgdEkvRc91NFoNrLjgGtkLWt47GKT6E2UDn3nd8ZkMBiziQ1Md1OiKoSsgzxsSnGKG3RVdhlbdZEkHjA== dependencies: - "@csstools/css-calc" "^2.1.0" + "@csstools/css-calc" "^2.1.1" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" -"@csstools/postcss-relative-color-syntax@^3.0.6": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.6.tgz#4b8bc219b34b16f5abdbbcf09ac13e65bff6ef16" - integrity sha512-yxP618Xb+ji1I624jILaYM62uEmZcmbdmFoZHoaThw896sq0vU39kqTTF+ZNic9XyPtPMvq0vyvbgmHaszq8xg== +"@csstools/postcss-relative-color-syntax@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@csstools/postcss-relative-color-syntax/-/postcss-relative-color-syntax-3.0.7.tgz#862f8c6a2bbbab1a46aff8265b6a095fd267a3a6" + integrity sha512-apbT31vsJVd18MabfPOnE977xgct5B1I+Jpf+Munw3n6kKb1MMuUmGGH+PT9Hm/fFs6fe61Q/EWnkrb4bNoNQw== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" @@ -1301,21 +1301,21 @@ dependencies: postcss-selector-parser "^7.0.0" -"@csstools/postcss-sign-functions@^1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.0.tgz#a524fae1374b0e167729f612ca875d7b1b334262" - integrity sha512-SLcc20Nujx/kqbSwDmj6oaXgpy3UjFhBy1sfcqPgDkHfOIfUtUVH7OXO+j7BU4v/At5s61N5ZX6shvgPwluhsA== +"@csstools/postcss-sign-functions@^1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@csstools/postcss-sign-functions/-/postcss-sign-functions-1.1.1.tgz#eb8e4a5ac637982aeb9264cb99f85817612ad3e8" + integrity sha512-MslYkZCeMQDxetNkfmmQYgKCy4c+w9pPDfgOBCJOo/RI1RveEUdZQYtOfrC6cIZB7sD7/PHr2VGOcMXlZawrnA== dependencies: - "@csstools/css-calc" "^2.1.0" + "@csstools/css-calc" "^2.1.1" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" -"@csstools/postcss-stepped-value-functions@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.5.tgz#4d68633d502fbe2b6ef3898e368e3540488a0d8a" - integrity sha512-G6SJ6hZJkhxo6UZojVlLo14MohH4J5J7z8CRBrxxUYy9JuZiIqUo5TBYyDGcE0PLdzpg63a7mHSJz3VD+gMwqw== +"@csstools/postcss-stepped-value-functions@^4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-4.0.6.tgz#ee88c6122daf58a1b8641f462e8e33427c60b1f1" + integrity sha512-/dwlO9w8vfKgiADxpxUbZOWlL5zKoRIsCymYoh1IPuBsXODKanKnfuZRr32DEqT0//3Av1VjfNZU9yhxtEfIeA== dependencies: - "@csstools/css-calc" "^2.1.0" + "@csstools/css-calc" "^2.1.1" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" @@ -1327,12 +1327,12 @@ "@csstools/color-helpers" "^5.0.1" postcss-value-parser "^4.2.0" -"@csstools/postcss-trigonometric-functions@^4.0.5": - version "4.0.5" - resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.5.tgz#267b95a8bd45536e0360596b6da660a9eb6aac83" - integrity sha512-/YQThYkt5MLvAmVu7zxjhceCYlKrYddK6LEmK5I4ojlS6BmO9u2yO4+xjXzu2+NPYmHSTtP4NFSamBCMmJ1NJA== +"@csstools/postcss-trigonometric-functions@^4.0.6": + version "4.0.6" + resolved "https://registry.yarnpkg.com/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-4.0.6.tgz#fc5c5f4c9bd0fd796b58b9a14d5d663be76d19fa" + integrity sha512-c4Y1D2Why/PeccaSouXnTt6WcNHJkoJRidV2VW9s5gJ97cNxnLgQ4Qj8qOqkIR9VmTQKJyNcbF4hy79ZQnWD7A== dependencies: - "@csstools/css-calc" "^2.1.0" + "@csstools/css-calc" "^2.1.1" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" @@ -1361,355 +1361,240 @@ resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz#c7184a326533fcdf1b8ee0733e21c713b975575f" integrity sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ== -"@esbuild/aix-ppc64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz#145b74d5e4a5223489cabdc238d8dad902df5259" - integrity sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ== - -"@esbuild/aix-ppc64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.0.tgz#b57697945b50e99007b4c2521507dc613d4a648c" - integrity sha512-WtKdFM7ls47zkKHFVzMz8opM7LkcsIp9amDUBIAWirg70RM71WRSjdILPsY5Uv1D42ZpUfaPILDlfactHgsRkw== +"@esbuild/aix-ppc64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461" + integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA== "@esbuild/android-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz#09d9b4357780da9ea3a7dfb833a1f1ff439b4052" integrity sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A== -"@esbuild/android-arm64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz#453bbe079fc8d364d4c5545069e8260228559832" - integrity sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ== - -"@esbuild/android-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.0.tgz#1add7e0af67acefd556e407f8497e81fddad79c0" - integrity sha512-Vsm497xFM7tTIPYK9bNTYJyF/lsP590Qc1WxJdlB6ljCbdZKU9SY8i7+Iin4kyhV/KV5J2rOKsBQbB77Ab7L/w== +"@esbuild/android-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894" + integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg== "@esbuild/android-arm@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.21.5.tgz#9b04384fb771926dfa6d7ad04324ecb2ab9b2e28" integrity sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg== -"@esbuild/android-arm@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.23.0.tgz#26c806853aa4a4f7e683e519cd9d68e201ebcf99" - integrity sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g== - -"@esbuild/android-arm@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.0.tgz#ab7263045fa8e090833a8e3c393b60d59a789810" - integrity sha512-arAtTPo76fJ/ICkXWetLCc9EwEHKaeya4vMrReVlEIUCAUncH7M4bhMQ+M9Vf+FFOZJdTNMXNBrWwW+OXWpSew== +"@esbuild/android-arm@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3" + integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q== "@esbuild/android-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.21.5.tgz#29918ec2db754cedcb6c1b04de8cd6547af6461e" integrity sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA== -"@esbuild/android-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.23.0.tgz#1e51af9a6ac1f7143769f7ee58df5b274ed202e6" - integrity sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ== - -"@esbuild/android-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.0.tgz#e8f8b196cfdfdd5aeaebbdb0110983460440e705" - integrity sha512-t8GrvnFkiIY7pa7mMgJd7p8p8qqYIz1NYiAoKc75Zyv73L3DZW++oYMSHPRarcotTKuSs6m3hTOa5CKHaS02TQ== +"@esbuild/android-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb" + integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw== "@esbuild/darwin-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz#e495b539660e51690f3928af50a76fb0a6ccff2a" integrity sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ== -"@esbuild/darwin-arm64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz#d996187a606c9534173ebd78c58098a44dd7ef9e" - integrity sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow== - -"@esbuild/darwin-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.0.tgz#2d0d9414f2acbffd2d86e98253914fca603a53dd" - integrity sha512-CKyDpRbK1hXwv79soeTJNHb5EiG6ct3efd/FTPdzOWdbZZfGhpbcqIpiD0+vwmpu0wTIL97ZRPZu8vUt46nBSw== +"@esbuild/darwin-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936" + integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA== "@esbuild/darwin-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz#c13838fa57372839abdddc91d71542ceea2e1e22" integrity sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw== -"@esbuild/darwin-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz#30c8f28a7ef4e32fe46501434ebe6b0912e9e86c" - integrity sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ== - -"@esbuild/darwin-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.0.tgz#33087aab31a1eb64c89daf3d2cf8ce1775656107" - integrity sha512-rgtz6flkVkh58od4PwTRqxbKH9cOjaXCMZgWD905JOzjFKW+7EiUObfd/Kav+A6Gyud6WZk9w+xu6QLytdi2OA== +"@esbuild/darwin-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9" + integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA== "@esbuild/freebsd-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz#646b989aa20bf89fd071dd5dbfad69a3542e550e" integrity sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g== -"@esbuild/freebsd-arm64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz#30f4fcec8167c08a6e8af9fc14b66152232e7fb4" - integrity sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw== - -"@esbuild/freebsd-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.0.tgz#bb76e5ea9e97fa3c753472f19421075d3a33e8a7" - integrity sha512-6Mtdq5nHggwfDNLAHkPlyLBpE5L6hwsuXZX8XNmHno9JuL2+bg2BX5tRkwjyfn6sKbxZTq68suOjgWqCicvPXA== +"@esbuild/freebsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00" + integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg== "@esbuild/freebsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz#aa615cfc80af954d3458906e38ca22c18cf5c261" integrity sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ== -"@esbuild/freebsd-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz#1003a6668fe1f5d4439e6813e5b09a92981bc79d" - integrity sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ== - -"@esbuild/freebsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.0.tgz#e0e2ce9249fdf6ee29e5dc3d420c7007fa579b93" - integrity sha512-D3H+xh3/zphoX8ck4S2RxKR6gHlHDXXzOf6f/9dbFt/NRBDIE33+cVa49Kil4WUjxMGW0ZIYBYtaGCa2+OsQwQ== +"@esbuild/freebsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f" + integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q== "@esbuild/linux-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz#70ac6fa14f5cb7e1f7f887bcffb680ad09922b5b" integrity sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q== -"@esbuild/linux-arm64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz#3b9a56abfb1410bb6c9138790f062587df3e6e3a" - integrity sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw== - -"@esbuild/linux-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.0.tgz#d1b2aa58085f73ecf45533c07c82d81235388e75" - integrity sha512-TDijPXTOeE3eaMkRYpcy3LarIg13dS9wWHRdwYRnzlwlA370rNdZqbcp0WTyyV/k2zSxfko52+C7jU5F9Tfj1g== +"@esbuild/linux-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43" + integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg== "@esbuild/linux-arm@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz#fc6fd11a8aca56c1f6f3894f2bea0479f8f626b9" integrity sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA== -"@esbuild/linux-arm@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz#237a8548e3da2c48cd79ae339a588f03d1889aad" - integrity sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw== - -"@esbuild/linux-arm@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.0.tgz#8e4915df8ea3e12b690a057e77a47b1d5935ef6d" - integrity sha512-gJKIi2IjRo5G6Glxb8d3DzYXlxdEj2NlkixPsqePSZMhLudqPhtZ4BUrpIuTjJYXxvF9njql+vRjB2oaC9XpBw== +"@esbuild/linux-arm@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736" + integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA== "@esbuild/linux-ia32@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz#3271f53b3f93e3d093d518d1649d6d68d346ede2" integrity sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg== -"@esbuild/linux-ia32@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz#4269cd19cb2de5de03a7ccfc8855dde3d284a238" - integrity sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA== - -"@esbuild/linux-ia32@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.0.tgz#8200b1110666c39ab316572324b7af63d82013fb" - integrity sha512-K40ip1LAcA0byL05TbCQ4yJ4swvnbzHscRmUilrmP9Am7//0UjPreh4lpYzvThT2Quw66MhjG//20mrufm40mA== +"@esbuild/linux-ia32@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5" + integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw== "@esbuild/linux-loong64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz#ed62e04238c57026aea831c5a130b73c0f9f26df" integrity sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg== -"@esbuild/linux-loong64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz#82b568f5658a52580827cc891cb69d2cb4f86280" - integrity sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A== - -"@esbuild/linux-loong64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.0.tgz#6ff0c99cf647504df321d0640f0d32e557da745c" - integrity sha512-0mswrYP/9ai+CU0BzBfPMZ8RVm3RGAN/lmOMgW4aFUSOQBjA31UP8Mr6DDhWSuMwj7jaWOT0p0WoZ6jeHhrD7g== +"@esbuild/linux-loong64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc" + integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ== "@esbuild/linux-mips64el@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz#e79b8eb48bf3b106fadec1ac8240fb97b4e64cbe" integrity sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg== -"@esbuild/linux-mips64el@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz#9a57386c926262ae9861c929a6023ed9d43f73e5" - integrity sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w== - -"@esbuild/linux-mips64el@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.0.tgz#3f720ccd4d59bfeb4c2ce276a46b77ad380fa1f3" - integrity sha512-hIKvXm0/3w/5+RDtCJeXqMZGkI2s4oMUGj3/jM0QzhgIASWrGO5/RlzAzm5nNh/awHE0A19h/CvHQe6FaBNrRA== +"@esbuild/linux-mips64el@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb" + integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw== "@esbuild/linux-ppc64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz#5f2203860a143b9919d383ef7573521fb154c3e4" integrity sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w== -"@esbuild/linux-ppc64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz#f3a79fd636ba0c82285d227eb20ed8e31b4444f6" - integrity sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw== - -"@esbuild/linux-ppc64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.0.tgz#9d6b188b15c25afd2e213474bf5f31e42e3aa09e" - integrity sha512-HcZh5BNq0aC52UoocJxaKORfFODWXZxtBaaZNuN3PUX3MoDsChsZqopzi5UupRhPHSEHotoiptqikjN/B77mYQ== +"@esbuild/linux-ppc64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412" + integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw== "@esbuild/linux-riscv64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz#07bcafd99322d5af62f618cb9e6a9b7f4bb825dc" integrity sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA== -"@esbuild/linux-riscv64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz#f9d2ef8356ce6ce140f76029680558126b74c780" - integrity sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw== - -"@esbuild/linux-riscv64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.0.tgz#f989fdc9752dfda286c9cd87c46248e4dfecbc25" - integrity sha512-bEh7dMn/h3QxeR2KTy1DUszQjUrIHPZKyO6aN1X4BCnhfYhuQqedHaa5MxSQA/06j3GpiIlFGSsy1c7Gf9padw== +"@esbuild/linux-riscv64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694" + integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q== "@esbuild/linux-s390x@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz#b7ccf686751d6a3e44b8627ababc8be3ef62d8de" integrity sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A== -"@esbuild/linux-s390x@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz#45390f12e802201f38a0229e216a6aed4351dfe8" - integrity sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg== - -"@esbuild/linux-s390x@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.0.tgz#29ebf87e4132ea659c1489fce63cd8509d1c7319" - integrity sha512-ZcQ6+qRkw1UcZGPyrCiHHkmBaj9SiCD8Oqd556HldP+QlpUIe2Wgn3ehQGVoPOvZvtHm8HPx+bH20c9pvbkX3g== +"@esbuild/linux-s390x@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577" + integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw== "@esbuild/linux-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz#6d8f0c768e070e64309af8004bb94e68ab2bb3b0" integrity sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ== -"@esbuild/linux-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz#c8409761996e3f6db29abcf9b05bee8d7d80e910" - integrity sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ== +"@esbuild/linux-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f" + integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q== -"@esbuild/linux-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.0.tgz#4af48c5c0479569b1f359ffbce22d15f261c0cef" - integrity sha512-vbutsFqQ+foy3wSSbmjBXXIJ6PL3scghJoM8zCL142cGaZKAdCZHyf+Bpu/MmX9zT9Q0zFBVKb36Ma5Fzfa8xA== +"@esbuild/netbsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6" + integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw== "@esbuild/netbsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz#bbe430f60d378ecb88decb219c602667387a6047" integrity sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg== -"@esbuild/netbsd-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz#ba70db0114380d5f6cfb9003f1d378ce989cd65c" - integrity sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw== +"@esbuild/netbsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40" + integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw== -"@esbuild/netbsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.0.tgz#1ae73d23cc044a0ebd4f198334416fb26c31366c" - integrity sha512-hjQ0R/ulkO8fCYFsG0FZoH+pWgTTDreqpqY7UnQntnaKv95uP5iW3+dChxnx7C3trQQU40S+OgWhUVwCjVFLvg== - -"@esbuild/openbsd-arm64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz#72fc55f0b189f7a882e3cf23f332370d69dfd5db" - integrity sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ== - -"@esbuild/openbsd-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.0.tgz#5d904a4f5158c89859fd902c427f96d6a9e632e2" - integrity sha512-MD9uzzkPQbYehwcN583yx3Tu5M8EIoTD+tUgKF982WYL9Pf5rKy9ltgD0eUgs8pvKnmizxjXZyLt0z6DC3rRXg== +"@esbuild/openbsd-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f" + integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A== "@esbuild/openbsd-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz#99d1cf2937279560d2104821f5ccce220cb2af70" integrity sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow== -"@esbuild/openbsd-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz#b6ae7a0911c18fe30da3db1d6d17a497a550e5d8" - integrity sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg== - -"@esbuild/openbsd-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.0.tgz#4c8aa88c49187c601bae2971e71c6dc5e0ad1cdf" - integrity sha512-4ir0aY1NGUhIC1hdoCzr1+5b43mw99uNwVzhIq1OY3QcEwPDO3B7WNXBzaKY5Nsf1+N11i1eOfFcq+D/gOS15Q== +"@esbuild/openbsd-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205" + integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA== "@esbuild/sunos-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz#08741512c10d529566baba837b4fe052c8f3487b" integrity sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg== -"@esbuild/sunos-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz#58f0d5e55b9b21a086bfafaa29f62a3eb3470ad8" - integrity sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA== - -"@esbuild/sunos-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.0.tgz#8ddc35a0ea38575fa44eda30a5ee01ae2fa54dd4" - integrity sha512-jVzdzsbM5xrotH+W5f1s+JtUy1UWgjU0Cf4wMvffTB8m6wP5/kx0KiaLHlbJO+dMgtxKV8RQ/JvtlFcdZ1zCPA== +"@esbuild/sunos-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6" + integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig== "@esbuild/win32-arm64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz#675b7385398411240735016144ab2e99a60fc75d" integrity sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A== -"@esbuild/win32-arm64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz#b858b2432edfad62e945d5c7c9e5ddd0f528ca6d" - integrity sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ== - -"@esbuild/win32-arm64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.0.tgz#6e79c8543f282c4539db684a207ae0e174a9007b" - integrity sha512-iKc8GAslzRpBytO2/aN3d2yb2z8XTVfNV0PjGlCxKo5SgWmNXx82I/Q3aG1tFfS+A2igVCY97TJ8tnYwpUWLCA== +"@esbuild/win32-arm64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85" + integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ== "@esbuild/win32-ia32@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz#1bfc3ce98aa6ca9a0969e4d2af72144c59c1193b" integrity sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA== -"@esbuild/win32-ia32@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz#167ef6ca22a476c6c0c014a58b4f43ae4b80dec7" - integrity sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA== - -"@esbuild/win32-ia32@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.0.tgz#057af345da256b7192d18b676a02e95d0fa39103" - integrity sha512-vQW36KZolfIudCcTnaTpmLQ24Ha1RjygBo39/aLkM2kmjkWmZGEJ5Gn9l5/7tzXA42QGIoWbICfg6KLLkIw6yw== +"@esbuild/win32-ia32@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2" + integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA== "@esbuild/win32-x64@0.21.5": version "0.21.5" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz#acad351d582d157bb145535db2a6ff53dd514b5c" integrity sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw== -"@esbuild/win32-x64@0.23.0": - version "0.23.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz#db44a6a08520b5f25bbe409f34a59f2d4bcc7ced" - integrity sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g== - -"@esbuild/win32-x64@0.24.0": - version "0.24.0" - resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.0.tgz#168ab1c7e1c318b922637fad8f339d48b01e1244" - integrity sha512-7IAFPrjSQIJrGsK6flwg7NFmwBoSTyF3rl7If0hNUFQU4ilTsEPL6GuMuU9BfIWVVGuRnuIidkSMC+c0Otu8IA== +"@esbuild/win32-x64@0.24.2": + version "0.24.2" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b" + integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg== "@eslint-community/eslint-utils@^4.2.0": version "4.4.0" @@ -1805,55 +1690,55 @@ integrity sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig== "@fontsource/inconsolata@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@fontsource/inconsolata/-/inconsolata-5.1.0.tgz#f6a76680173336d02d2ce4009699821a6be239ce" - integrity sha512-vYPdG3R46MhK+99De8e8MMyNad5BAb1oTnHMpojlctZyWJIcin8bKHFPUpQSNRhZ4HQL/+DCW+RTiG2RbnweTw== + version "5.1.1" + resolved "https://registry.yarnpkg.com/@fontsource/inconsolata/-/inconsolata-5.1.1.tgz#bc5cc74d04dee8b2cb4e706cc33ac3dc50100191" + integrity sha512-jLLMagEJURTae5J30gehIsXRv96vjQ0XlALGxZC7DERWPqsJTa0oSsZR8k6IJfizU4ZeRl/aKWpZca2Lo3TvSg== "@fontsource/inter@^5.1.0": - version "5.1.0" - resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-5.1.0.tgz#ab629b2c662457022d2d6a29854b8dc8ba538c47" - integrity sha512-zKZR3kf1G0noIes1frLfOHP5EXVVm0M7sV/l9f/AaYf+M/DId35FO4LkigWjqWYjTJZGgplhdv4cB+ssvCqr5A== + version "5.1.1" + resolved "https://registry.yarnpkg.com/@fontsource/inter/-/inter-5.1.1.tgz#401803b6ac4c877f5be94088aa89147ed5a2bd85" + integrity sha512-weN3E+rq0Xb3Z93VHJ+Rc7WOQX9ETJPTAJ+gDcaMHtjft67L58sfS65rAjC5tZUXQ2FdZ/V1/sSzCwZ6v05kJw== -"@formatjs/ecma402-abstract@2.3.1": - version "2.3.1" - resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.1.tgz#cdeb3ffe1aeea9c4284b85b7e37e8e8615314c39" - integrity sha512-Ip9uV+/MpLXWRk03U/GzeJMuPeOXpJBSB5V1tjA6kJhvqssye5J5LoYLc7Z5IAHb7nR62sRoguzrFiVCP/hnzw== +"@formatjs/ecma402-abstract@2.3.2": + version "2.3.2" + resolved "https://registry.yarnpkg.com/@formatjs/ecma402-abstract/-/ecma402-abstract-2.3.2.tgz#0ee291effe7ee2c340742a6c95d92eacb5e6c00a" + integrity sha512-6sE5nyvDloULiyOMbOTJEEgWL32w+VHkZQs8S02Lnn8Y/O5aQhjOEXwWzvR7SsBE/exxlSpY2EsWZgqHbtLatg== dependencies: - "@formatjs/fast-memoize" "2.2.5" - "@formatjs/intl-localematcher" "0.5.9" + "@formatjs/fast-memoize" "2.2.6" + "@formatjs/intl-localematcher" "0.5.10" decimal.js "10" tslib "2" -"@formatjs/fast-memoize@2.2.5": - version "2.2.5" - resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.5.tgz#54a4a1793d773b72c372d3dcab3595149aee7880" - integrity sha512-6PoewUMrrcqxSoBXAOJDiW1m+AmkrAj0RiXnOMD59GRaswjXhm3MDhgepXPBgonc09oSirAJTsAggzAGQf6A6g== +"@formatjs/fast-memoize@2.2.6": + version "2.2.6" + resolved "https://registry.yarnpkg.com/@formatjs/fast-memoize/-/fast-memoize-2.2.6.tgz#fac0a84207a1396be1f1aa4ee2805b179e9343d1" + integrity sha512-luIXeE2LJbQnnzotY1f2U2m7xuQNj2DA8Vq4ce1BY9ebRZaoPB1+8eZ6nXpLzsxuW5spQxr7LdCg+CApZwkqkw== dependencies: tslib "2" "@formatjs/intl-durationformat@^0.7.0": - version "0.7.1" - resolved "https://registry.yarnpkg.com/@formatjs/intl-durationformat/-/intl-durationformat-0.7.1.tgz#d83e6f4bf188cafac50a2a911241084bafe89524" - integrity sha512-tM/sscHRcVMVAn0qMJlmq5mf3MaqA0jSz73NT4SYBHZuZqfU0EKWjJCwZBYeNRfvO6y20Yo0RzGxom0KvSVUlA== + version "0.7.2" + resolved "https://registry.yarnpkg.com/@formatjs/intl-durationformat/-/intl-durationformat-0.7.2.tgz#cb49e84b3be882341c21f1ffbb6a6320353bf506" + integrity sha512-GTO67hNFJOv7g3nOEpSJ+0CN0VHI/GvIfv0sTfTjl30aGN4oGV7SEo2IKCQe3NbPTAYUcCRCzKa5+vAW3crS5w== dependencies: - "@formatjs/ecma402-abstract" "2.3.1" - "@formatjs/intl-localematcher" "0.5.9" + "@formatjs/ecma402-abstract" "2.3.2" + "@formatjs/intl-localematcher" "0.5.10" tslib "2" -"@formatjs/intl-localematcher@0.5.9": - version "0.5.9" - resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.9.tgz#43c6ee22be85b83340bcb09bdfed53657a2720db" - integrity sha512-8zkGu/sv5euxbjfZ/xmklqLyDGQSxsLqg8XOq88JW3cmJtzhCP8EtSJXlaKZnVO4beEaoiT9wj4eIoCQ9smwxA== +"@formatjs/intl-localematcher@0.5.10": + version "0.5.10" + resolved "https://registry.yarnpkg.com/@formatjs/intl-localematcher/-/intl-localematcher-0.5.10.tgz#1e0bd3fc1332c1fe4540cfa28f07e9227b659a58" + integrity sha512-af3qATX+m4Rnd9+wHcjJ4w2ijq+rAVP3CCinJQvFv1kgSu1W6jypUmvleJxcewdxmutM8dmIRZFxO/IQBZmP2Q== dependencies: tslib "2" "@formatjs/intl-segmenter@^11.7.3": - version "11.7.7" - resolved "https://registry.yarnpkg.com/@formatjs/intl-segmenter/-/intl-segmenter-11.7.7.tgz#8a5aaa316e11ca2d31b99222e6fcf1ab539b085e" - integrity sha512-610J5xz5DxtEpa16zNR89CrvA9qWHxQFkUB3FKiGao0Nwn7i8cl+oyBhuH9SvtXF9j2LUOM9VMdVCMzJkVANNw== + version "11.7.8" + resolved "https://registry.yarnpkg.com/@formatjs/intl-segmenter/-/intl-segmenter-11.7.8.tgz#85990c7e3961ef686ed78b8cacb216852cadb061" + integrity sha512-+nqMCJ6LNLl+qXldE2uthF82O/2Yo6GZlyWbOY25fe3066iaHjmrR4nXd6AKRMCHNeBBx3rANFLm2B5cNTBzTQ== dependencies: - "@formatjs/ecma402-abstract" "2.3.1" - "@formatjs/intl-localematcher" "0.5.9" + "@formatjs/ecma402-abstract" "2.3.2" + "@formatjs/intl-localematcher" "0.5.10" tslib "2" "@gulpjs/to-absolute-glob@^4.0.0": @@ -2084,10 +1969,10 @@ dependencies: "@octokit/openapi-types" "^22.2.0" -"@opentelemetry/api-logs@0.56.0": - version "0.56.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.56.0.tgz#68f8c51ca905c260b610c8a3c67d3f9fa3d59a45" - integrity sha512-Wr39+94UNNG3Ei9nv3pHd4AJ63gq5nSemMRpCd8fPwDL9rN3vK26lzxfH27mw16XzOSO+TpyQwBAMaLxaPWG0g== +"@opentelemetry/api-logs@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/api-logs/-/api-logs-0.57.0.tgz#794f9ff6343671f68e228eeb606d416c4ab29653" + integrity sha512-l1aJ30CXeauVYaI+btiynHpw341LthkMTv3omi1VJDX14werY2Wmv9n1yudMsq9HuY0m8PvXEVX4d8zxEb+WRg== dependencies: "@opentelemetry/api" "^1.3.0" @@ -2096,86 +1981,86 @@ resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== -"@opentelemetry/core@1.29.0", "@opentelemetry/core@^1.25.1": - version "1.29.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.29.0.tgz#a9397dfd9a8b37b2435b5e44be16d39ec1c82bd9" - integrity sha512-gmT7vAreXl0DTHD2rVZcw3+l2g84+5XiHIqdBUxXbExymPCvSsGOpiwMmn8nkiJur28STV31wnhIDrzWDPzjfA== +"@opentelemetry/core@1.30.0", "@opentelemetry/core@^1.25.1": + version "1.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.30.0.tgz#ef959e11e137d72466e566e375ecc5a82e922b86" + integrity sha512-Q/3u/K73KUjTCnFUP97ZY+pBjQ1kPEgjOfXj/bJl8zW7GbXdkw6cwuyZk6ZTXkVgCBsYRYUzx4fvYK1jxdb9MA== dependencies: "@opentelemetry/semantic-conventions" "1.28.0" -"@opentelemetry/exporter-trace-otlp-http@^0.56.0": - version "0.56.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.56.0.tgz#184bd208d68bd19c3382a9a22737200b34f7edb9" - integrity sha512-vqVuJvcwameA0r0cNrRzrZqPLB0otS+95g0XkZdiKOXUo81wYdY6r4kyrwz4nSChqTBEFm0lqi/H2OWGboOa6g== +"@opentelemetry/exporter-trace-otlp-http@^0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/exporter-trace-otlp-http/-/exporter-trace-otlp-http-0.57.0.tgz#fee258d502dabda6646dd19029860192115017b6" + integrity sha512-BJl35PSkwoMlGEOrzjCG1ih6zqZoAZJIR4xyqSKC2BqPtwuRjID0vWBaEdP9xrxxJTEIEQw+gEY/0pUgicX0ew== dependencies: - "@opentelemetry/core" "1.29.0" - "@opentelemetry/otlp-exporter-base" "0.56.0" - "@opentelemetry/otlp-transformer" "0.56.0" - "@opentelemetry/resources" "1.29.0" - "@opentelemetry/sdk-trace-base" "1.29.0" + "@opentelemetry/core" "1.30.0" + "@opentelemetry/otlp-exporter-base" "0.57.0" + "@opentelemetry/otlp-transformer" "0.57.0" + "@opentelemetry/resources" "1.30.0" + "@opentelemetry/sdk-trace-base" "1.30.0" -"@opentelemetry/otlp-exporter-base@0.56.0": - version "0.56.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.56.0.tgz#3461fd403fbd3d366df46536a5a7dd7c7f499536" - integrity sha512-eURvv0fcmBE+KE1McUeRo+u0n18ZnUeSc7lDlW/dzlqFYasEbsztTK4v0Qf8C4vEY+aMTjPKUxBG0NX2Te3Pmw== +"@opentelemetry/otlp-exporter-base@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-exporter-base/-/otlp-exporter-base-0.57.0.tgz#45a1c23edfc492723183f136cd7feb954f25ca28" + integrity sha512-QQl4Ngm3D6H8SDO0EM642ncTxjRsf/HDq7+IWIA0eaEK/NTsJeQ3iYJiZj3F4jkALnvyeM1kkwd+DHtqxTBx9Q== dependencies: - "@opentelemetry/core" "1.29.0" - "@opentelemetry/otlp-transformer" "0.56.0" + "@opentelemetry/core" "1.30.0" + "@opentelemetry/otlp-transformer" "0.57.0" -"@opentelemetry/otlp-transformer@0.56.0": - version "0.56.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.56.0.tgz#d2bae377ff2cabc0366d002ab993fcb8ea7d2700" - integrity sha512-kVkH/W2W7EpgWWpyU5VnnjIdSD7Y7FljQYObAQSKdRcejiwMj2glypZtUdfq1LTJcv4ht0jyTrw1D3CCxssNtQ== +"@opentelemetry/otlp-transformer@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/otlp-transformer/-/otlp-transformer-0.57.0.tgz#7a4b6e3015397d975b9ea6de6068a072ef5880a7" + integrity sha512-yHX7sdwkdAmSa6Jbi3caSLDWy0PCHS1pKQeKz8AIWSyQqL7IojHKgdk9A+7eRd98Z1n9YTdwWSWLnObvIqhEhQ== dependencies: - "@opentelemetry/api-logs" "0.56.0" - "@opentelemetry/core" "1.29.0" - "@opentelemetry/resources" "1.29.0" - "@opentelemetry/sdk-logs" "0.56.0" - "@opentelemetry/sdk-metrics" "1.29.0" - "@opentelemetry/sdk-trace-base" "1.29.0" + "@opentelemetry/api-logs" "0.57.0" + "@opentelemetry/core" "1.30.0" + "@opentelemetry/resources" "1.30.0" + "@opentelemetry/sdk-logs" "0.57.0" + "@opentelemetry/sdk-metrics" "1.30.0" + "@opentelemetry/sdk-trace-base" "1.30.0" protobufjs "^7.3.0" -"@opentelemetry/resources@1.29.0", "@opentelemetry/resources@^1.25.1": - version "1.29.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.29.0.tgz#d170f39b2ac93d61b53d13dfcd96795181bdc372" - integrity sha512-s7mLXuHZE7RQr1wwweGcaRp3Q4UJJ0wazeGlc/N5/XSe6UyXfsh1UQGMADYeg7YwD+cEdMtU1yJAUXdnFzYzyQ== +"@opentelemetry/resources@1.30.0", "@opentelemetry/resources@^1.25.1": + version "1.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.30.0.tgz#87604359e6195c017075b7d294a949ad018e692d" + integrity sha512-5mGMjL0Uld/99t7/pcd7CuVtJbkARckLVuiOX84nO8RtLtIz0/J6EOHM2TGvPZ6F4K+XjUq13gMx14w80SVCQg== dependencies: - "@opentelemetry/core" "1.29.0" + "@opentelemetry/core" "1.30.0" "@opentelemetry/semantic-conventions" "1.28.0" -"@opentelemetry/sdk-logs@0.56.0": - version "0.56.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-logs/-/sdk-logs-0.56.0.tgz#2ce3416111d1524305f4ec92dccf9e9f9e9626cf" - integrity sha512-OS0WPBJF++R/cSl+terUjQH5PebloidB1Jbbecgg2rnCmQbTST9xsRes23bLfDQVRvmegmHqDh884h0aRdJyLw== +"@opentelemetry/sdk-logs@0.57.0": + version "0.57.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-logs/-/sdk-logs-0.57.0.tgz#cf47ce698326e3d37084ef1aa97e0a0d45cba567" + integrity sha512-6Kbxdu/QE9LWH7+WSLmYo3DjAq+c55TiCLXiXu6b/2m2muy5SyOG2m0MrGqetyRpfYSSbIqHmJoqNVTN3+2a9g== dependencies: - "@opentelemetry/api-logs" "0.56.0" - "@opentelemetry/core" "1.29.0" - "@opentelemetry/resources" "1.29.0" + "@opentelemetry/api-logs" "0.57.0" + "@opentelemetry/core" "1.30.0" + "@opentelemetry/resources" "1.30.0" -"@opentelemetry/sdk-metrics@1.29.0": - version "1.29.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.29.0.tgz#26b9891e47715c0caaaa4d4e8b536685e1937a06" - integrity sha512-MkVtuzDjXZaUJSuJlHn6BSXjcQlMvHcsDV7LjY4P6AJeffMa4+kIGDjzsCf6DkAh6Vqlwag5EWEam3KZOX5Drw== +"@opentelemetry/sdk-metrics@1.30.0": + version "1.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.30.0.tgz#2a2aaa5d3a67cad5dbbfcf34cf7d990d11d109df" + integrity sha512-5kcj6APyRMvv6dEIP5plz2qfJAD4OMipBRT11u/pa1a68rHKI2Ln+iXVkAGKgx8o7CXbD7FdPypTUY88ZQgP4Q== dependencies: - "@opentelemetry/core" "1.29.0" - "@opentelemetry/resources" "1.29.0" + "@opentelemetry/core" "1.30.0" + "@opentelemetry/resources" "1.30.0" -"@opentelemetry/sdk-trace-base@1.29.0", "@opentelemetry/sdk-trace-base@^1.25.1": - version "1.29.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.29.0.tgz#f48d95dae0e58e601d0596bd2e482122d2688fb8" - integrity sha512-hEOpAYLKXF3wGJpXOtWsxEtqBgde0SCv+w+jvr3/UusR4ll3QrENEGnSl1WDCyRrpqOQ5NCNOvZch9UFVa7MnQ== +"@opentelemetry/sdk-trace-base@1.30.0", "@opentelemetry/sdk-trace-base@^1.25.1": + version "1.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.30.0.tgz#27c68ab01b1cfb4af16356550f8091d6e727f182" + integrity sha512-RKQDaDIkV7PwizmHw+rE/FgfB2a6MBx+AEVVlAHXRG1YYxLiBpPX2KhmoB99R5vA4b72iJrjle68NDWnbrE9Dg== dependencies: - "@opentelemetry/core" "1.29.0" - "@opentelemetry/resources" "1.29.0" + "@opentelemetry/core" "1.30.0" + "@opentelemetry/resources" "1.30.0" "@opentelemetry/semantic-conventions" "1.28.0" "@opentelemetry/sdk-trace-web@^1.9.1": - version "1.29.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-web/-/sdk-trace-web-1.29.0.tgz#0d0321b511011a0174662bec821f046a55de51e8" - integrity sha512-PQVtJ76dsZ7HYBSlgZGIuxFtnKXxNbyHzMnRUxww7V2/6V/qtQN+cvNkqwPVffrUfbvClOnejo08NezAE1y+6g== + version "1.30.0" + resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-web/-/sdk-trace-web-1.30.0.tgz#d47478c45ae61dd0e5e88e284932b4be46e59c81" + integrity sha512-tSsPbaOQqmkfSkRkMnv1T8au2hwlv3v5ZUGmRwc7zIL1hokhZKg5qhqTsvrWvRENlZ7+J9+cXZFKIMNKHodyhQ== dependencies: - "@opentelemetry/core" "1.29.0" - "@opentelemetry/sdk-trace-base" "1.29.0" + "@opentelemetry/core" "1.30.0" + "@opentelemetry/sdk-trace-base" "1.30.0" "@opentelemetry/semantic-conventions" "1.28.0" "@opentelemetry/semantic-conventions@1.28.0", "@opentelemetry/semantic-conventions@^1.25.1": @@ -2380,14 +2265,14 @@ integrity sha512-UASk9zi+crv9WteK/NU4PLvOoL3OuE6BWVKNF6hPRBtYBDXQ2u5iu3O59zUlJiTVvkyuycnqrztsHVJwcK9K+Q== "@radix-ui/react-dialog@^1.0.4", "@radix-ui/react-dialog@^1.1.1": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.3.tgz#87cf49f619a6a0f6219980678be0f7c31978dee1" - integrity sha512-ujGvqQNkZ0J7caQyl8XuZRj2/TIrYcOGwqz5TeD1OMcCdfBuEMP0D12ve+8J5F9XuNUth3FAKFWo/wt0E/GJrQ== + version "1.1.4" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz#d68e977acfcc0d044b9dab47b6dd2c179d2b3191" + integrity sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA== dependencies: "@radix-ui/primitive" "1.1.1" "@radix-ui/react-compose-refs" "1.1.1" "@radix-ui/react-context" "1.1.1" - "@radix-ui/react-dismissable-layer" "1.1.2" + "@radix-ui/react-dismissable-layer" "1.1.3" "@radix-ui/react-focus-guards" "1.1.1" "@radix-ui/react-focus-scope" "1.1.1" "@radix-ui/react-id" "1.1.0" @@ -2397,24 +2282,13 @@ "@radix-ui/react-slot" "1.1.1" "@radix-ui/react-use-controllable-state" "1.1.0" aria-hidden "^1.1.1" - react-remove-scroll "2.6.0" + react-remove-scroll "^2.6.1" "@radix-ui/react-direction@1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== -"@radix-ui/react-dismissable-layer@1.1.2": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.2.tgz#771594b202f32bc8ffeb278c565f10c513814aee" - integrity sha512-kEHnlhv7wUggvhuJPkyw4qspXLJOdYoAP4dO2c8ngGuXTq1w/HZp1YeVB+NQ2KbH1iEG+pvOCGYSqh9HZOz6hg== - dependencies: - "@radix-ui/primitive" "1.1.1" - "@radix-ui/react-compose-refs" "1.1.1" - "@radix-ui/react-primitive" "2.0.1" - "@radix-ui/react-use-callback-ref" "1.1.0" - "@radix-ui/react-use-escape-keydown" "1.1.0" - "@radix-ui/react-dismissable-layer@1.1.3": version "1.1.3" resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz#4ee0f0f82d53bf5bd9db21665799bb0d1bad5ed8" @@ -2710,236 +2584,236 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.25.0.tgz#3e7eda4c0c1de6d2415343002d742ff95e38dca7" integrity sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA== -"@rollup/rollup-android-arm-eabi@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz#7f4c4d8cd5ccab6e95d6750dbe00321c1f30791e" - integrity sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ== +"@rollup/rollup-android-arm-eabi@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.2.tgz#d4c3965f18ebf567a99154f93bcf283fd527e2a9" + integrity sha512-s/8RiF4bdmGnc/J0N7lHAr5ZFJj+NdJqJ/Hj29K+c4lEdoVlukzvWXB9XpWZCdakVT0YAw8iyIqUP2iFRz5/jA== "@rollup/rollup-android-arm64@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.25.0.tgz#04f679231acf7284f1f8a1f7250d0e0944865ba8" integrity sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg== -"@rollup/rollup-android-arm64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz#17ea71695fb1518c2c324badbe431a0bd1879f2d" - integrity sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA== +"@rollup/rollup-android-arm64@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.2.tgz#cbc7e636a7aab984161fc045039bf3c6abb50083" + integrity sha512-mKRlVj1KsKWyEOwR6nwpmzakq6SgZXW4NUHNWlYSiyncJpuXk7wdLzuKdWsRoR1WLbWsZBKvsUCdCTIAqRn9cA== "@rollup/rollup-darwin-arm64@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.25.0.tgz#ecea723041621747d0772af93b54752edf26467a" integrity sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg== -"@rollup/rollup-darwin-arm64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz#dac0f0d0cfa73e7d5225ae6d303c13c8979e7999" - integrity sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ== +"@rollup/rollup-darwin-arm64@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.2.tgz#d084c6120f96749a7ddc5ef81d8740f2525abb6e" + integrity sha512-vJX+vennGwygmutk7N333lvQ/yKVAHnGoBS2xMRQgXWW8tvn46YWuTDOpKroSPR9BEW0Gqdga2DHqz8Pwk6X5w== "@rollup/rollup-darwin-x64@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.25.0.tgz#28e6e0687092f31e20982fc104779d48c643fc21" integrity sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA== -"@rollup/rollup-darwin-x64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz#8f63baa1d31784904a380d2e293fa1ddf53dd4a2" - integrity sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ== +"@rollup/rollup-darwin-x64@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.2.tgz#1393f12d5722cc39b8c014aedd4b4da8043929a9" + integrity sha512-e2rW9ng5O6+Mt3ht8fH0ljfjgSCC6ffmOipiLUgAnlK86CHIaiCdHCzHzmTkMj6vEkqAiRJ7ss6Ibn56B+RE5w== "@rollup/rollup-freebsd-arm64@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.25.0.tgz#99e9173b8aef3d1ef086983da70413988206e530" integrity sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g== -"@rollup/rollup-freebsd-arm64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz#30ed247e0df6e8858cdc6ae4090e12dbeb8ce946" - integrity sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA== +"@rollup/rollup-freebsd-arm64@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.2.tgz#1c11650970c4b52d7fb077f5a4a6e16ba5e6db4f" + integrity sha512-/xdNwZe+KesG6XJCK043EjEDZTacCtL4yurMZRLESIgHQdvtNyul3iz2Ab03ZJG0pQKbFTu681i+4ETMF9uE/Q== "@rollup/rollup-freebsd-x64@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.25.0.tgz#f3a1ef941f8d3c6b2b036484c69a7b2d3d9ebbd7" integrity sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw== -"@rollup/rollup-freebsd-x64@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz#57846f382fddbb508412ae07855b8a04c8f56282" - integrity sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ== +"@rollup/rollup-freebsd-x64@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.2.tgz#d3d79a2b96e81475571cb9bb414910450bcebe04" + integrity sha512-eXKvpThGzREuAbc6qxnArHh8l8W4AyTcL8IfEnmx+bcnmaSGgjyAHbzZvHZI2csJ+e0MYddl7DX0X7g3sAuXDQ== "@rollup/rollup-linux-arm-gnueabihf@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.25.0.tgz#9ba6adcc33f26f2a0c6ee658f0bbda4de8da2f75" integrity sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA== -"@rollup/rollup-linux-arm-gnueabihf@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz#378ca666c9dae5e6f94d1d351e7497c176e9b6df" - integrity sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA== +"@rollup/rollup-linux-arm-gnueabihf@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.2.tgz#14a39257111abbc38412805c9162819d3bb248c1" + integrity sha512-h4VgxxmzmtXLLYNDaUcQevCmPYX6zSj4SwKuzY7SR5YlnCBYsmvfYORXgiU8axhkFCDtQF3RW5LIXT8B14Qykg== "@rollup/rollup-linux-arm-musleabihf@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.25.0.tgz#62f2426fa9016ec884f4fa779d7b62d5ba02a41a" integrity sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ== -"@rollup/rollup-linux-arm-musleabihf@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz#a692eff3bab330d5c33a5d5813a090c15374cddb" - integrity sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg== +"@rollup/rollup-linux-arm-musleabihf@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.2.tgz#64304812643515c0ed83cdaf4fde034c35dbc776" + integrity sha512-EObwZ45eMmWZQ1w4N7qy4+G1lKHm6mcOwDa+P2+61qxWu1PtQJ/lz2CNJ7W3CkfgN0FQ7cBUy2tk6D5yR4KeXw== "@rollup/rollup-linux-arm64-gnu@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.25.0.tgz#f98ec111a231d35e0c6d3404e3d80f67f9d5b9f8" integrity sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A== -"@rollup/rollup-linux-arm64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz#6b1719b76088da5ac1ae1feccf48c5926b9e3db9" - integrity sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA== +"@rollup/rollup-linux-arm64-gnu@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.2.tgz#60d457954c288c168049aadb304c204d8a680236" + integrity sha512-Z7zXVHEXg1elbbYiP/29pPwlJtLeXzjrj4241/kCcECds8Zg9fDfURWbZHRIKrEriAPS8wnVtdl4ZJBvZr325w== "@rollup/rollup-linux-arm64-musl@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.25.0.tgz#4b36ffb8359f959f2c29afd187603c53368b6723" integrity sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw== -"@rollup/rollup-linux-arm64-musl@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz#865baf5b6f5ff67acb32e5a359508828e8dc5788" - integrity sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A== +"@rollup/rollup-linux-arm64-musl@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.2.tgz#17deb5058243bc5599164a9e0a899b0902310fca" + integrity sha512-TF4kxkPq+SudS/r4zGPf0G08Bl7+NZcFrUSR3484WwsHgGgJyPQRLCNrQ/R5J6VzxfEeQR9XRpc8m2t7lD6SEQ== -"@rollup/rollup-linux-loongarch64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz#23c6609ba0f7fa7a7f2038b6b6a08555a5055a87" - integrity sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA== +"@rollup/rollup-linux-loongarch64-gnu@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.2.tgz#5c65dd6557fda1f45c285cfeb4c5eda4c868341d" + integrity sha512-kO9Fv5zZuyj2zB2af4KA29QF6t7YSxKrY7sxZXfw8koDQj9bx5Tk5RjH+kWKFKok0wLGTi4bG117h31N+TIBEg== "@rollup/rollup-linux-powerpc64le-gnu@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.25.0.tgz#52f4b39e6783505d168a745b79d86474fde71680" integrity sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA== -"@rollup/rollup-linux-powerpc64le-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz#652ef0d9334a9f25b9daf85731242801cb0fc41c" - integrity sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A== +"@rollup/rollup-linux-powerpc64le-gnu@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.2.tgz#33e45cac222fa6d09891f73bfb2d5d027ec34989" + integrity sha512-gIh776X7UCBaetVJGdjXPFurGsdWwHHinwRnC5JlLADU8Yk0EdS/Y+dMO264OjJFo7MXQ5PX4xVFbxrwK8zLqA== "@rollup/rollup-linux-riscv64-gnu@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.25.0.tgz#49195be7e6a7d68d482b12461e2ea914e31ff977" integrity sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA== -"@rollup/rollup-linux-riscv64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz#1eb6651839ee6ebca64d6cc64febbd299e95e6bd" - integrity sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA== +"@rollup/rollup-linux-riscv64-gnu@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.2.tgz#1edee7a06538597720c4bf8178367d4b5651717d" + integrity sha512-YgikssQ5UNq1GoFKZydMEkhKbjlUq7G3h8j6yWXLBF24KyoA5BcMtaOUAXq5sydPmOPEqB6kCyJpyifSpCfQ0w== "@rollup/rollup-linux-s390x-gnu@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.25.0.tgz#4b8d50a205eac7b46cdcb9c50d4a6ae5994c02e0" integrity sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ== -"@rollup/rollup-linux-s390x-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz#015c52293afb3ff2a293cf0936b1d43975c1e9cd" - integrity sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg== +"@rollup/rollup-linux-s390x-gnu@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.2.tgz#0ad4aaae2fd89c3607b743c63514c4561905672b" + integrity sha512-9ouIR2vFWCyL0Z50dfnon5nOrpDdkTG9lNDs7MRaienQKlTyHcDxplmk3IbhFlutpifBSBr2H4rVILwmMLcaMA== "@rollup/rollup-linux-x64-gnu@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.25.0.tgz#dfcceebc5ccac7fc2db19471996026258c81b55f" integrity sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig== -"@rollup/rollup-linux-x64-gnu@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz#b83001b5abed2bcb5e2dbeec6a7e69b194235c1e" - integrity sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw== +"@rollup/rollup-linux-x64-gnu@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.2.tgz#ae27f8d26c02d8ce6f84275860e99678b9f3e932" + integrity sha512-ckBBNRN/F+NoSUDENDIJ2U9UWmIODgwDB/vEXCPOMcsco1niTkxTXa6D2Y/pvCnpzaidvY2qVxGzLilNs9BSzw== "@rollup/rollup-linux-x64-musl@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.25.0.tgz#192f78bad8429711d63a31dc0a7d3312e2df850e" integrity sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ== -"@rollup/rollup-linux-x64-musl@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz#6cc7c84cd4563737f8593e66f33b57d8e228805b" - integrity sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g== +"@rollup/rollup-linux-x64-musl@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.2.tgz#24ff1a64dddd75c489bd8714bcb5a659769d3e4a" + integrity sha512-jycl1wL4AgM2aBFJFlpll/kGvAjhK8GSbEmFT5v3KC3rP/b5xZ1KQmv0vQQ8Bzb2ieFQ0kZFPRMbre/l3Bu9JA== "@rollup/rollup-win32-arm64-msvc@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.25.0.tgz#f4ec076579634f780b4e5896ae7f59f3e38e0c60" integrity sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww== -"@rollup/rollup-win32-arm64-msvc@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz#631ffeee094d71279fcd1fe8072bdcf25311bc11" - integrity sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A== +"@rollup/rollup-win32-arm64-msvc@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.2.tgz#7c56efd576618db251909e21818d473cbcf96786" + integrity sha512-S2V0LlcOiYkNGlRAWZwwUdNgdZBfvsDHW0wYosYFV3c7aKgEVcbonetZXsHv7jRTTX+oY5nDYT4W6B1oUpMNOg== "@rollup/rollup-win32-ia32-msvc@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.25.0.tgz#5458eab1929827e4f805cefb90bd09ecf7eeed2b" integrity sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg== -"@rollup/rollup-win32-ia32-msvc@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz#06d1d60d5b9f718e8a6c4a43f82e3f9e3254587f" - integrity sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA== +"@rollup/rollup-win32-ia32-msvc@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.2.tgz#0b77e11129b04bb5b9bfff4b011d084a975190e0" + integrity sha512-pW8kioj9H5f/UujdoX2atFlXNQ9aCfAxFRaa+mhczwcsusm6gGrSo4z0SLvqLF5LwFqFTjiLCCzGkNK/LE0utQ== "@rollup/rollup-win32-x64-msvc@4.25.0": version "4.25.0" resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.25.0.tgz#93415e7e707e4b156d77c5950b983b58f4bc33f3" integrity sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg== -"@rollup/rollup-win32-x64-msvc@4.28.1": - version "4.28.1" - resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz#4dff5c4259ebe6c5b4a8f2c5bc3829b7a8447ff0" - integrity sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA== +"@rollup/rollup-win32-x64-msvc@4.29.2": + version "4.29.2" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.2.tgz#dc89d92418ae2efa1d70e071c686cffbcf788147" + integrity sha512-p6fTArexECPf6KnOHvJXRpAEq0ON1CBtzG/EY4zw08kCHk/kivBc5vUEtnCFNCHOpJZ2ne77fxwRLIKD4wuW2Q== "@rtsao/scc@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@rtsao/scc/-/scc-1.1.0.tgz#927dd2fae9bc3361403ac2c7a00c32ddce9ad7e8" integrity sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g== -"@sentry-internal/browser-utils@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.45.0.tgz#8e9217b8e8a4242c9a8244dce648289eaa1e38a0" - integrity sha512-MX/E/C+W5I9jkGD1PsbZ2hpCc7YuizNKmEbuGPxQPfUSIPrdE2wpo6ZfIhEbxq9m/trl1oRCN4PXi3BB7dlYYg== +"@sentry-internal/browser-utils@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.47.0.tgz#39f2766a1bbdffc2d211e2f61f8ed8c258245b3d" + integrity sha512-vOXzYzHTKkahTLDzWWIA4EiVCQ+Gk+7xGWUlNcR2ZiEPBqYZVb5MjsUozAcc7syrSUy6WicyFjcomZ3rlCVQhg== dependencies: - "@sentry/core" "8.45.0" + "@sentry/core" "8.47.0" -"@sentry-internal/feedback@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.45.0.tgz#cfd7f54d5089682a2768c1229a5efcda4d9561fe" - integrity sha512-WerpfkKrKPAlnQuqjEgKXZtrx68cla7GyOkNOeL40JQbY4/By4Qjx1atUOmgk/FdjrCLPw+jQQY9pXRpMRqqRw== +"@sentry-internal/feedback@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.47.0.tgz#22bceac03b61ab8509e79c0875fb140f214b7c4f" + integrity sha512-IAiIemTQIalxAOYhUENs9bZ8pMNgJnX3uQSuY7v0gknEqClOGpGkG04X/cxCmtJUj1acZ9ShTGDxoh55a+ggAQ== dependencies: - "@sentry/core" "8.45.0" + "@sentry/core" "8.47.0" -"@sentry-internal/replay-canvas@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.45.0.tgz#46f39402ff0cfee4ae05191af20b4e4fac6f474c" - integrity sha512-LZ8kBuzO5gutDiWnCyYEzBMDLq9PIllcsWsXRpKoau0Zqs3DbyRolI11dNnxmUSh7UW21FksxBpqn5yPmUMbag== +"@sentry-internal/replay-canvas@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.47.0.tgz#5bbd04c81235b2bf627aa216185ae1993d2102c4" + integrity sha512-M4W9UGouEeELbGbP3QsXLDVtGiQSZoWJlKwqMWyqdQgZuLoKw0S33+60t6teLVMhuQZR0UI9VJTF5coiXysnnA== dependencies: - "@sentry-internal/replay" "8.45.0" - "@sentry/core" "8.45.0" + "@sentry-internal/replay" "8.47.0" + "@sentry/core" "8.47.0" -"@sentry-internal/replay@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.45.0.tgz#e94d250de235491888694f7cf0f637114adb4b9a" - integrity sha512-SOFwFpzx0B6lxhLl2hBnxvybo7gdB5TMY8dOHMwXgk5A2+BXvSpvWXnr33yqUlBmC8R3LeFTB3C0plzM5lhkJg== +"@sentry-internal/replay@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.47.0.tgz#4f7bd359df2de25d919a378295cab67dfa05a406" + integrity sha512-G/S40ZBORj0HSMLw/uVC6YDEPN/dqVk901vf4VYfml686DEhJrZesfAfp5SydJumQ0NKZQrdtvny+BWnlI5H1w== dependencies: - "@sentry-internal/browser-utils" "8.45.0" - "@sentry/core" "8.45.0" + "@sentry-internal/browser-utils" "8.47.0" + "@sentry/core" "8.47.0" "@sentry/babel-plugin-component-annotate@2.22.7": version "2.22.7" resolved "https://registry.yarnpkg.com/@sentry/babel-plugin-component-annotate/-/babel-plugin-component-annotate-2.22.7.tgz#604c7e33d48528a13477e7af597c4d5fca51b8bd" integrity sha512-aa7XKgZMVl6l04NY+3X7BP7yvQ/s8scn8KzQfTLrGRarziTlMGrsCOBQtCNWXOPEbtxAIHpZ9dsrAn5EJSivOQ== -"@sentry/browser@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.45.0.tgz#2e8f7b8b1a7860863aae4d716b9748a21789f0e0" - integrity sha512-Y+BcfpXY1eEkOYOzgLGkx1YH940uMAymYOxfSZSvC+Vx6xHuaGT05mIFef/aeZbyu2AUs6JjdvD1BRBZlHg78w== +"@sentry/browser@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.47.0.tgz#fe0b6b65c0394f54438d6704039adeaec214ce18" + integrity sha512-K6BzHisykmbFy/wORtGyfsAlw7ShevLALzu3ReZZZ18dVubO1bjSNjkZQU9MJD5Jcb9oLwkq89n3N9XIBfvdRA== dependencies: - "@sentry-internal/browser-utils" "8.45.0" - "@sentry-internal/feedback" "8.45.0" - "@sentry-internal/replay" "8.45.0" - "@sentry-internal/replay-canvas" "8.45.0" - "@sentry/core" "8.45.0" + "@sentry-internal/browser-utils" "8.47.0" + "@sentry-internal/feedback" "8.47.0" + "@sentry-internal/replay" "8.47.0" + "@sentry-internal/replay-canvas" "8.47.0" + "@sentry/core" "8.47.0" "@sentry/bundler-plugin-core@2.22.7": version "2.22.7" @@ -3009,18 +2883,18 @@ "@sentry/cli-win32-i686" "2.39.1" "@sentry/cli-win32-x64" "2.39.1" -"@sentry/core@8.45.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.45.0.tgz#a03a1b666989898ce7fb33f9ec279ea08450b317" - integrity sha512-4YTuBipWSh4JrtSYS5GxUQBAcAgOIkEoFfFbwVcr3ivijOacJLRXTBn3rpcy1CKjBq0PHDGR+2RGRYC+bNAMxg== +"@sentry/core@8.47.0": + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.47.0.tgz#e811444552f7a91b5de573875a318a6cd4e802f8" + integrity sha512-iSEJZMe3DOcqBFZQAqgA3NB2lCWBc4Gv5x/SCri/TVg96wAlss4VrUunSI2Mp0J4jJ5nJcJ2ChqHSBAU48k3FA== "@sentry/react@^8.0.0": - version "8.45.0" - resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.45.0.tgz#9a1bfbbbb3575fffb92796acc28ad5bb93a6855a" - integrity sha512-xuJBDATJKAHOxpR5IBfGFWJxXb05GMPGGpk8UoWai1Mh50laAQ0/WW+5sDAKrCjXoA+JZ6fb3DP8EE2X93n1nw== + version "8.47.0" + resolved "https://registry.yarnpkg.com/@sentry/react/-/react-8.47.0.tgz#0d9c120b0d4a2efd6d8e8fb9acff332c63afd50d" + integrity sha512-SRk2Up+qBTow4rQGiRXViC2i4M5w/tae5w8I/rmX+IxFoPyh8wXERcLAj/8xbbRm8aR+A4i5gNgfFtrYsyFJFA== dependencies: - "@sentry/browser" "8.45.0" - "@sentry/core" "8.45.0" + "@sentry/browser" "8.47.0" + "@sentry/core" "8.47.0" hoist-non-react-statics "^3.3.2" "@sentry/vite-plugin@^2.0.0": @@ -3284,9 +3158,9 @@ undici-types "~6.19.8" "@types/node@^22.0.0": - version "22.10.2" - resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.2.tgz#a485426e6d1fdafc7b0d4c7b24e2c78182ddabb9" - integrity sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ== + version "22.10.5" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.5.tgz#95af89a3fb74a2bb41ef9927f206e6472026e48b" + integrity sha512-F8Q+SeGimwOo86fiovQh8qiXfFEh2/ocYv7tU5pJ3EXMSSxk1Joj5wefpFK2fHTf/N6HKGSxIDBT9f3gCxXPkQ== dependencies: undici-types "~6.20.0" @@ -3385,15 +3259,15 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^8.0.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.18.0.tgz#0901933326aea4443b81df3f740ca7dfc45c7bea" - integrity sha512-NR2yS7qUqCL7AIxdJUQf2MKKNDVNaig/dEB0GBLU7D+ZdHgK1NoH/3wsgO3OnPVipn51tG3MAwaODEGil70WEw== + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.19.0.tgz#2b1e1b791e21d5fc27ddc93884db066444f597b5" + integrity sha512-NggSaEZCdSrFddbctrVjkVZvFC6KGfKfNK0CU7mNK/iKHGKbzT4Wmgm08dKpcZECBu9f5FypndoMyRHkdqfT1Q== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "8.18.0" - "@typescript-eslint/type-utils" "8.18.0" - "@typescript-eslint/utils" "8.18.0" - "@typescript-eslint/visitor-keys" "8.18.0" + "@typescript-eslint/scope-manager" "8.19.0" + "@typescript-eslint/type-utils" "8.19.0" + "@typescript-eslint/utils" "8.19.0" + "@typescript-eslint/visitor-keys" "8.19.0" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" @@ -3407,14 +3281,14 @@ "@typescript-eslint/utils" "5.62.0" "@typescript-eslint/parser@^8.0.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.18.0.tgz#a1c9456cbb6a089730bf1d3fc47946c5fb5fe67b" - integrity sha512-hgUZ3kTEpVzKaK3uNibExUYm6SKKOmTU2BOxBSvOYwtJEPdVQ70kZJpPjstlnhCHcuc2WGfSbpKlb/69ttyN5Q== + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-8.19.0.tgz#f1512e6e5c491b03aabb2718b95becde22b15292" + integrity sha512-6M8taKyOETY1TKHp0x8ndycipTVgmp4xtg5QpEZzXxDhNvvHOJi5rLRkLr8SK3jTgD5l4fTlvBiRdfsuWydxBw== dependencies: - "@typescript-eslint/scope-manager" "8.18.0" - "@typescript-eslint/types" "8.18.0" - "@typescript-eslint/typescript-estree" "8.18.0" - "@typescript-eslint/visitor-keys" "8.18.0" + "@typescript-eslint/scope-manager" "8.19.0" + "@typescript-eslint/types" "8.19.0" + "@typescript-eslint/typescript-estree" "8.19.0" + "@typescript-eslint/visitor-keys" "8.19.0" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": @@ -3425,21 +3299,21 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@8.18.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.18.0.tgz#30b040cb4557804a7e2bcc65cf8fdb630c96546f" - integrity sha512-PNGcHop0jkK2WVYGotk/hxj+UFLhXtGPiGtiaWgVBVP1jhMoMCHlTyJA+hEj4rszoSdLTK3fN4oOatrL0Cp+Xw== +"@typescript-eslint/scope-manager@8.19.0": + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-8.19.0.tgz#28fa413a334f70e8b506a968531e0a7c9c3076dc" + integrity sha512-hkoJiKQS3GQ13TSMEiuNmSCvhz7ujyqD1x3ShbaETATHrck+9RaDdUbt+osXaUuns9OFwrDTTrjtwsU8gJyyRA== dependencies: - "@typescript-eslint/types" "8.18.0" - "@typescript-eslint/visitor-keys" "8.18.0" + "@typescript-eslint/types" "8.19.0" + "@typescript-eslint/visitor-keys" "8.19.0" -"@typescript-eslint/type-utils@8.18.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.18.0.tgz#6f0d12cf923b6fd95ae4d877708c0adaad93c471" - integrity sha512-er224jRepVAVLnMF2Q7MZJCq5CsdH2oqjP4dT7K6ij09Kyd+R21r7UVJrF0buMVdZS5QRhDzpvzAxHxabQadow== +"@typescript-eslint/type-utils@8.19.0": + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-8.19.0.tgz#41abd7d2e4cf93b6854b1fe6cbf416fab5abf89f" + integrity sha512-TZs0I0OSbd5Aza4qAMpp1cdCYVnER94IziudE3JU328YUHgWu9gwiwhag+fuLeJ2LkWLXI+F/182TbG+JaBdTg== dependencies: - "@typescript-eslint/typescript-estree" "8.18.0" - "@typescript-eslint/utils" "8.18.0" + "@typescript-eslint/typescript-estree" "8.19.0" + "@typescript-eslint/utils" "8.19.0" debug "^4.3.4" ts-api-utils "^1.3.0" @@ -3448,10 +3322,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@8.18.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.18.0.tgz#3afcd30def8756bc78541268ea819a043221d5f3" - integrity sha512-FNYxgyTCAnFwTrzpBGq+zrnoTO4x0c1CKYY5MuUTzpScqmY5fmsh2o3+57lqdI3NZucBDCzDgdEbIaNfAjAHQA== +"@typescript-eslint/types@8.19.0": + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-8.19.0.tgz#a190a25c5484a42b81eaad06989579fdeb478cbb" + integrity sha512-8XQ4Ss7G9WX8oaYvD4OOLCjIQYgRQxO+qCiR2V2s2GxI9AUpo7riNwo6jDhKtTcaJjT8PY54j2Yb33kWtSJsmA== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -3466,13 +3340,13 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@8.18.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.18.0.tgz#d8ca785799fbb9c700cdff1a79c046c3e633c7f9" - integrity sha512-rqQgFRu6yPkauz+ms3nQpohwejS8bvgbPyIDq13cgEDbkXt4LH4OkDMT0/fN1RUtzG8e8AKJyDBoocuQh8qNeg== +"@typescript-eslint/typescript-estree@8.19.0": + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-8.19.0.tgz#6b4f48f98ffad6597379951b115710f4d68c9ccb" + integrity sha512-WW9PpDaLIFW9LCbucMSdYUuGeFUz1OkWYS/5fwZwTA+l2RwlWFdJvReQqMUMBw4yJWJOfqd7An9uwut2Oj8sLw== dependencies: - "@typescript-eslint/types" "8.18.0" - "@typescript-eslint/visitor-keys" "8.18.0" + "@typescript-eslint/types" "8.19.0" + "@typescript-eslint/visitor-keys" "8.19.0" debug "^4.3.4" fast-glob "^3.3.2" is-glob "^4.0.3" @@ -3494,15 +3368,15 @@ eslint-scope "^5.1.1" semver "^7.3.7" -"@typescript-eslint/utils@8.18.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.18.0.tgz#48f67205d42b65d895797bb7349d1be5c39a62f7" - integrity sha512-p6GLdY383i7h5b0Qrfbix3Vc3+J2k6QWw6UMUeY5JGfm3C5LbZ4QIZzJNoNOfgyRe0uuYKjvVOsO/jD4SJO+xg== +"@typescript-eslint/utils@8.19.0": + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-8.19.0.tgz#33824310e1fccc17f27fbd1030fd8bbd9a674684" + integrity sha512-PTBG+0oEMPH9jCZlfg07LCB2nYI0I317yyvXGfxnvGvw4SHIOuRnQ3kadyyXY6tGdChusIHIbM5zfIbp4M6tCg== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "8.18.0" - "@typescript-eslint/types" "8.18.0" - "@typescript-eslint/typescript-estree" "8.18.0" + "@typescript-eslint/scope-manager" "8.19.0" + "@typescript-eslint/types" "8.19.0" + "@typescript-eslint/typescript-estree" "8.19.0" "@typescript-eslint/visitor-keys@5.62.0": version "5.62.0" @@ -3512,12 +3386,12 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@8.18.0": - version "8.18.0" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.18.0.tgz#7b6d33534fa808e33a19951907231ad2ea5c36dd" - integrity sha512-pCh/qEA8Lb1wVIqNvBke8UaRjJ6wrAWkJO5yyIbs8Yx6TNGYyfNjOo61tLv+WwLvoLPp4BQ8B7AHKijl8NGUfw== +"@typescript-eslint/visitor-keys@8.19.0": + version "8.19.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-8.19.0.tgz#dc313f735e64c4979c9073f51ffcefb6d9be5c77" + integrity sha512-mCFtBbFBJDCNCWUl5y6sZSCHXw1DEFEk3c/M3nRK2a4XUB8StGFtmcEMizdjKuBzB6e/smJAAWYug3VrdLMr1w== dependencies: - "@typescript-eslint/types" "8.18.0" + "@typescript-eslint/types" "8.19.0" eslint-visitor-keys "^4.2.0" "@ungap/structured-clone@^1.2.0": @@ -3764,13 +3638,13 @@ aria-query@^5.0.0, aria-query@^5.3.2: resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.2.tgz#93f81a43480e33a338f19163a3d10a50c01dcd59" integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== -array-buffer-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz#1e5583ec16763540a27ae52eed99ff899223568f" - integrity sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg== +array-buffer-byte-length@^1.0.1, array-buffer-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz#384d12a37295aec3769ab022ad323a18a51ccf8b" + integrity sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw== dependencies: - call-bind "^1.0.5" - is-array-buffer "^3.0.4" + call-bound "^1.0.3" + is-array-buffer "^3.0.5" array-includes@^3.1.6, array-includes@^3.1.8: version "3.1.8" @@ -3813,7 +3687,17 @@ array.prototype.findlastindex@^1.2.5: es-object-atoms "^1.0.0" es-shim-unscopables "^1.0.2" -array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: +array.prototype.flat@^1.3.1: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz#534aaf9e6e8dd79fb6b9a9917f839ef1ec63afe5" + integrity sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + +array.prototype.flat@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== @@ -3833,6 +3717,16 @@ array.prototype.flatmap@^1.3.2: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" +array.prototype.flatmap@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz#712cc792ae70370ae40586264629e33aab5dd38b" + integrity sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg== + dependencies: + call-bind "^1.0.8" + define-properties "^1.2.1" + es-abstract "^1.23.5" + es-shim-unscopables "^1.0.2" + array.prototype.tosorted@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" @@ -3844,19 +3738,18 @@ array.prototype.tosorted@^1.1.4: es-errors "^1.3.0" es-shim-unscopables "^1.0.2" -arraybuffer.prototype.slice@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz#097972f4255e41bc3425e37dc3f6421cf9aefde6" - integrity sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A== +arraybuffer.prototype.slice@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz#9d760d84dbdd06d0cbf92c8849615a1a7ab3183c" + integrity sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ== dependencies: array-buffer-byte-length "^1.0.1" - call-bind "^1.0.5" + call-bind "^1.0.8" define-properties "^1.2.1" - es-abstract "^1.22.3" - es-errors "^1.2.1" - get-intrinsic "^1.2.3" + es-abstract "^1.23.5" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" is-array-buffer "^3.0.4" - is-shared-array-buffer "^1.0.2" assertion-error@^2.0.1: version "2.0.1" @@ -3908,9 +3801,9 @@ axobject-query@^4.1.0: integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== b4a@^1.6.4: - version "1.6.6" - resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.6.tgz#a4cc349a3851987c3c4ac2d7785c18744f6da9ba" - integrity sha512-5Tk1HLk6b6ctmjIkAcU/Ujv/1WqiDl0F0JdRCR80VsOcUlHcu7pWeWRlOqQLHfDEsVx9YH/aif5AG4ehoCtTmg== + version "1.6.7" + resolved "https://registry.yarnpkg.com/b4a/-/b4a-1.6.7.tgz#a99587d4ebbfbd5a6e3b21bdb5d5fa385767abe4" + integrity sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg== babel-plugin-polyfill-corejs2@^0.4.10: version "0.4.11" @@ -3950,9 +3843,9 @@ balanced-match@^1.0.0: integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== bare-events@^2.2.0: - version "2.4.2" - resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.4.2.tgz#3140cca7a0e11d49b3edc5041ab560659fd8e1f8" - integrity sha512-qMKFd2qG/36aA4GwvKq8MxnPgCQAmBWmSyLWsJcbn8v03wvIPQ/hG1Ms8bPzndZxMDoHpxez5VOS+gC9Yi24/Q== + version "2.5.1" + resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.5.1.tgz#052a96e3fc0e87cd9f226199d7f8a80cd87b6d21" + integrity sha512-Bw2PgKSrZ3uCuSV9WQ998c/GTJTd+9bWj97n7aDQMP8dP/exAZQlJeswPty0ISy+HZD+9Ex+C7CCnc9Q5QJFmQ== base-x@^5.0.0: version "5.0.0" @@ -4101,16 +3994,31 @@ cac@^6.7.14: resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== -call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" - integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== +call-bind-apply-helpers@^1.0.0, call-bind-apply-helpers@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz#32e5892e6361b29b0b545ba6f7763378daca2840" + integrity sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g== dependencies: - es-define-property "^1.0.0" es-errors "^1.3.0" function-bind "^1.1.2" + +call-bind@^1.0.2, call-bind@^1.0.7, call-bind@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.8.tgz#0736a9660f537e3388826f440d5ec45f744eaa4c" + integrity sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww== + dependencies: + call-bind-apply-helpers "^1.0.0" + es-define-property "^1.0.0" get-intrinsic "^1.2.4" - set-function-length "^1.2.1" + set-function-length "^1.2.2" + +call-bound@^1.0.2, call-bound@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/call-bound/-/call-bound-1.0.3.tgz#41cfd032b593e39176a71533ab4f384aa04fd681" + integrity sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA== + dependencies: + call-bind-apply-helpers "^1.0.1" + get-intrinsic "^1.2.6" callsites@^3.0.0: version "3.1.0" @@ -4127,7 +4035,12 @@ camelcase@^6.2.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== -caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001669, caniuse-lite@^1.0.30001688: +caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688: + version "1.0.30001690" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz#f2d15e3aaf8e18f76b2b8c1481abde063b8104c8" + integrity sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w== + +caniuse-lite@^1.0.30001669: version "1.0.30001688" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001688.tgz#f9d3ede749f083ce0db4c13db9d828adaf2e8d0a" integrity sha512-Nmqpru91cuABu/DTCXbM2NSRHzM2uVHfPnhJ/1zEAJx/ILBRVmz3pzH4N7DZqbdG0gWClsCC05Oj0mJ/1AWMbA== @@ -4228,9 +4141,9 @@ chokidar@^3.5.3: fsevents "~2.3.2" chokidar@^4.0.0: - version "4.0.1" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.1.tgz#4a6dff66798fb0f72a94f616abbd7e1a19f31d41" - integrity sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA== + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== dependencies: readdirp "^4.0.1" @@ -4318,7 +4231,7 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== -colors@1.4.0: +colors@^1.4.0: version "1.4.0" resolved "https://registry.yarnpkg.com/colors/-/colors-1.4.0.tgz#c50491479d4c1bdaed2c9ced32cf7c7dc2360f78" integrity sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA== @@ -4330,16 +4243,16 @@ combined-stream@^1.0.8: dependencies: delayed-stream "~1.0.0" +commander@^12.1.0: + version "12.1.0" + resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" + integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== + commander@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/commander/-/commander-4.1.1.tgz#9fd602bd936294e9e9ef46a3f4d6964044b18068" integrity sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA== -commander@~12.1.0: - version "12.1.0" - resolved "https://registry.yarnpkg.com/commander/-/commander-12.1.0.tgz#01423b36f501259fdaac4d0e4d60c96c991585d3" - integrity sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA== - common-tags@^1.8.0: version "1.8.2" resolved "https://registry.yarnpkg.com/common-tags/-/common-tags-1.8.2.tgz#94ebb3c076d26032745fd54face7f688ef5ac9c6" @@ -4491,30 +4404,30 @@ data-urls@^5.0.0: whatwg-mimetype "^4.0.0" whatwg-url "^14.0.0" -data-view-buffer@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.1.tgz#8ea6326efec17a2e42620696e671d7d5a8bc66b2" - integrity sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA== +data-view-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-buffer/-/data-view-buffer-1.0.2.tgz#211a03ba95ecaf7798a8c7198d79536211f88570" + integrity sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ== dependencies: - call-bind "^1.0.6" + call-bound "^1.0.3" es-errors "^1.3.0" - is-data-view "^1.0.1" + is-data-view "^1.0.2" -data-view-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz#90721ca95ff280677eb793749fce1011347669e2" - integrity sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ== +data-view-byte-length@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz#9e80f7ca52453ce3e93d25a35318767ea7704735" + integrity sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" es-errors "^1.3.0" - is-data-view "^1.0.1" + is-data-view "^1.0.2" -data-view-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz#5e0bbfb4828ed2d1b9b400cd8a7d119bca0ff18a" - integrity sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA== +data-view-byte-offset@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz#068307f9b71ab76dbbe10291389e020856606191" + integrity sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ== dependencies: - call-bind "^1.0.6" + call-bound "^1.0.2" es-errors "^1.3.0" is-data-view "^1.0.1" @@ -4684,9 +4597,9 @@ domhandler@^5.0.2, domhandler@^5.0.3: domelementtype "^2.3.0" domutils@^3.0.1, domutils@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.1.0.tgz#c47f551278d3dc4b0b1ab8cbb42d751a6f0d824e" - integrity sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA== + version "3.2.1" + resolved "https://registry.yarnpkg.com/domutils/-/domutils-3.2.1.tgz#b39f4c390a1ae6f6a2c56a5f5a16d6438b6bce28" + integrity sha512-xWXmuRnN9OMP6ptPd2+H0cCbcYBULa5YDTbMm/2lvkWvNA3O4wcW+GvzooqBuNM8yy6pl3VIAeJTUUWUbfI5Fw== dependencies: dom-serializer "^2.0.0" domelementtype "^2.3.0" @@ -4705,6 +4618,15 @@ dotenv@^16.3.1: resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.7.tgz#0e20c5b82950140aa99be360a8a5f52335f53c26" integrity sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ== +dunder-proto@^1.0.0, dunder-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/dunder-proto/-/dunder-proto-1.0.1.tgz#d7ae667e1dc83482f8b70fd0f6eefc50da30f58a" + integrity sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A== + dependencies: + call-bind-apply-helpers "^1.0.1" + es-errors "^1.3.0" + gopd "^1.2.0" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -4719,11 +4641,16 @@ easy-table@1.2.0: optionalDependencies: wcwidth "^1.0.1" -electron-to-chromium@^1.5.41, electron-to-chromium@^1.5.73: +electron-to-chromium@^1.5.41: version "1.5.73" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.73.tgz#f32956ce40947fa3c8606726a96cd8fb5bb5f720" integrity sha512-8wGNxG9tAG5KhGd3eeA0o6ixhiNdgr0DcHWm85XPCphwZgD1lIEoi6t3VERayWao7SF7AAZTw6oARGJeVjH8Kg== +electron-to-chromium@^1.5.73: + version "1.5.76" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.76.tgz#db20295c5061b68f07c8ea4dfcbd701485d94a3d" + integrity sha512-CjVQyG7n7Sr+eBXE86HIulnL5N8xZY1sgmOPGuq/F0Rr0FJq63lg0kEtOIDfZBk44FnDLf6FUJ+dsJcuiUDdDQ== + emoji-regex@^8.0.0: version "8.0.0" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" @@ -4743,9 +4670,9 @@ encoding-sniffer@^0.2.0: whatwg-encoding "^3.1.1" enhanced-resolve@^5.17.1: - version "5.17.1" - resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" - integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + version "5.18.0" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz#91eb1db193896b9801251eeff1c6980278b1e404" + integrity sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ== dependencies: graceful-fs "^4.2.4" tapable "^2.2.0" @@ -4772,89 +4699,94 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: - version "1.23.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" - integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.23.2, es-abstract@^1.23.3, es-abstract@^1.23.5, es-abstract@^1.23.6, es-abstract@^1.23.9: + version "1.23.9" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.9.tgz#5b45994b7de78dada5c1bebf1379646b32b9d606" + integrity sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA== dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" + array-buffer-byte-length "^1.0.2" + arraybuffer.prototype.slice "^1.0.4" available-typed-arrays "^1.0.7" - call-bind "^1.0.7" - data-view-buffer "^1.0.1" - data-view-byte-length "^1.0.1" - data-view-byte-offset "^1.0.0" - es-define-property "^1.0.0" + call-bind "^1.0.8" + call-bound "^1.0.3" + data-view-buffer "^1.0.2" + data-view-byte-length "^1.0.2" + data-view-byte-offset "^1.0.1" + es-define-property "^1.0.1" es-errors "^1.3.0" es-object-atoms "^1.0.0" - es-set-tostringtag "^2.0.3" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.6" - get-intrinsic "^1.2.4" - get-symbol-description "^1.0.2" - globalthis "^1.0.3" - gopd "^1.0.1" + es-set-tostringtag "^2.1.0" + es-to-primitive "^1.3.0" + function.prototype.name "^1.1.8" + get-intrinsic "^1.2.7" + get-proto "^1.0.0" + get-symbol-description "^1.1.0" + globalthis "^1.0.4" + gopd "^1.2.0" has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" + has-proto "^1.2.0" + has-symbols "^1.1.0" hasown "^2.0.2" - internal-slot "^1.0.7" - is-array-buffer "^3.0.4" + internal-slot "^1.1.0" + is-array-buffer "^3.0.5" is-callable "^1.2.7" - is-data-view "^1.0.1" - is-negative-zero "^2.0.3" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.3" - is-string "^1.0.7" - is-typed-array "^1.1.13" - is-weakref "^1.0.2" - object-inspect "^1.13.1" + is-data-view "^1.0.2" + is-regex "^1.2.1" + is-shared-array-buffer "^1.0.4" + is-string "^1.1.1" + is-typed-array "^1.1.15" + is-weakref "^1.1.0" + math-intrinsics "^1.1.0" + object-inspect "^1.13.3" object-keys "^1.1.1" - object.assign "^4.1.5" - regexp.prototype.flags "^1.5.2" - safe-array-concat "^1.1.2" - safe-regex-test "^1.0.3" - string.prototype.trim "^1.2.9" - string.prototype.trimend "^1.0.8" + object.assign "^4.1.7" + own-keys "^1.0.1" + regexp.prototype.flags "^1.5.3" + safe-array-concat "^1.1.3" + safe-push-apply "^1.0.0" + safe-regex-test "^1.1.0" + set-proto "^1.0.0" + string.prototype.trim "^1.2.10" + string.prototype.trimend "^1.0.9" string.prototype.trimstart "^1.0.8" - typed-array-buffer "^1.0.2" - typed-array-byte-length "^1.0.1" - typed-array-byte-offset "^1.0.2" - typed-array-length "^1.0.6" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.15" + typed-array-buffer "^1.0.3" + typed-array-byte-length "^1.0.3" + typed-array-byte-offset "^1.0.4" + typed-array-length "^1.0.7" + unbox-primitive "^1.1.0" + which-typed-array "^1.1.18" -es-define-property@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" - integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== - dependencies: - get-intrinsic "^1.2.4" +es-define-property@^1.0.0, es-define-property@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.1.tgz#983eb2f9a6724e9303f61addf011c72e09e0b0fa" + integrity sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g== -es-errors@^1.2.1, es-errors@^1.3.0: +es-errors@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== -es-iterator-helpers@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.1.0.tgz#f6d745d342aea214fe09497e7152170dc333a7a6" - integrity sha512-/SurEfycdyssORP/E+bj4sEu1CWw4EmLDsHynHwSXQ7utgbrMRWW195pTrCjFgFCddf/UkYm3oqKPRq5i8bJbw== +es-iterator-helpers@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz#d1dd0f58129054c0ad922e6a9a1e65eef435fe75" + integrity sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - es-abstract "^1.23.3" + es-abstract "^1.23.6" es-errors "^1.3.0" es-set-tostringtag "^2.0.3" function-bind "^1.1.2" - get-intrinsic "^1.2.4" + get-intrinsic "^1.2.6" globalthis "^1.0.4" + gopd "^1.2.0" has-property-descriptors "^1.0.2" - has-proto "^1.0.3" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - iterator.prototype "^1.1.3" - safe-array-concat "^1.1.2" + has-proto "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + iterator.prototype "^1.1.4" + safe-array-concat "^1.1.3" es-module-lexer@^1.5.4: version "1.5.4" @@ -4868,14 +4800,15 @@ es-object-atoms@^1.0.0: dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz#8bb60f0a440c2e4281962428438d58545af39777" - integrity sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ== +es-set-tostringtag@^2.0.3, es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== dependencies: - get-intrinsic "^1.2.4" + es-errors "^1.3.0" + get-intrinsic "^1.2.6" has-tostringtag "^1.0.2" - hasown "^2.0.1" + hasown "^2.0.2" es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: version "1.0.2" @@ -4884,14 +4817,14 @@ es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: dependencies: hasown "^2.0.0" -es-to-primitive@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" - integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== +es-to-primitive@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.3.0.tgz#96c89c82cc49fd8794a24835ba3e1ff87f214e18" + integrity sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g== dependencies: - is-callable "^1.1.4" - is-date-object "^1.0.1" - is-symbol "^1.0.2" + is-callable "^1.2.7" + is-date-object "^1.0.5" + is-symbol "^1.0.4" esbuild@^0.21.3: version "0.21.5" @@ -4922,65 +4855,36 @@ esbuild@^0.21.3: "@esbuild/win32-ia32" "0.21.5" "@esbuild/win32-x64" "0.21.5" -esbuild@^0.23.0: - version "0.23.0" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.23.0.tgz#de06002d48424d9fdb7eb52dbe8e95927f852599" - integrity sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA== +esbuild@^0.24.0, esbuild@^0.24.2: + version "0.24.2" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d" + integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA== optionalDependencies: - "@esbuild/aix-ppc64" "0.23.0" - "@esbuild/android-arm" "0.23.0" - "@esbuild/android-arm64" "0.23.0" - "@esbuild/android-x64" "0.23.0" - "@esbuild/darwin-arm64" "0.23.0" - "@esbuild/darwin-x64" "0.23.0" - "@esbuild/freebsd-arm64" "0.23.0" - "@esbuild/freebsd-x64" "0.23.0" - "@esbuild/linux-arm" "0.23.0" - "@esbuild/linux-arm64" "0.23.0" - "@esbuild/linux-ia32" "0.23.0" - "@esbuild/linux-loong64" "0.23.0" - "@esbuild/linux-mips64el" "0.23.0" - "@esbuild/linux-ppc64" "0.23.0" - "@esbuild/linux-riscv64" "0.23.0" - "@esbuild/linux-s390x" "0.23.0" - "@esbuild/linux-x64" "0.23.0" - "@esbuild/netbsd-x64" "0.23.0" - "@esbuild/openbsd-arm64" "0.23.0" - "@esbuild/openbsd-x64" "0.23.0" - "@esbuild/sunos-x64" "0.23.0" - "@esbuild/win32-arm64" "0.23.0" - "@esbuild/win32-ia32" "0.23.0" - "@esbuild/win32-x64" "0.23.0" - -esbuild@^0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.0.tgz#f2d470596885fcb2e91c21eb3da3b3c89c0b55e7" - integrity sha512-FuLPevChGDshgSicjisSooU0cemp/sGXR841D5LHMB7mTVOmsEHcAxaH3irL53+8YDIeVNQEySh4DaYU/iuPqQ== - optionalDependencies: - "@esbuild/aix-ppc64" "0.24.0" - "@esbuild/android-arm" "0.24.0" - "@esbuild/android-arm64" "0.24.0" - "@esbuild/android-x64" "0.24.0" - "@esbuild/darwin-arm64" "0.24.0" - "@esbuild/darwin-x64" "0.24.0" - "@esbuild/freebsd-arm64" "0.24.0" - "@esbuild/freebsd-x64" "0.24.0" - "@esbuild/linux-arm" "0.24.0" - "@esbuild/linux-arm64" "0.24.0" - "@esbuild/linux-ia32" "0.24.0" - "@esbuild/linux-loong64" "0.24.0" - "@esbuild/linux-mips64el" "0.24.0" - "@esbuild/linux-ppc64" "0.24.0" - "@esbuild/linux-riscv64" "0.24.0" - "@esbuild/linux-s390x" "0.24.0" - "@esbuild/linux-x64" "0.24.0" - "@esbuild/netbsd-x64" "0.24.0" - "@esbuild/openbsd-arm64" "0.24.0" - "@esbuild/openbsd-x64" "0.24.0" - "@esbuild/sunos-x64" "0.24.0" - "@esbuild/win32-arm64" "0.24.0" - "@esbuild/win32-ia32" "0.24.0" - "@esbuild/win32-x64" "0.24.0" + "@esbuild/aix-ppc64" "0.24.2" + "@esbuild/android-arm" "0.24.2" + "@esbuild/android-arm64" "0.24.2" + "@esbuild/android-x64" "0.24.2" + "@esbuild/darwin-arm64" "0.24.2" + "@esbuild/darwin-x64" "0.24.2" + "@esbuild/freebsd-arm64" "0.24.2" + "@esbuild/freebsd-x64" "0.24.2" + "@esbuild/linux-arm" "0.24.2" + "@esbuild/linux-arm64" "0.24.2" + "@esbuild/linux-ia32" "0.24.2" + "@esbuild/linux-loong64" "0.24.2" + "@esbuild/linux-mips64el" "0.24.2" + "@esbuild/linux-ppc64" "0.24.2" + "@esbuild/linux-riscv64" "0.24.2" + "@esbuild/linux-s390x" "0.24.2" + "@esbuild/linux-x64" "0.24.2" + "@esbuild/netbsd-arm64" "0.24.2" + "@esbuild/netbsd-x64" "0.24.2" + "@esbuild/openbsd-arm64" "0.24.2" + "@esbuild/openbsd-x64" "0.24.2" + "@esbuild/sunos-x64" "0.24.2" + "@esbuild/win32-arm64" "0.24.2" + "@esbuild/win32-ia32" "0.24.2" + "@esbuild/win32-x64" "0.24.2" escalade@^3.1.1, escalade@^3.2.0: version "3.2.0" @@ -5094,27 +4998,27 @@ eslint-plugin-react-hooks@^5.0.0: integrity sha512-mpJRtPgHN2tNAvZ35AMfqeB3Xqeo273QxrHJsbBEPWODRM4r0yB6jfoROqKEYrOn27UtRPpcpHc2UqyBSuUNTw== eslint-plugin-react@^7.29.4: - version "7.37.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.2.tgz#cd0935987876ba2900df2f58339f6d92305acc7a" - integrity sha512-EsTAnj9fLVr/GZleBLFbj/sSuXeWmp1eXIN60ceYnZveqEaUCyW4X+Vh4WTdUhCkW4xutXYqTXCUSyqD4rB75w== + version "7.37.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.37.3.tgz#567549e9251533975c4ea9706f986c3a64832031" + integrity sha512-DomWuTQPFYZwF/7c9W2fkKkStqZmBd3uugfqBYLdkZ3Hii23WzZuOLUskGxB8qkSKqftxEeGL1TB2kMhrce0jA== dependencies: array-includes "^3.1.8" array.prototype.findlast "^1.2.5" - array.prototype.flatmap "^1.3.2" + array.prototype.flatmap "^1.3.3" array.prototype.tosorted "^1.1.4" doctrine "^2.1.0" - es-iterator-helpers "^1.1.0" + es-iterator-helpers "^1.2.1" estraverse "^5.3.0" hasown "^2.0.2" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" object.entries "^1.1.8" object.fromentries "^2.0.8" - object.values "^1.2.0" + object.values "^1.2.1" prop-types "^15.8.1" resolve "^2.0.0-next.5" semver "^6.3.1" - string.prototype.matchall "^4.0.11" + string.prototype.matchall "^4.0.12" string.prototype.repeat "^1.0.0" eslint-plugin-rxjs@^5.0.3: @@ -5294,7 +5198,7 @@ fast-fifo@^1.3.2: resolved "https://registry.yarnpkg.com/fast-fifo/-/fast-fifo-1.3.2.tgz#286e31de96eb96d38a97899815740ba2a4f3640c" integrity sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ== -fast-glob@^3.2.9, fast-glob@^3.3.2: +fast-glob@^3.2.9: version "3.3.2" resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== @@ -5305,6 +5209,17 @@ fast-glob@^3.2.9, fast-glob@^3.3.2: merge2 "^1.3.0" micromatch "^4.0.4" +fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + fast-json-stable-stringify@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" @@ -5316,9 +5231,9 @@ fast-levenshtein@^2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.13.0, fastq@^1.6.0: - version "1.17.1" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.1.tgz#2a523f07a4e7b1e81a42b91b8bf2254107753b47" - integrity sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w== + version "1.18.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.18.0.tgz#d631d7e25faffea81887fe5ea8c9010e1b36fee0" + integrity sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw== dependencies: reusify "^1.0.4" @@ -5400,7 +5315,7 @@ fraction.js@^4.3.7: resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7" integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew== -fs-extra@^11.1.0: +fs-extra@^11.2.0: version "11.2.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-11.2.0.tgz#e70e17dfad64232287d01929399e0ea7c86b0e5b" integrity sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw== @@ -5463,15 +5378,17 @@ function-bind@^1.1.2: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== -function.prototype.name@^1.1.6: - version "1.1.6" - resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" - integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== +function.prototype.name@^1.1.6, function.prototype.name@^1.1.8: + version "1.1.8" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.8.tgz#e68e1df7b259a5c949eeef95cdbde53edffabb78" + integrity sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" functions-have-names "^1.2.3" + hasown "^2.0.2" + is-callable "^1.2.7" functions-have-names@^1.2.3: version "1.2.3" @@ -5488,30 +5405,43 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: - version "1.2.4" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" - integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== +get-intrinsic@^1.2.4, get-intrinsic@^1.2.5, get-intrinsic@^1.2.6, get-intrinsic@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.7.tgz#dcfcb33d3272e15f445d15124bc0a216189b9044" + integrity sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA== dependencies: + call-bind-apply-helpers "^1.0.1" + es-define-property "^1.0.1" es-errors "^1.3.0" + es-object-atoms "^1.0.0" function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" + get-proto "^1.0.0" + gopd "^1.2.0" + has-symbols "^1.1.0" + hasown "^2.0.2" + math-intrinsics "^1.1.0" get-nonce@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/get-nonce/-/get-nonce-1.0.1.tgz#fdf3f0278073820d2ce9426c18f07481b1e0cdf3" integrity sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q== -get-symbol-description@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.2.tgz#533744d5aa20aca4e079c8e5daf7fd44202821f5" - integrity sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg== +get-proto@^1.0.0, get-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/get-proto/-/get-proto-1.0.1.tgz#150b3f2743869ef3e851ec0c49d15b1d14d00ee1" + integrity sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g== dependencies: - call-bind "^1.0.5" + dunder-proto "^1.0.1" + es-object-atoms "^1.0.0" + +get-symbol-description@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.1.0.tgz#7bdd54e0befe8ffc9f3b4e203220d9f1e881b6ee" + integrity sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg== + dependencies: + call-bound "^1.0.3" es-errors "^1.3.0" - get-intrinsic "^1.2.4" + get-intrinsic "^1.2.6" glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" @@ -5597,7 +5527,7 @@ globals@^15.9.0: resolved "https://registry.yarnpkg.com/globals/-/globals-15.12.0.tgz#1811872883ad8f41055b61457a130221297de5b5" integrity sha512-1+gLErljJFhbOVyaetcwJiJ4+eLe45S2E7P5UiZ9xGfeq3ATQf5DOv9G7MH3gGbKQLkzmNh2DxfZwLdw+j6oTQ== -globalthis@^1.0.3, globalthis@^1.0.4: +globalthis@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.4.tgz#7430ed3a975d97bfb59bcce41f5cabbafa651236" integrity sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ== @@ -5617,12 +5547,10 @@ globby@^11.1.0: merge2 "^1.4.1" slash "^3.0.0" -gopd@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" - integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== - dependencies: - get-intrinsic "^1.1.3" +gopd@^1.0.1, gopd@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.2.0.tgz#89f56b8217bdbc8802bd299df6d7f1081d7e51a1" + integrity sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg== graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.10, graceful-fs@^4.2.11, graceful-fs@^4.2.4, graceful-fs@^4.2.8: version "4.2.11" @@ -5641,10 +5569,10 @@ gulp-sort@^2.0.0: dependencies: through2 "^2.0.1" -has-bigints@^1.0.1, has-bigints@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" - integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== +has-bigints@^1.0.2: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.1.0.tgz#28607e965ac967e03cd2a2c70a2636a1edad49fe" + integrity sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg== has-flag@^3.0.0: version "3.0.0" @@ -5663,24 +5591,26 @@ has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: dependencies: es-define-property "^1.0.0" -has-proto@^1.0.1, has-proto@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" - integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== +has-proto@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.2.0.tgz#5de5a6eabd95fdffd9818b43055e8065e39fe9d5" + integrity sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ== + dependencies: + dunder-proto "^1.0.0" -has-symbols@^1.0.2, has-symbols@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" - integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== +has-symbols@^1.0.3, has-symbols@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.1.0.tgz#fc9c6a783a084951d0b971fe1018de813707a338" + integrity sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ== -has-tostringtag@^1.0.0, has-tostringtag@^1.0.2: +has-tostringtag@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.2.tgz#2cdc42d40bef2e5b4eeab7c01a73c54ce7ab5abc" integrity sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw== dependencies: has-symbols "^1.0.3" -hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: +hasown@^2.0.0, hasown@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== @@ -5787,35 +5717,42 @@ i18next-browser-languagedetector@^8.0.0: "@babel/runtime" "^7.23.2" i18next-parser@^9.0.0: - version "9.0.2" - resolved "https://registry.yarnpkg.com/i18next-parser/-/i18next-parser-9.0.2.tgz#f9d627422d33c352967556c8724975d58f1f5a95" - integrity sha512-Q1yTZljBp1DcVAQD7LxduEqFRpjIeZc+5VnQ+gU8qG9WvY3U5rqK0IVONRWNtngh3orb197bfy1Sz4wlwcplxg== + version "9.1.0" + resolved "https://registry.yarnpkg.com/i18next-parser/-/i18next-parser-9.1.0.tgz#e1cc3f42c4b2e1b1013f1ad30e69f076a280af72" + integrity sha512-HuuTdZ7VoDHtBnB8x9Vwt/DT4XgflGkRgIDhmjxy5Aa6YYzaRpkMqIcR3GDO+LVX09CYG9K+T10x+JeZfsl4sw== dependencies: - "@babel/runtime" "^7.23.2" + "@babel/runtime" "^7.25.0" broccoli-plugin "^4.0.7" cheerio "^1.0.0" - colors "1.4.0" - commander "~12.1.0" + colors "^1.4.0" + commander "^12.1.0" eol "^0.9.1" - esbuild "^0.23.0" - fs-extra "^11.1.0" + esbuild "^0.24.0" + fs-extra "^11.2.0" gulp-sort "^2.0.0" - i18next "^23.5.1" - js-yaml "4.1.0" - lilconfig "^3.0.0" - rsvp "^4.8.2" + i18next "^23.5.1 || ^24.2.0" + js-yaml "^4.1.0" + lilconfig "^3.1.2" + rsvp "^4.8.5" sort-keys "^5.0.0" typescript "^5.0.4" - vinyl "~3.0.0" + vinyl "^3.0.0" vinyl-fs "^4.0.0" -i18next@^23.0.0, i18next@^23.5.1: +i18next@^23.0.0: version "23.16.8" resolved "https://registry.yarnpkg.com/i18next/-/i18next-23.16.8.tgz#3ae1373d344c2393f465556f394aba5a9233b93a" integrity sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg== dependencies: "@babel/runtime" "^7.23.2" +"i18next@^23.5.1 || ^24.2.0": + version "24.2.0" + resolved "https://registry.yarnpkg.com/i18next/-/i18next-24.2.0.tgz#344c15a6f3b43d02aed78e2b08532e5b170951b4" + integrity sha512-ArJJTS1lV6lgKH7yEf4EpgNZ7+THl7bsGxxougPYiXRTJ/Fe1j08/TBpV9QsXCIYVfdE/HWG/xLezJ5DOlfBOA== + dependencies: + "@babel/runtime" "^7.23.2" + iconv-lite@0.6.3, iconv-lite@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501" @@ -5869,27 +5806,28 @@ inherits@2, inherits@^2.0.3, inherits@^2.0.4, inherits@~2.0.3: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== -internal-slot@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802" - integrity sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g== +internal-slot@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.1.0.tgz#1eac91762947d2f7056bc838d93e13b2e9604961" + integrity sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw== dependencies: es-errors "^1.3.0" - hasown "^2.0.0" - side-channel "^1.0.4" + hasown "^2.0.2" + side-channel "^1.1.0" interpret@^1.0.0: version "1.4.0" resolved "https://registry.yarnpkg.com/interpret/-/interpret-1.4.0.tgz#665ab8bc4da27a774a40584e812e3e0fa45b1a1e" integrity sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA== -is-array-buffer@^3.0.4: - version "3.0.4" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.4.tgz#7a1f92b3d61edd2bc65d24f130530ea93d7fae98" - integrity sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw== +is-array-buffer@^3.0.4, is-array-buffer@^3.0.5: + version "3.0.5" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.5.tgz#65742e1e687bd2cc666253068fd8707fe4d44280" + integrity sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" + call-bind "^1.0.8" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" is-arrayish@^0.2.1: version "0.2.1" @@ -5897,18 +5835,21 @@ is-arrayish@^0.2.1: integrity sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg== is-async-function@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.0.0.tgz#8e4418efd3e5d3a6ebb0164c05ef5afb69aa9646" - integrity sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA== + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-async-function/-/is-async-function-2.1.0.tgz#1d1080612c493608e93168fc4458c245074c06a6" + integrity sha512-GExz9MtyhlZyXYLxzlJRj5WUCE661zhDa1Yna52CN57AJsymh+DvXXjyveSioqSRdxvUrdKdvqB1b5cVKsNpWQ== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.1" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" -is-bigint@^1.0.1: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" - integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== +is-bigint@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.1.0.tgz#dda7a3445df57a42583db4228682eba7c4170672" + integrity sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ== dependencies: - has-bigints "^1.0.1" + has-bigints "^1.0.2" is-binary-path@~2.1.0: version "2.1.0" @@ -5917,13 +5858,13 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" -is-boolean-object@^1.1.0: - version "1.1.2" - resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" - integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== +is-boolean-object@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.2.1.tgz#c20d0c654be05da4fbc23c562635c019e93daf89" + integrity sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + has-tostringtag "^1.0.2" is-builtin-module@^3.2.1: version "3.2.1" @@ -5932,43 +5873,53 @@ is-builtin-module@^3.2.1: dependencies: builtin-modules "^3.3.0" -is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: +is-callable@^1.1.3, is-callable@^1.2.7: version "1.2.7" resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== -is-core-module@^2.13.0, is-core-module@^2.15.1: +is-core-module@^2.13.0: + version "2.16.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4" + integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w== + dependencies: + hasown "^2.0.2" + +is-core-module@^2.15.1: version "2.15.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.15.1.tgz#a7363a25bee942fefab0de13bf6aa372c82dcc37" integrity sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ== dependencies: hasown "^2.0.2" -is-data-view@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.1.tgz#4b4d3a511b70f3dc26d42c03ca9ca515d847759f" - integrity sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w== +is-data-view@^1.0.1, is-data-view@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-data-view/-/is-data-view-1.0.2.tgz#bae0a41b9688986c2188dda6657e56b8f9e63b8e" + integrity sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw== dependencies: + call-bound "^1.0.2" + get-intrinsic "^1.2.6" is-typed-array "^1.1.13" -is-date-object@^1.0.1, is-date-object@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" - integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== +is-date-object@^1.0.5, is-date-object@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.1.0.tgz#ad85541996fc7aa8b2729701d27b7319f95d82f7" + integrity sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + has-tostringtag "^1.0.2" is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== -is-finalizationregistry@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.0.2.tgz#c8749b65f17c133313e661b1289b95ad3dbd62e6" - integrity sha512-0by5vtUJs8iFQb5TYUHHPudOR+qXYIMKtiUzvLIZITZUjknFmziyBJuLhVRc+Ds0dREFlskDNJKYIdIzu/9pfw== +is-finalizationregistry@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz#eefdcdc6c94ddd0674d9c85887bf93f944a97c90" + integrity sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" is-fullwidth-code-point@^3.0.0: version "3.0.0" @@ -5976,11 +5927,14 @@ is-fullwidth-code-point@^3.0.0: integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== is-generator-function@^1.0.10: - version "1.0.10" - resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.0.10.tgz#f1558baf1ac17e0deea7c0415c438351ff2b3c72" - integrity sha512-jsEjy9l3yiXEQ+PsXdmBwEPcOxaXWLspKdplFUVI9vq1iZgIekeC0L167qeu86czQaxed3q/Uzuw0swL0irL8A== + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-generator-function/-/is-generator-function-1.1.0.tgz#bf3eeda931201394f57b5dba2800f91a238309ca" + integrity sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + get-proto "^1.0.0" + has-tostringtag "^1.0.2" + safe-regex-test "^1.1.0" is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3, is-glob@~4.0.1: version "4.0.3" @@ -5999,17 +5953,13 @@ is-negated-glob@^1.0.0: resolved "https://registry.yarnpkg.com/is-negated-glob/-/is-negated-glob-1.0.0.tgz#6910bca5da8c95e784b5751b976cf5a10fee36d2" integrity sha512-czXVVn/QEmgvej1f50BZ648vUI+em0xqMq2Sn+QncCLN4zj1UAxlT+kw/6ggQTOaZPd1HqKQGEqbpQVtJucWug== -is-negative-zero@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.3.tgz#ced903a027aca6381b777a5743069d7376a49747" - integrity sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw== - -is-number-object@^1.0.4: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" - integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== +is-number-object@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.1.1.tgz#144b21e95a1bc148205dcc2814a9134ec41b2541" + integrity sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" is-number@^7.0.0: version "7.0.0" @@ -6031,51 +5981,56 @@ is-potential-custom-element-name@^1.0.1: resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz#171ed6f19e3ac554394edf78caa05784a45bebb5" integrity sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ== -is-regex@^1.1.4: - version "1.1.4" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" - integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== +is-regex@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.2.1.tgz#76d70a3ed10ef9be48eb577887d74205bf0cad22" + integrity sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g== dependencies: - call-bind "^1.0.2" - has-tostringtag "^1.0.0" + call-bound "^1.0.2" + gopd "^1.2.0" + has-tostringtag "^1.0.2" + hasown "^2.0.2" is-set@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== -is-shared-array-buffer@^1.0.2, is-shared-array-buffer@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz#1237f1cba059cdb62431d378dcc37d9680181688" - integrity sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg== +is-shared-array-buffer@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz#9b67844bd9b7f246ba0708c3a93e34269c774f6f" + integrity sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" is-stream@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== -is-string@^1.0.5, is-string@^1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" - integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== +is-string@^1.0.7, is-string@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.1.1.tgz#92ea3f3d5c5b6e039ca8677e5ac8d07ea773cbb9" + integrity sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA== dependencies: - has-tostringtag "^1.0.0" + call-bound "^1.0.3" + has-tostringtag "^1.0.2" -is-symbol@^1.0.2, is-symbol@^1.0.3: - version "1.0.4" - resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" - integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== +is-symbol@^1.0.4, is-symbol@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.1.1.tgz#f47761279f532e2b05a7024a7506dbbedacd0634" + integrity sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w== dependencies: - has-symbols "^1.0.2" + call-bound "^1.0.2" + has-symbols "^1.1.0" + safe-regex-test "^1.1.0" -is-typed-array@^1.1.13: - version "1.1.13" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.13.tgz#d6c5ca56df62334959322d7d7dd1cca50debe229" - integrity sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw== +is-typed-array@^1.1.13, is-typed-array@^1.1.14, is-typed-array@^1.1.15: + version "1.1.15" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.15.tgz#4bfb4a45b61cee83a5a46fba778e4e8d59c0ce0b" + integrity sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ== dependencies: - which-typed-array "^1.1.14" + which-typed-array "^1.1.16" is-valid-glob@^1.0.0: version "1.0.0" @@ -6087,20 +6042,20 @@ is-weakmap@^2.0.2: resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.2.tgz#bf72615d649dfe5f699079c54b83e47d1ae19cfd" integrity sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w== -is-weakref@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" - integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== +is-weakref@^1.0.2, is-weakref@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.1.0.tgz#47e3472ae95a63fa9cf25660bcf0c181c39770ef" + integrity sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.2" is-weakset@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.3.tgz#e801519df8c0c43e12ff2834eead84ec9e624007" - integrity sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ== + version "2.0.4" + resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.4.tgz#c9f5deb0bc1906c6d6f1027f284ddf459249daca" + integrity sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ== dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" + call-bound "^1.0.3" + get-intrinsic "^1.2.6" isarray@0.0.1: version "0.0.1" @@ -6153,16 +6108,17 @@ istanbul-reports@^3.1.7: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" -iterator.prototype@^1.1.3: - version "1.1.3" - resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.3.tgz#016c2abe0be3bbdb8319852884f60908ac62bf9c" - integrity sha512-FW5iMbeQ6rBGm/oKgzq2aW4KvAGpxPzYES8N4g4xNXUKpL1mclMvOe+76AcLDTvD+Ze+sOpVhgdAQEKF4L9iGQ== +iterator.prototype@^1.1.4: + version "1.1.5" + resolved "https://registry.yarnpkg.com/iterator.prototype/-/iterator.prototype-1.1.5.tgz#12c959a29de32de0aa3bbbb801f4d777066dae39" + integrity sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g== dependencies: - define-properties "^1.2.1" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - reflect.getprototypeof "^1.0.4" - set-function-name "^2.0.1" + define-data-property "^1.1.4" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.6" + get-proto "^1.0.0" + has-symbols "^1.1.0" + set-function-name "^2.0.2" jackspeak@^3.1.2: version "3.4.3" @@ -6174,16 +6130,16 @@ jackspeak@^3.1.2: "@pkgjs/parseargs" "^0.11.0" jiti@^2.4.0: - version "2.4.1" - resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.1.tgz#4de9766ccbfa941d9b6390d2b159a4b295a52e6b" - integrity sha512-yPBThwecp1wS9DmoA4x4KR2h3QoslacnDR8ypuFM962kI4/456Iy1oHx2RAgh4jfZNdn0bctsdadceiBUgpU1g== + version "2.4.2" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560" + integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A== "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== -js-yaml@4.1.0, js-yaml@^4.1.0: +js-yaml@^4.1.0: version "4.1.0" resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== @@ -6303,9 +6259,9 @@ kleur@^3.0.3: integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== knip@^5.27.2: - version "5.40.0" - resolved "https://registry.yarnpkg.com/knip/-/knip-5.40.0.tgz#6da9113d9d0c696fc3e5dc3f3a281db57b4b828a" - integrity sha512-EzBfQDz4YBzYnMLueWnaaVr15mneqZs1c3RanttciuVuRcodlNjzAmR2nch/khlRdVABAxAdMGFxfSvhvcH1NA== + version "5.41.1" + resolved "https://registry.yarnpkg.com/knip/-/knip-5.41.1.tgz#b6e27186d38e6bccd2ef8346294e78d13322f1cd" + integrity sha512-yNpCCe2REU7U3VRvMASnXSEtfEC2HmOoDW9Vp9teQ9FktJYnuagvSZD3xWq8Ru7sPABkmvbC5TVWuMzIaeADNA== dependencies: "@nodelib/fs.walk" "1.2.8" "@snyk/github-codeowners" "1.1.0" @@ -6349,10 +6305,10 @@ levn@^0.4.1: prelude-ls "^1.2.1" type-check "~0.4.0" -lilconfig@^3.0.0: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.2.tgz#e4a7c3cb549e3a606c8dcc32e5ae1005e62c05cb" - integrity sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow== +lilconfig@^3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/lilconfig/-/lilconfig-3.1.3.tgz#a1bcfd6257f9585bf5ae14ceeebb7b559025e4c4" + integrity sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw== lines-and-columns@^1.1.6: version "1.2.4" @@ -6497,6 +6453,11 @@ matcher-collection@^2.0.0: "@types/minimatch" "^3.0.3" minimatch "^3.0.2" +math-intrinsics@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/math-intrinsics/-/math-intrinsics-1.1.0.tgz#a0dd74be81e2aa5c2f27e65ce283605ee4e2b7f9" + integrity sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g== + matrix-events-sdk@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" @@ -6535,7 +6496,7 @@ merge2@^1.3.0, merge2@^1.4.1: resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== -micromatch@^4.0.4, micromatch@^4.0.5: +micromatch@^4.0.4, micromatch@^4.0.5, micromatch@^4.0.8: version "4.0.8" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== @@ -6695,24 +6656,26 @@ object-assign@^4.1.0, object-assign@^4.1.1: resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg== -object-inspect@^1.13.1: - version "1.13.2" - resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" - integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== +object-inspect@^1.13.3: + version "1.13.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.3.tgz#f14c183de51130243d6d18ae149375ff50ea488a" + integrity sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA== object-keys@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== -object.assign@^4.1.4, object.assign@^4.1.5: - version "4.1.5" - resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.5.tgz#3a833f9ab7fdb80fc9e8d2300c803d216d8fdbb0" - integrity sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ== +object.assign@^4.1.4, object.assign@^4.1.7: + version "4.1.7" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.7.tgz#8c14ca1a424c6a561b0bb2a22f66f5049a945d3d" + integrity sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw== dependencies: - call-bind "^1.0.5" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - has-symbols "^1.0.3" + es-object-atoms "^1.0.0" + has-symbols "^1.1.0" object-keys "^1.1.1" object.entries@^1.1.8: @@ -6743,7 +6706,17 @@ object.groupby@^1.0.3: define-properties "^1.2.1" es-abstract "^1.23.2" -object.values@^1.1.6, object.values@^1.2.0: +object.values@^1.1.6, object.values@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.1.tgz#deed520a50809ff7f75a7cfd4bc64c7a038c6216" + integrity sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA== + dependencies: + call-bind "^1.0.8" + call-bound "^1.0.3" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + +object.values@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== @@ -6783,6 +6756,15 @@ optionator@^0.9.3: type-check "^0.4.0" word-wrap "^1.2.5" +own-keys@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/own-keys/-/own-keys-1.0.1.tgz#e4006910a2bf913585289676eebd6f390cf51358" + integrity sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg== + dependencies: + get-intrinsic "^1.2.6" + object-keys "^1.1.1" + safe-push-apply "^1.0.0" + p-limit@^2.2.0: version "2.3.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" @@ -6864,11 +6846,11 @@ parse-ms@^4.0.0: integrity sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw== parse5-htmlparser2-tree-adapter@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.0.0.tgz#23c2cc233bcf09bb7beba8b8a69d46b08c62c2f1" - integrity sha512-B77tOZrqqfUfnVcOrUvfdLbz4pu4RopLD/4vmu3HUPswwTA8OH0EMW9BlWR2B0RCoiZRAHEUu7IxeP1Pd1UU+g== + version "7.1.0" + resolved "https://registry.yarnpkg.com/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz#b5a806548ed893a43e24ccb42fbb78069311e81b" + integrity sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g== dependencies: - domhandler "^5.0.2" + domhandler "^5.0.3" parse5 "^7.0.0" parse5-parser-stream@^7.1.2: @@ -6879,11 +6861,11 @@ parse5-parser-stream@^7.1.2: parse5 "^7.0.0" parse5@^7.0.0, parse5@^7.1.2: - version "7.1.2" - resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.1.2.tgz#0736bebbfd77793823240a23b7fc5e010b7f8e32" - integrity sha512-Czj1WaSVpaoj0wbhMzLmWD69anp2WH7FXMB9n1Sy8/ZFF9jolSQVMu1Ij5WIyGmcBmhk7EOndpO4mIpihVqAXw== + version "7.2.1" + resolved "https://registry.yarnpkg.com/parse5/-/parse5-7.2.1.tgz#8928f55915e6125f430cc44309765bf17556a33a" + integrity sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ== dependencies: - entities "^4.4.0" + entities "^4.5.0" path-exists@^4.0.0: version "4.0.0" @@ -6984,12 +6966,12 @@ postcss-clamp@^4.1.0: dependencies: postcss-value-parser "^4.2.0" -postcss-color-functional-notation@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.6.tgz#d74c1e2294b72287eb9af079c04b7ddeff7ec5b3" - integrity sha512-wLXvm8RmLs14Z2nVpB4CWlnvaWPRcOZFltJSlcbYwSJ1EDZKsKDhPKIMecCnuU054KSmlmubkqczmm6qBPCBhA== +postcss-color-functional-notation@^7.0.7: + version "7.0.7" + resolved "https://registry.yarnpkg.com/postcss-color-functional-notation/-/postcss-color-functional-notation-7.0.7.tgz#c5362df010926f902ce4e7fb3da2a46cff175d1b" + integrity sha512-EZvAHsvyASX63vXnyXOIynkxhaHRSsdb7z6yiXKIovGXAolW4cMZ3qoh7k3VdTsLBS6VGdksGfIo3r6+waLoOw== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" @@ -7090,12 +7072,12 @@ postcss-image-set-function@^7.0.0: "@csstools/utilities" "^2.0.0" postcss-value-parser "^4.2.0" -postcss-lab-function@^7.0.6: - version "7.0.6" - resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-7.0.6.tgz#3121800fc7939ed1d9a1e87abeb33c407151252c" - integrity sha512-HPwvsoK7C949vBZ+eMyvH2cQeMr3UREoHvbtra76/UhDuiViZH6pir+z71UaJQohd7VDSVUdR6TkWYKExEc9aQ== +postcss-lab-function@^7.0.7: + version "7.0.7" + resolved "https://registry.yarnpkg.com/postcss-lab-function/-/postcss-lab-function-7.0.7.tgz#9c87c21ce5132c55824190b75d7d7adede9c2fac" + integrity sha512-+ONj2bpOQfsCKZE2T9VGMyVVdGcGUpr7u3SVfvkJlvhTRmDCfY25k4Jc8fubB9DclAPR4+w8uVtDZmdRgdAHig== dependencies: - "@csstools/css-color-parser" "^3.0.6" + "@csstools/css-color-parser" "^3.0.7" "@csstools/css-parser-algorithms" "^3.0.4" "@csstools/css-tokenizer" "^3.0.3" "@csstools/postcss-progressive-custom-properties" "^4.0.0" @@ -7142,19 +7124,19 @@ postcss-place@^10.0.0: postcss-value-parser "^4.2.0" postcss-preset-env@^10.0.0: - version "10.1.2" - resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.1.2.tgz#ea9c25d92045ef06edd78f9945d2586107aab3e3" - integrity sha512-OqUBZ9ByVfngWhMNuBEMy52Izj07oIFA6K/EOGBlaSv+P12MiE1+S2cqXtS1VuW82demQ/Tzc7typYk3uHunkA== + version "10.1.3" + resolved "https://registry.yarnpkg.com/postcss-preset-env/-/postcss-preset-env-10.1.3.tgz#7d07adef2237a643162e751b00eb1e339aa3b82e" + integrity sha512-9qzVhcMFU/MnwYHyYpJz4JhGku/4+xEiPTmhn0hj3IxnUYlEF9vbh7OC1KoLAnenS6Fgg43TKNp9xcuMeAi4Zw== dependencies: "@csstools/postcss-cascade-layers" "^5.0.1" - "@csstools/postcss-color-function" "^4.0.6" - "@csstools/postcss-color-mix-function" "^3.0.6" + "@csstools/postcss-color-function" "^4.0.7" + "@csstools/postcss-color-mix-function" "^3.0.7" "@csstools/postcss-content-alt-text" "^2.0.4" - "@csstools/postcss-exponential-functions" "^2.0.5" + "@csstools/postcss-exponential-functions" "^2.0.6" "@csstools/postcss-font-format-keywords" "^4.0.0" - "@csstools/postcss-gamut-mapping" "^2.0.6" - "@csstools/postcss-gradients-interpolation-method" "^5.0.6" - "@csstools/postcss-hwb-function" "^4.0.6" + "@csstools/postcss-gamut-mapping" "^2.0.7" + "@csstools/postcss-gradients-interpolation-method" "^5.0.7" + "@csstools/postcss-hwb-function" "^4.0.7" "@csstools/postcss-ic-unit" "^4.0.0" "@csstools/postcss-initial" "^2.0.0" "@csstools/postcss-is-pseudo-class" "^5.0.1" @@ -7164,19 +7146,19 @@ postcss-preset-env@^10.0.0: "@csstools/postcss-logical-overscroll-behavior" "^2.0.0" "@csstools/postcss-logical-resize" "^3.0.0" "@csstools/postcss-logical-viewport-units" "^3.0.3" - "@csstools/postcss-media-minmax" "^2.0.5" + "@csstools/postcss-media-minmax" "^2.0.6" "@csstools/postcss-media-queries-aspect-ratio-number-values" "^3.0.4" "@csstools/postcss-nested-calc" "^4.0.0" "@csstools/postcss-normalize-display-values" "^4.0.0" - "@csstools/postcss-oklab-function" "^4.0.6" + "@csstools/postcss-oklab-function" "^4.0.7" "@csstools/postcss-progressive-custom-properties" "^4.0.0" - "@csstools/postcss-random-function" "^1.0.1" - "@csstools/postcss-relative-color-syntax" "^3.0.6" + "@csstools/postcss-random-function" "^1.0.2" + "@csstools/postcss-relative-color-syntax" "^3.0.7" "@csstools/postcss-scope-pseudo-class" "^4.0.1" - "@csstools/postcss-sign-functions" "^1.1.0" - "@csstools/postcss-stepped-value-functions" "^4.0.5" + "@csstools/postcss-sign-functions" "^1.1.1" + "@csstools/postcss-stepped-value-functions" "^4.0.6" "@csstools/postcss-text-decoration-shorthand" "^4.0.1" - "@csstools/postcss-trigonometric-functions" "^4.0.5" + "@csstools/postcss-trigonometric-functions" "^4.0.6" "@csstools/postcss-unset-value" "^4.0.0" autoprefixer "^10.4.19" browserslist "^4.23.1" @@ -7186,7 +7168,7 @@ postcss-preset-env@^10.0.0: cssdb "^8.2.3" postcss-attribute-case-insensitive "^7.0.1" postcss-clamp "^4.1.0" - postcss-color-functional-notation "^7.0.6" + postcss-color-functional-notation "^7.0.7" postcss-color-hex-alpha "^10.0.0" postcss-color-rebeccapurple "^10.0.0" postcss-custom-media "^11.0.5" @@ -7199,7 +7181,7 @@ postcss-preset-env@^10.0.0: postcss-font-variant "^5.0.0" postcss-gap-properties "^6.0.0" postcss-image-set-function "^7.0.0" - postcss-lab-function "^7.0.6" + postcss-lab-function "^7.0.7" postcss-logical "^8.0.0" postcss-nesting "^13.0.1" postcss-opacity-percentage "^3.0.0" @@ -7395,9 +7377,9 @@ react-error-boundary@^3.1.0: "@babel/runtime" "^7.12.5" react-i18next@^15.0.0: - version "15.2.0" - resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.2.0.tgz#6b51650e1e93eb4d235a4d533fcf61b3bbf4ea10" - integrity sha512-iJNc8111EaDtVTVMKigvBtPHyrJV+KblWG73cUxqp+WmJCcwkzhWNFXmkAD5pwP2Z4woeDj/oXDdbjDsb3Gutg== + version "15.4.0" + resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-15.4.0.tgz#87c755fb6d7a567eec134e4759b022a0baacb19e" + integrity sha512-Py6UkX3zV08RTvL6ZANRoBh9sL/ne6rQq79XlkHEdd82cZr2H9usbWpUNVadJntIZP2pu3M2rL1CN+5rQYfYFw== dependencies: "@babel/runtime" "^7.25.0" html-parse-stringify "^3.0.1" @@ -7417,7 +7399,7 @@ react-refresh@^0.14.2: resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.14.2.tgz#3833da01ce32da470f1f936b9d477da5c7028bf9" integrity sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA== -react-remove-scroll-bar@^2.3.6, react-remove-scroll-bar@^2.3.7: +react-remove-scroll-bar@^2.3.7: version "2.3.8" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223" integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q== @@ -7425,17 +7407,6 @@ react-remove-scroll-bar@^2.3.6, react-remove-scroll-bar@^2.3.7: react-style-singleton "^2.2.2" tslib "^2.0.0" -react-remove-scroll@2.6.0: - version "2.6.0" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.0.tgz#fb03a0845d7768a4f1519a99fdb84983b793dc07" - integrity sha512-I2U4JVEsQenxDAKaVa3VZ/JeJZe0/2DxPWL8Tj8yLKctQJQiZM52pn/GWFpSp8dftjM3pSAHVJZscAnC/y+ySQ== - dependencies: - react-remove-scroll-bar "^2.3.6" - react-style-singleton "^2.2.1" - tslib "^2.1.0" - use-callback-ref "^1.3.0" - use-sidecar "^1.1.2" - react-remove-scroll@^2.6.1: version "2.6.2" resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz#2518d2c5112e71ea8928f1082a58459b5c7a2a97" @@ -7572,18 +7543,19 @@ redent@^3.0.0: indent-string "^4.0.0" strip-indent "^3.0.0" -reflect.getprototypeof@^1.0.4: - version "1.0.6" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" - integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== +reflect.getprototypeof@^1.0.6, reflect.getprototypeof@^1.0.9: + version "1.0.10" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz#c629219e78a3316d8b604c765ef68996964e7bf9" + integrity sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" define-properties "^1.2.1" - es-abstract "^1.23.1" + es-abstract "^1.23.9" es-errors "^1.3.0" - get-intrinsic "^1.2.4" - globalthis "^1.0.3" - which-builtin-type "^1.1.3" + es-object-atoms "^1.0.0" + get-intrinsic "^1.2.7" + get-proto "^1.0.1" + which-builtin-type "^1.2.1" regenerate-unicode-properties@^10.2.0: version "10.2.0" @@ -7619,14 +7591,16 @@ regexp-tree@^0.1.27: resolved "https://registry.yarnpkg.com/regexp-tree/-/regexp-tree-0.1.27.tgz#2198f0ef54518ffa743fe74d983b56ffd631b6cd" integrity sha512-iETxpjK6YoRWJG5o6hXLwvjYAoW+FEZn9os0PD/b6AP6xQwsa/Y7lCVgIixBbUPMfhu+i2LtdeAqVTgGlQarfA== -regexp.prototype.flags@^1.5.2: - version "1.5.3" - resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz#b3ae40b1d2499b8350ab2c3fe6ef3845d3a96f42" - integrity sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ== +regexp.prototype.flags@^1.5.3: + version "1.5.4" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz#1ad6c62d44a259007e55b3970e00f746efbcaa19" + integrity sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" define-properties "^1.2.1" es-errors "^1.3.0" + get-proto "^1.0.1" + gopd "^1.2.0" set-function-name "^2.0.2" regexpu-core@^6.1.1: @@ -7772,31 +7746,31 @@ rollup@^4.20.0: fsevents "~2.3.2" rollup@^4.23.0: - version "4.28.1" - resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.28.1.tgz#7718ba34d62b449dfc49adbfd2f312b4fe0df4de" - integrity sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg== + version "4.29.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.29.2.tgz#ff1555fd27fc20599a9b8f90527f0f43a1738e7f" + integrity sha512-tJXpsEkzsEzyAKIaB3qv3IuvTVcTN7qBw1jL4SPPXM3vzDrJgiLGFY6+HodgFaUHAJ2RYJ94zV5MKRJCoQzQeA== dependencies: "@types/estree" "1.0.6" optionalDependencies: - "@rollup/rollup-android-arm-eabi" "4.28.1" - "@rollup/rollup-android-arm64" "4.28.1" - "@rollup/rollup-darwin-arm64" "4.28.1" - "@rollup/rollup-darwin-x64" "4.28.1" - "@rollup/rollup-freebsd-arm64" "4.28.1" - "@rollup/rollup-freebsd-x64" "4.28.1" - "@rollup/rollup-linux-arm-gnueabihf" "4.28.1" - "@rollup/rollup-linux-arm-musleabihf" "4.28.1" - "@rollup/rollup-linux-arm64-gnu" "4.28.1" - "@rollup/rollup-linux-arm64-musl" "4.28.1" - "@rollup/rollup-linux-loongarch64-gnu" "4.28.1" - "@rollup/rollup-linux-powerpc64le-gnu" "4.28.1" - "@rollup/rollup-linux-riscv64-gnu" "4.28.1" - "@rollup/rollup-linux-s390x-gnu" "4.28.1" - "@rollup/rollup-linux-x64-gnu" "4.28.1" - "@rollup/rollup-linux-x64-musl" "4.28.1" - "@rollup/rollup-win32-arm64-msvc" "4.28.1" - "@rollup/rollup-win32-ia32-msvc" "4.28.1" - "@rollup/rollup-win32-x64-msvc" "4.28.1" + "@rollup/rollup-android-arm-eabi" "4.29.2" + "@rollup/rollup-android-arm64" "4.29.2" + "@rollup/rollup-darwin-arm64" "4.29.2" + "@rollup/rollup-darwin-x64" "4.29.2" + "@rollup/rollup-freebsd-arm64" "4.29.2" + "@rollup/rollup-freebsd-x64" "4.29.2" + "@rollup/rollup-linux-arm-gnueabihf" "4.29.2" + "@rollup/rollup-linux-arm-musleabihf" "4.29.2" + "@rollup/rollup-linux-arm64-gnu" "4.29.2" + "@rollup/rollup-linux-arm64-musl" "4.29.2" + "@rollup/rollup-linux-loongarch64-gnu" "4.29.2" + "@rollup/rollup-linux-powerpc64le-gnu" "4.29.2" + "@rollup/rollup-linux-riscv64-gnu" "4.29.2" + "@rollup/rollup-linux-s390x-gnu" "4.29.2" + "@rollup/rollup-linux-x64-gnu" "4.29.2" + "@rollup/rollup-linux-x64-musl" "4.29.2" + "@rollup/rollup-win32-arm64-msvc" "4.29.2" + "@rollup/rollup-win32-ia32-msvc" "4.29.2" + "@rollup/rollup-win32-x64-msvc" "4.29.2" fsevents "~2.3.2" rrweb-cssom@^0.7.1: @@ -7804,7 +7778,7 @@ rrweb-cssom@^0.7.1: resolved "https://registry.yarnpkg.com/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz#c73451a484b86dd7cfb1e0b2898df4b703183e4b" integrity sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg== -rsvp@^4.8.2: +rsvp@^4.8.5: version "4.8.5" resolved "https://registry.yarnpkg.com/rsvp/-/rsvp-4.8.5.tgz#c8f155311d167f68f21e168df71ec5b083113734" integrity sha512-nfMOlASu9OnRJo1mbEk2cz0D56a1MBNrJ7orjRZQG10XDyuvwksKbuXNp6qa+kbn839HwjwhBzhFmdsaEAfauA== @@ -7841,14 +7815,15 @@ rxjs@7.8.1, rxjs@^7.5.2, rxjs@^7.8.1: dependencies: tslib "^2.1.0" -safe-array-concat@^1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.2.tgz#81d77ee0c4e8b863635227c721278dd524c20edb" - integrity sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q== +safe-array-concat@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.3.tgz#c9e54ec4f603b0bbb8e7e5007a5ee7aecd1538c3" + integrity sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q== dependencies: - call-bind "^1.0.7" - get-intrinsic "^1.2.4" - has-symbols "^1.0.3" + call-bind "^1.0.8" + call-bound "^1.0.2" + get-intrinsic "^1.2.6" + has-symbols "^1.1.0" isarray "^2.0.5" safe-buffer@~5.1.0, safe-buffer@~5.1.1: @@ -7861,14 +7836,22 @@ safe-buffer@~5.2.0: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== -safe-regex-test@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.3.tgz#a5b4c0f06e0ab50ea2c395c14d8371232924c377" - integrity sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw== +safe-push-apply@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-push-apply/-/safe-push-apply-1.0.0.tgz#01850e981c1602d398c85081f360e4e6d03d27f5" + integrity sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA== dependencies: - call-bind "^1.0.6" es-errors "^1.3.0" - is-regex "^1.1.4" + isarray "^2.0.5" + +safe-regex-test@^1.0.3, safe-regex-test@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.1.0.tgz#7f87dfb67a3150782eaaf18583ff5d1711ac10c1" + integrity sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + is-regex "^1.2.1" "safer-buffer@>= 2.1.2 < 3.0.0": version "2.1.2" @@ -7876,9 +7859,9 @@ safe-regex-test@^1.0.3: integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== sass@^1.42.1: - version "1.83.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.0.tgz#e36842c0b88a94ed336fd16249b878a0541d536f" - integrity sha512-qsSxlayzoOjdvXMVLkzF84DJFc2HZEL/rFyGIKbbilYtAvlCxyuzUeff9LawTn4btVnLKg75Z8MMr1lxU1lfGw== + version "1.83.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.83.1.tgz#dee1ab94b47a6f9993d3195d36f556bcbda64846" + integrity sha512-EVJbDaEs4Rr3F0glJzFSOvtg2/oy2V/YrGFPqPY24UqcLDWcI9ZY5sN+qyO3c/QCZwzgfirvhXvINiJCE/OLcA== dependencies: chokidar "^4.0.0" immutable "^5.0.2" @@ -7930,7 +7913,7 @@ set-blocking@^2.0.0: resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== -set-function-length@^1.2.1: +set-function-length@^1.2.2: version "1.2.2" resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== @@ -7942,7 +7925,7 @@ set-function-length@^1.2.1: gopd "^1.0.1" has-property-descriptors "^1.0.2" -set-function-name@^2.0.1, set-function-name@^2.0.2: +set-function-name@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.2.tgz#16a705c5a0dc2f5e638ca96d8a8cd4e1c2b90985" integrity sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ== @@ -7952,6 +7935,15 @@ set-function-name@^2.0.1, set-function-name@^2.0.2: functions-have-names "^1.2.3" has-property-descriptors "^1.0.2" +set-proto@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/set-proto/-/set-proto-1.0.0.tgz#0760dbcff30b2d7e801fd6e19983e56da337565e" + integrity sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw== + dependencies: + dunder-proto "^1.0.1" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + shebang-command@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" @@ -7973,15 +7965,45 @@ shelljs@0.8.4: interpret "^1.0.0" rechoir "^0.6.2" -side-channel@^1.0.4, side-channel@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" - integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== +side-channel-list@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/side-channel-list/-/side-channel-list-1.0.0.tgz#10cb5984263115d3b7a0e336591e290a830af8ad" + integrity sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA== dependencies: - call-bind "^1.0.7" es-errors "^1.3.0" - get-intrinsic "^1.2.4" - object-inspect "^1.13.1" + object-inspect "^1.13.3" + +side-channel-map@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/side-channel-map/-/side-channel-map-1.0.1.tgz#d6bb6b37902c6fef5174e5f533fab4c732a26f42" + integrity sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + +side-channel-weakmap@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz#11dda19d5368e40ce9ec2bdc1fb0ecbc0790ecea" + integrity sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A== + dependencies: + call-bound "^1.0.2" + es-errors "^1.3.0" + get-intrinsic "^1.2.5" + object-inspect "^1.13.3" + side-channel-map "^1.0.1" + +side-channel@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.1.0.tgz#c3fcff9c4da932784873335ec9765fa94ff66bc9" + integrity sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw== + dependencies: + es-errors "^1.3.0" + object-inspect "^1.13.3" + side-channel-list "^1.0.0" + side-channel-map "^1.0.1" + side-channel-weakmap "^1.0.2" siginfo@^2.0.0: version "2.0.0" @@ -8017,9 +8039,9 @@ snake-case@^3.0.4: tslib "^2.0.3" sort-keys@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-5.0.0.tgz#5d775f8ae93ecc29bc7312bbf3acac4e36e3c446" - integrity sha512-Pdz01AvCAottHTPQGzndktFNdbRA75BgOfeT1hH+AMnJFv8lynkPi42rfeEhpx1saTEI3YNMWxfqu0sFD1G8pw== + version "5.1.0" + resolved "https://registry.yarnpkg.com/sort-keys/-/sort-keys-5.1.0.tgz#50a3f3d1ad3c5a76d043e0aeeba7299241e9aa5c" + integrity sha512-aSbHV0DaBcr7u0PVHXzM6NbZNAtrr9sF6+Qfs9UUVG7Ll3jQ6hHi8F/xqIIcn2rvIVbr0v/2zyjSdwSV47AgLQ== dependencies: is-plain-obj "^4.0.0" @@ -8077,9 +8099,9 @@ stream-composer@^1.0.2: streamx "^2.13.2" streamx@^2.12.0, streamx@^2.12.5, streamx@^2.13.2, streamx@^2.14.0: - version "2.18.0" - resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.18.0.tgz#5bc1a51eb412a667ebfdcd4e6cf6a6fc65721ac7" - integrity sha512-LLUC1TWdjVdn1weXGcSxyTR3T4+acB6tVGXT95y0nGbca4t4o/ng1wKAGTljm9VicuCVLvRlqFYXYy5GwgM7sQ== + version "2.21.1" + resolved "https://registry.yarnpkg.com/streamx/-/streamx-2.21.1.tgz#f02979d8395b6b637d08a589fb514498bed55845" + integrity sha512-PhP9wUnFLa+91CPy3N6tiQsK+gnYyUNuk15S3YG/zjYE7RuPeCjJngqnzpC31ow0lzBHQ+QGO4cNJnd0djYUsw== dependencies: fast-fifo "^1.3.2" queue-tick "^1.0.1" @@ -8123,23 +8145,24 @@ string.prototype.includes@^2.0.1: define-properties "^1.2.1" es-abstract "^1.23.3" -string.prototype.matchall@^4.0.11: - version "4.0.11" - resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" - integrity sha512-NUdh0aDavY2og7IbBPenWqR9exH+E26Sv8e0/eTe1tltDGZL+GtBkDAnnyBtmekfK6/Dq3MkcGtzXFEd1LQrtg== +string.prototype.matchall@^4.0.12: + version "4.0.12" + resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz#6c88740e49ad4956b1332a911e949583a275d4c0" + integrity sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" define-properties "^1.2.1" - es-abstract "^1.23.2" + es-abstract "^1.23.6" es-errors "^1.3.0" es-object-atoms "^1.0.0" - get-intrinsic "^1.2.4" - gopd "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.7" - regexp.prototype.flags "^1.5.2" + get-intrinsic "^1.2.6" + gopd "^1.2.0" + has-symbols "^1.1.0" + internal-slot "^1.1.0" + regexp.prototype.flags "^1.5.3" set-function-name "^2.0.2" - side-channel "^1.0.6" + side-channel "^1.1.0" string.prototype.repeat@^1.0.0: version "1.0.0" @@ -8149,22 +8172,26 @@ string.prototype.repeat@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" -string.prototype.trim@^1.2.9: - version "1.2.9" - resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz#b6fa326d72d2c78b6df02f7759c73f8f6274faa4" - integrity sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw== +string.prototype.trim@^1.2.10: + version "1.2.10" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz#40b2dd5ee94c959b4dcfb1d65ce72e90da480c81" + integrity sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.2" + define-data-property "^1.1.4" define-properties "^1.2.1" - es-abstract "^1.23.0" + es-abstract "^1.23.5" es-object-atoms "^1.0.0" + has-property-descriptors "^1.0.2" -string.prototype.trimend@^1.0.8: - version "1.0.8" - resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz#3651b8513719e8a9f48de7f2f77640b26652b229" - integrity sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ== +string.prototype.trimend@^1.0.8, string.prototype.trimend@^1.0.9: + version "1.0.9" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz#62e2731272cd285041b36596054e9f66569b6942" + integrity sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.2" define-properties "^1.2.1" es-object-atoms "^1.0.0" @@ -8298,9 +8325,9 @@ test-exclude@^7.0.1: minimatch "^9.0.4" text-decoder@^1.1.0: - version "1.1.1" - resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.1.1.tgz#5df9c224cebac4a7977720b9f083f9efa1aefde8" - integrity sha512-8zll7REEv4GDD3x4/0pW+ppIxSNs7H1J10IKFZsuOMscumCdM2a+toDGLPA3T+1+fLBql4zbt5z83GEQGGV5VA== + version "1.2.3" + resolved "https://registry.yarnpkg.com/text-decoder/-/text-decoder-1.2.3.tgz#b19da364d981b2326d5f43099c310cc80d770c65" + integrity sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA== dependencies: b4a "^1.6.4" @@ -8484,49 +8511,50 @@ type-fest@^0.8.1: resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== -typed-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz#1867c5d83b20fcb5ccf32649e5e2fc7424474ff3" - integrity sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ== +typed-array-buffer@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz#a72395450a4869ec033fd549371b47af3a2ee536" + integrity sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw== dependencies: - call-bind "^1.0.7" + call-bound "^1.0.3" es-errors "^1.3.0" - is-typed-array "^1.1.13" + is-typed-array "^1.1.14" -typed-array-byte-length@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz#d92972d3cff99a3fa2e765a28fcdc0f1d89dec67" - integrity sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw== +typed-array-byte-length@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz#8407a04f7d78684f3d252aa1a143d2b77b4160ce" + integrity sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg== dependencies: - call-bind "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.14" -typed-array-byte-offset@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz#f9ec1acb9259f395093e4567eb3c28a580d02063" - integrity sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA== +typed-array-byte-offset@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz#ae3698b8ec91a8ab945016108aef00d5bff12355" + integrity sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.7" + call-bind "^1.0.8" for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" + gopd "^1.2.0" + has-proto "^1.2.0" + is-typed-array "^1.1.15" + reflect.getprototypeof "^1.0.9" -typed-array-length@^1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" - integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== +typed-array-length@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.7.tgz#ee4deff984b64be1e118b0de8c9c877d5ce73d3d" + integrity sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg== dependencies: call-bind "^1.0.7" for-each "^0.3.3" gopd "^1.0.1" - has-proto "^1.0.3" is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" + reflect.getprototypeof "^1.0.6" typed-emitter@^2.1.0: version "2.1.0" @@ -8545,15 +8573,15 @@ typescript@^5.0.4, typescript@^5.1.6: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== -unbox-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" - integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== +unbox-primitive@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.1.0.tgz#8d9d2c9edeea8460c7f35033a88867944934d1e2" + integrity sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw== dependencies: - call-bind "^1.0.2" + call-bound "^1.0.3" has-bigints "^1.0.2" - has-symbols "^1.0.3" - which-boxed-primitive "^1.0.2" + has-symbols "^1.1.0" + which-boxed-primitive "^1.1.1" underscore.string@~3.3.4: version "3.3.6" @@ -8581,9 +8609,9 @@ undici@^5.25.4: "@fastify/busboy" "^2.0.0" undici@^6.19.5: - version "6.19.7" - resolved "https://registry.yarnpkg.com/undici/-/undici-6.19.7.tgz#7d4cf26dc689838aa8b6753a3c5c4288fc1e0216" - integrity sha512-HR3W/bMGPSr90i8AAp2C4DM3wChFdJPLrWYpIS++LxS8K+W535qftjt+4MyjNYHeWabMj1nvtmLIi7l++iq91A== + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici/-/undici-6.21.0.tgz#4b3d3afaef984e07b48e7620c34ed8a285ed4cd4" + integrity sha512-BUgJXc752Kou3oOIuU1i+yZZypyZRqNPW0vqoMPl8VaoalSfeR0D8/t4iAS3yirs79SSMTxTag+ZC86uswv+Cw== unhomoglyph@^1.0.6: version "1.0.6" @@ -8666,7 +8694,7 @@ uri-js@^4.2.2: dependencies: punycode "^2.1.0" -use-callback-ref@^1.3.0, use-callback-ref@^1.3.3: +use-callback-ref@^1.3.3: version "1.3.3" resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf" integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg== @@ -8763,7 +8791,7 @@ vinyl-sourcemap@^2.0.0: vinyl "^3.0.0" vinyl-contents "^2.0.0" -vinyl@^3.0.0, vinyl@~3.0.0: +vinyl@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/vinyl/-/vinyl-3.0.0.tgz#11e14732bf56e2faa98ffde5157fe6c13259ff30" integrity sha512-rC2VRfAVVCGEgjnxHUnpIVh3AGuk62rP3tqVrn+yab0YH7UULisC085+NYH+mnqf3Wx4SpSi1RQMwudL89N03g== @@ -8821,11 +8849,11 @@ vite@^5.0.0: fsevents "~2.3.3" vite@^6.0.0: - version "6.0.3" - resolved "https://registry.yarnpkg.com/vite/-/vite-6.0.3.tgz#cc01f403e326a9fc1e064235df8a6de084c8a491" - integrity sha512-Cmuo5P0ENTN6HxLSo6IHsjCLn/81Vgrp81oaiFFMRa8gGDj5xEjIcEpf2ZymZtZR8oU0P2JX5WuUp/rlXcHkAw== + version "6.0.7" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.0.7.tgz#f0f8c120733b04af52b4a1e3e7cb54eb851a799b" + integrity sha512-RDt8r/7qx9940f8FcOIAH9PTViRrghKaK2K1jY3RaAURrEUbm9Du1mJ72G+jlhtG3WwodnfzY8ORQZbBavZEAQ== dependencies: - esbuild "^0.24.0" + esbuild "^0.24.2" postcss "^8.4.49" rollup "^4.23.0" optionalDependencies: @@ -8960,34 +8988,35 @@ whatwg-url@^5.0.0: tr46 "~0.0.3" webidl-conversions "^3.0.0" -which-boxed-primitive@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" - integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== +which-boxed-primitive@^1.1.0, which-boxed-primitive@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz#d76ec27df7fa165f18d5808374a5fe23c29b176e" + integrity sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA== dependencies: - is-bigint "^1.0.1" - is-boolean-object "^1.1.0" - is-number-object "^1.0.4" - is-string "^1.0.5" - is-symbol "^1.0.3" + is-bigint "^1.1.0" + is-boolean-object "^1.2.1" + is-number-object "^1.1.1" + is-string "^1.1.1" + is-symbol "^1.1.1" -which-builtin-type@^1.1.3: - version "1.1.4" - resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.1.4.tgz#592796260602fc3514a1b5ee7fa29319b72380c3" - integrity sha512-bppkmBSsHFmIMSl8BO9TbsyzsvGjVoppt8xUiGzwiu/bhDCGxnpOKCxgqj6GuyHE0mINMDecBFPlOm2hzY084w== +which-builtin-type@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/which-builtin-type/-/which-builtin-type-1.2.1.tgz#89183da1b4907ab089a6b02029cc5d8d6574270e" + integrity sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q== dependencies: + call-bound "^1.0.2" function.prototype.name "^1.1.6" has-tostringtag "^1.0.2" is-async-function "^2.0.0" - is-date-object "^1.0.5" - is-finalizationregistry "^1.0.2" + is-date-object "^1.1.0" + is-finalizationregistry "^1.1.0" is-generator-function "^1.0.10" - is-regex "^1.1.4" + is-regex "^1.2.1" is-weakref "^1.0.2" isarray "^2.0.5" - which-boxed-primitive "^1.0.2" + which-boxed-primitive "^1.1.0" which-collection "^1.0.2" - which-typed-array "^1.1.15" + which-typed-array "^1.1.16" which-collection@^1.0.2: version "1.0.2" @@ -9004,15 +9033,16 @@ which-module@^2.0.0: resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== -which-typed-array@^1.1.14, which-typed-array@^1.1.15: - version "1.1.15" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.15.tgz#264859e9b11a649b388bfaaf4f767df1f779b38d" - integrity sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA== +which-typed-array@^1.1.16, which-typed-array@^1.1.18: + version "1.1.18" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.18.tgz#df2389ebf3fbb246a71390e90730a9edb6ce17ad" + integrity sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA== dependencies: available-typed-arrays "^1.0.7" - call-bind "^1.0.7" + call-bind "^1.0.8" + call-bound "^1.0.3" for-each "^0.3.3" - gopd "^1.0.1" + gopd "^1.2.0" has-tostringtag "^1.0.2" which@^2.0.1, which@^2.0.2: From 46a82b2c390ab9a4954c283d97bdfd9a43312303 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:18:12 +0000 Subject: [PATCH 11/11] Update dependency @vector-im/compound-design-tokens to v3 (#2896) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index ac693368..bc85b9c6 100644 --- a/package.json +++ b/package.json @@ -63,7 +63,7 @@ "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", "@use-gesture/react": "^10.2.11", - "@vector-im/compound-design-tokens": "^2.0.0", + "@vector-im/compound-design-tokens": "^3.0.0", "@vector-im/compound-web": "^7.2.0", "@vitejs/plugin-basic-ssl": "^1.0.1", "@vitejs/plugin-react": "^4.0.1", diff --git a/yarn.lock b/yarn.lock index a74d404a..a555346d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3411,10 +3411,10 @@ dependencies: "@use-gesture/core" "10.3.1" -"@vector-im/compound-design-tokens@^2.0.0": - version "2.1.3" - resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-2.1.3.tgz#8205ffb455a09d71a02d838f3dbb8503c4e6ec27" - integrity sha512-U4UF7MVguENf0lQnkU2a9p/3llTsLXzbzmFFOxi0h6ny2igNxZj/kROP/jXTxxV9xD4TNn3z098Bos4J/qJpBA== +"@vector-im/compound-design-tokens@^3.0.0": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-3.0.1.tgz#ee9c6ca84946b17900cdda10715b69c4b4b29264" + integrity sha512-uwpMteMxfX1xRKM5xe6IcuHAGMWYFHAD/R0ANia6JYnP2Q2ytlqUDDFa/nqNqMLYdVytbZs3bJtOfuJxmUJfgg== "@vector-im/compound-web@^7.2.0": version "7.6.1"