diff --git a/linked-dependencies/matrix-react-sdk/.eslintrc.js b/linked-dependencies/matrix-react-sdk/.eslintrc.js index 342dbde484..14afc41c07 100644 --- a/linked-dependencies/matrix-react-sdk/.eslintrc.js +++ b/linked-dependencies/matrix-react-sdk/.eslintrc.js @@ -76,6 +76,9 @@ module.exports = { group: [ "matrix-js-sdk/src/**", "!matrix-js-sdk/src/matrix", + "!matrix-js-sdk/src/crypto-api", + "!matrix-js-sdk/src/types", + "!matrix-js-sdk/src/testing", "matrix-js-sdk/lib", "matrix-js-sdk/lib/", "matrix-js-sdk/lib/**", @@ -104,13 +107,9 @@ module.exports = { "!matrix-js-sdk/src/extensible_events_v1/PollResponseEvent", "!matrix-js-sdk/src/extensible_events_v1/PollEndEvent", "!matrix-js-sdk/src/extensible_events_v1/InvalidEventError", - "!matrix-js-sdk/src/crypto-api", - "!matrix-js-sdk/src/crypto-api/verification", "!matrix-js-sdk/src/crypto", "!matrix-js-sdk/src/crypto/algorithms", - "!matrix-js-sdk/src/crypto/api", "!matrix-js-sdk/src/crypto/aes", - "!matrix-js-sdk/src/crypto/backup", "!matrix-js-sdk/src/crypto/olmlib", "!matrix-js-sdk/src/crypto/crypto", "!matrix-js-sdk/src/crypto/keybackup", @@ -120,13 +119,6 @@ module.exports = { "!matrix-js-sdk/src/crypto/CrossSigning", "!matrix-js-sdk/src/crypto/recoverykey", "!matrix-js-sdk/src/crypto/dehydration", - "!matrix-js-sdk/src/crypto/verification", - "!matrix-js-sdk/src/crypto/verification/SAS", - "!matrix-js-sdk/src/crypto/verification/QRCode", - "!matrix-js-sdk/src/crypto/verification/request", - "!matrix-js-sdk/src/crypto/verification/request/VerificationRequest", - "!matrix-js-sdk/src/common-crypto", - "!matrix-js-sdk/src/common-crypto/CryptoBackend", "!matrix-js-sdk/src/oidc", "!matrix-js-sdk/src/oidc/discovery", "!matrix-js-sdk/src/oidc/authorize", diff --git a/linked-dependencies/matrix-react-sdk/.github/workflows/netlify.yaml b/linked-dependencies/matrix-react-sdk/.github/workflows/netlify.yaml index ea393830d6..21c6f22df0 100644 --- a/linked-dependencies/matrix-react-sdk/.github/workflows/netlify.yaml +++ b/linked-dependencies/matrix-react-sdk/.github/workflows/netlify.yaml @@ -13,7 +13,7 @@ jobs: environment: Netlify steps: - name: 📝 Create Deployment - uses: bobheadxi/deployments@88ce5600046c82542f8246ac287d0a53c461bca3 # v1 + uses: bobheadxi/deployments@648679e8e4915b27893bd7dbc35cb504dc915bc8 # v1 id: deployment with: step: start diff --git a/linked-dependencies/matrix-react-sdk/CHANGELOG.md b/linked-dependencies/matrix-react-sdk/CHANGELOG.md index bdcf0d8611..440239db81 100644 --- a/linked-dependencies/matrix-react-sdk/CHANGELOG.md +++ b/linked-dependencies/matrix-react-sdk/CHANGELOG.md @@ -1,3 +1,84 @@ +Changes in [3.98.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.98.0) (2024-04-23) +===================================================================================================== +## ✨ Features + +* Make empty state copy for TAC depend on the value of the setting ([#12419](https://github.com/matrix-org/matrix-react-sdk/pull/12419)). Contributed by @dbkr. +* Linkify User Interactive Authentication errors ([#12271](https://github.com/matrix-org/matrix-react-sdk/pull/12271)). Contributed by @t3chguy. +* Add support for device dehydration v2 ([#12316](https://github.com/matrix-org/matrix-react-sdk/pull/12316)). Contributed by @uhoreg. +* Replace `SecurityCustomisations` with `CryptoSetupExtension` ([#12342](https://github.com/matrix-org/matrix-react-sdk/pull/12342)). Contributed by @thoraj. +* Add activity toggle for TAC ([#12413](https://github.com/matrix-org/matrix-react-sdk/pull/12413)). Contributed by @dbkr. +* Humanize spell check language labels ([#12409](https://github.com/matrix-org/matrix-react-sdk/pull/12409)). Contributed by @t3chguy. +* Call Guest Access, give user the option to change the acces level so they can generate a call link. ([#12401](https://github.com/matrix-org/matrix-react-sdk/pull/12401)). Contributed by @toger5. +* TAC: Release Announcement ([#12380](https://github.com/matrix-org/matrix-react-sdk/pull/12380)). Contributed by @florianduros. +* Show the call and share button if the user can create a guest link. ([#12385](https://github.com/matrix-org/matrix-react-sdk/pull/12385)). Contributed by @toger5. +* Add analytics for mark all threads unread ([#12384](https://github.com/matrix-org/matrix-react-sdk/pull/12384)). Contributed by @dbkr. +* Add `EventType.RoomEncryption` to the auto approve capabilities of Element Call widgets ([#12386](https://github.com/matrix-org/matrix-react-sdk/pull/12386)). Contributed by @toger5. + +## 🐛 Bug Fixes + +* Fix link modal not shown after access upgrade ([#12411](https://github.com/matrix-org/matrix-react-sdk/pull/12411)). Contributed by @toger5. +* Fix thread navigation in timeline ([#12412](https://github.com/matrix-org/matrix-react-sdk/pull/12412)). Contributed by @florianduros. +* Fix inability to join a `knock` room via space hierarchy view ([#12404](https://github.com/matrix-org/matrix-react-sdk/pull/12404)). Contributed by @t3chguy. +* Focus the thread panel when clicking on an item in the TAC ([#12410](https://github.com/matrix-org/matrix-react-sdk/pull/12410)). Contributed by @dbkr. +* Fix space hierarchy tile busy state being stuck after join error ([#12405](https://github.com/matrix-org/matrix-react-sdk/pull/12405)). Contributed by @t3chguy. +* Fix room topic in-app links not being handled correctly on topic dialog ([#12406](https://github.com/matrix-org/matrix-react-sdk/pull/12406)). Contributed by @t3chguy. + + +Changes in [3.97.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.97.0) (2024-04-09) +===================================================================================================== +## ✨ Features + +* Mark all threads as read button ([#12378](https://github.com/matrix-org/matrix-react-sdk/pull/12378)). Contributed by @dbkr. +* Video call meta space ([#12297](https://github.com/matrix-org/matrix-react-sdk/pull/12297)). Contributed by @toger5. +* Add leave room warning for last admin ([#9452](https://github.com/matrix-org/matrix-react-sdk/pull/9452)). Contributed by @Arnei. +* Iterate styles around Link new device via QR ([#12356](https://github.com/matrix-org/matrix-react-sdk/pull/12356)). Contributed by @t3chguy. +* Improve code-splitting of highlight.js and maplibre-gs libs ([#12349](https://github.com/matrix-org/matrix-react-sdk/pull/12349)). Contributed by @t3chguy. +* Use data-mx-color for rainbows ([#12325](https://github.com/matrix-org/matrix-react-sdk/pull/12325)). Contributed by @tulir. + +## 🐛 Bug Fixes + +* Fix external guest access url for unencrypted rooms ([#12345](https://github.com/matrix-org/matrix-react-sdk/pull/12345)). Contributed by @toger5. +* Fix video rooms not showing share link button ([#12374](https://github.com/matrix-org/matrix-react-sdk/pull/12374)). Contributed by @toger5. +* Fix space topic jumping on hover/focus ([#12377](https://github.com/matrix-org/matrix-react-sdk/pull/12377)). Contributed by @t3chguy. +* Allow popping out a Jitsi widget to respect Desktop `web_base_url` config ([#12376](https://github.com/matrix-org/matrix-react-sdk/pull/12376)). Contributed by @t3chguy. +* Remove the Lazy Loading `InvalidStoreError` Dialogs ([#12358](https://github.com/matrix-org/matrix-react-sdk/pull/12358)). Contributed by @langleyd. +* Improve readability of badges and pills ([#12360](https://github.com/matrix-org/matrix-react-sdk/pull/12360)). Contributed by @robintown. + + +Changes in [3.96.1](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.96.1) (2024-03-28) +===================================================================================================== +## 🐛 Bug Fixes + +* Revert "Make EC widget theme reactive - Update widget url when the theme changes" ([#12383](https://github.com/matrix-org/matrix-react-sdk/pull/12383)) in order to fix widgets that require authentication. + + +Changes in [3.96.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.96.0) (2024-03-26) +===================================================================================================== +## ✨ Features + +* Change user permission by using a new apply button ([#12346](https://github.com/matrix-org/matrix-react-sdk/pull/12346)). Contributed by @florianduros. +* Mark as Unread ([#12254](https://github.com/matrix-org/matrix-react-sdk/pull/12254)). Contributed by @dbkr. +* Refine the colors of some more components ([#12343](https://github.com/matrix-org/matrix-react-sdk/pull/12343)). Contributed by @robintown. +* TAC: Order rooms by most recent after notification level ([#12329](https://github.com/matrix-org/matrix-react-sdk/pull/12329)). Contributed by @florianduros. +* Make EC widget theme reactive - Update widget url when the theme changes ([#12295](https://github.com/matrix-org/matrix-react-sdk/pull/12295)). Contributed by @toger5. +* Refine styles of menus, toasts, popovers, and modals ([#12332](https://github.com/matrix-org/matrix-react-sdk/pull/12332)). Contributed by @robintown. +* Element Call: fix widget shown while its still loading (`waitForIframeLoad=false`) ([#12292](https://github.com/matrix-org/matrix-react-sdk/pull/12292)). Contributed by @toger5. +* Improve Forward Dialog a11y by switching to roving tab index interactions ([#12306](https://github.com/matrix-org/matrix-react-sdk/pull/12306)). Contributed by @t3chguy. +* Call guest access link creation to join calls as a non registered user via the EC SPA ([#12259](https://github.com/matrix-org/matrix-react-sdk/pull/12259)). Contributed by @toger5. +* Use `strong` element to semantically denote visually emphasised content ([#12320](https://github.com/matrix-org/matrix-react-sdk/pull/12320)). Contributed by @t3chguy. +* Handle up/down arrow keys as well as left/right for horizontal toolbars for improved a11y ([#12305](https://github.com/matrix-org/matrix-react-sdk/pull/12305)). Contributed by @t3chguy. + +## 🐛 Bug Fixes + +* [Backport staging] Remove the glass border from modal spinners ([#12369](https://github.com/matrix-org/matrix-react-sdk/pull/12369)). Contributed by @RiotRobot. +* Fix incorrect check for private read receipt support ([#12348](https://github.com/matrix-org/matrix-react-sdk/pull/12348)). Contributed by @tulir. +* TAC: Fix hover state when expanded ([#12337](https://github.com/matrix-org/matrix-react-sdk/pull/12337)). Contributed by @florianduros. +* Fix the image view ([#12341](https://github.com/matrix-org/matrix-react-sdk/pull/12341)). Contributed by @robintown. +* Use correct push rule to evaluate room-wide mentions ([#12318](https://github.com/matrix-org/matrix-react-sdk/pull/12318)). Contributed by @t3chguy. +* Reset power selector on API failure to prevent state mismatch ([#12319](https://github.com/matrix-org/matrix-react-sdk/pull/12319)). Contributed by @t3chguy. +* Fix spotlight opening in TAC ([#12315](https://github.com/matrix-org/matrix-react-sdk/pull/12315)). Contributed by @florianduros. + + Changes in [3.95.0](https://github.com/matrix-org/matrix-react-sdk/releases/tag/v3.95.0) (2024-03-14) ===================================================================================================== ## 🐛 Bug Fixes diff --git a/linked-dependencies/matrix-react-sdk/package.json b/linked-dependencies/matrix-react-sdk/package.json index b40e5ede6d..eae134822e 100644 --- a/linked-dependencies/matrix-react-sdk/package.json +++ b/linked-dependencies/matrix-react-sdk/package.json @@ -1,7 +1,7 @@ { "name": "matrix-react-sdk", "version": "0.0.0", - "version-matrix": "3.95.0", + "version-matrix": "3.98.0", "description": "SDK for matrix.org using React for Tchap", "author": "DINUM", "repository": { @@ -68,16 +68,16 @@ }, "dependencies": { "@babel/runtime": "^7.12.5", - "@matrix-org/analytics-events": "^0.10.0", + "@matrix-org/analytics-events": "^0.19.0", "@matrix-org/emojibase-bindings": "^1.1.2", "@matrix-org/matrix-wysiwyg": "2.17.0", "@matrix-org/olm": "3.2.15", - "@matrix-org/react-sdk-module-api": "^2.3.0", + "@matrix-org/react-sdk-module-api": "^2.4.0", "@matrix-org/spec": "^1.7.0", "@sentry/browser": "^7.0.0", "@testing-library/react-hooks": "^8.0.1", "@vector-im/compound-design-tokens": "^1.2.0", - "@vector-im/compound-web": "^3.1.1", + "@vector-im/compound-web": "^3.3.1", "@zxcvbn-ts/core": "^3.0.4", "@zxcvbn-ts/language-common": "^3.0.4", "@zxcvbn-ts/language-en": "^3.0.2", @@ -91,7 +91,7 @@ "emojibase-regex": "15.3.0", "escape-html": "^1.0.3", "file-saver": "^2.0.5", - "filesize": "10.1.0", + "filesize": "10.1.1", "gfm.css": "^1.1.2", "glob-to-regexp": "^0.4.1", "graphemer": "^1.4.0", @@ -109,7 +109,7 @@ "maplibre-gl": "^2.0.0", "matrix-encrypt-attachment": "^1.0.3", "matrix-events-sdk": "0.0.1", - "matrix-js-sdk": "31.5.0", + "matrix-js-sdk": "32.1.0", "matrix-widget-api": "^1.5.0", "memoize-one": "^6.0.0", "minimist": "^1.2.5", @@ -117,7 +117,7 @@ "opus-recorder": "^8.0.3", "pako": "^2.0.3", "png-chunks-extract": "^1.0.0", - "posthog-js": "1.106.0", + "posthog-js": "1.116.6", "proposal-temporal": "^0.9.0", "qrcode": "1.5.3", "re-resizable": "^6.9.0", @@ -129,15 +129,15 @@ "react-transition-group": "^4.4.1", "rfc4648": "^1.4.0", "sanitize-filename": "^1.6.3", - "sanitize-html": "2.12.1", + "sanitize-html": "2.13.0", "tar-js": "^0.3.0", "ua-parser-js": "^1.0.2", "uuid": "^9.0.0", "what-input": "^5.2.10" }, "devDependencies": { - "@action-validator/cli": "^0.5.3", - "@action-validator/core": "^0.5.3", + "@action-validator/cli": "^0.6.0", + "@action-validator/core": "^0.6.0", "@axe-core/playwright": "^4.8.1", "@babel/cli": "^7.12.10", "@babel/core": "^7.12.10", @@ -188,10 +188,10 @@ "@types/uuid": "^9.0.2", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", - "axe-core": "4.8.4", + "axe-core": "4.9.0", "babel-jest": "^29.0.0", "blob-polyfill": "^7.0.0", - "eslint": "8.56.0", + "eslint": "8.57.0", "eslint-config-google": "^0.14.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-deprecate": "0.8.4", @@ -224,7 +224,7 @@ "stylelint-config-standard": "^36.0.0", "stylelint-scss": "^6.0.0", "ts-node": "^10.9.1", - "typescript": "5.3.3" + "typescript": "5.4.3" }, "peerDependencies": { "postcss": "^8.4.19", diff --git a/linked-dependencies/matrix-react-sdk/playwright/Dockerfile b/linked-dependencies/matrix-react-sdk/playwright/Dockerfile index 205f0642a7..f13d7a2c68 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/Dockerfile +++ b/linked-dependencies/matrix-react-sdk/playwright/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/playwright:v1.41.2-jammy +FROM mcr.microsoft.com/playwright:v1.42.1-jammy WORKDIR /work/matrix-react-sdk VOLUME ["/work/element-web/node_modules"] diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/audio-player/audio-player.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/audio-player/audio-player.spec.ts index 11b7b53d50..4581801db5 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/audio-player/audio-player.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/audio-player/audio-player.spec.ts @@ -95,6 +95,10 @@ test.describe("Audio player", () => { .mx_MessageTimestamp { display: none !important; } + /* The MAB showing up on hover is not needed for the test */ + .mx_MessageActionBar { + display: none !important; + } `, mask: [page.locator(".mx_AudioPlayer_seek")], }; diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/crypto.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/crypto.spec.ts index d917a40839..957be58711 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/crypto.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/crypto.spec.ts @@ -121,9 +121,6 @@ test.describe("Cryptography", function () { botCreateOpts: { displayName: "Bob", autoAcceptInvites: false, - // XXX: We use a custom prefix here to coerce the Rust Crypto SDK to prefer `@user` in race resolution - // by using a prefix that is lexically after `@user` in the alphabet. - userIdPrefix: "zzz_", }, }); @@ -152,6 +149,12 @@ test.describe("Cryptography", function () { await app.client.bootstrapCrossSigning(aliceCredentials); } + await page.route("**/_matrix/client/v3/keys/signatures/upload", async (route) => { + // We delay this API otherwise the `Setting up keys` may happen too quickly and cause flakiness + await new Promise((resolve) => setTimeout(resolve, 500)); + await route.continue(); + }); + await app.settings.openUserSettings("Security & Privacy"); await page.getByRole("button", { name: "Set up Secure Backup" }).click(); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/dehydration.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/dehydration.spec.ts new file mode 100644 index 0000000000..13da99ccad --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/dehydration.spec.ts @@ -0,0 +1,114 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { Locator, type Page } from "@playwright/test"; + +import { test as base, expect } from "../../element-web-test"; +import { viewRoomSummaryByName } from "../right-panel/utils"; +import { isDendrite } from "../../plugins/homeserver/dendrite"; + +const test = base.extend({ + // eslint-disable-next-line no-empty-pattern + startHomeserverOpts: async ({}, use) => { + await use("dehydration"); + }, + config: async ({ homeserver, context }, use) => { + const wellKnown = { + "m.homeserver": { + base_url: homeserver.config.baseUrl, + }, + "org.matrix.msc3814": true, + }; + + await context.route("https://localhost/.well-known/matrix/client", async (route) => { + await route.fulfill({ json: wellKnown }); + }); + + await use({ + default_server_config: wellKnown, + }); + }, +}); + +const ROOM_NAME = "Test room"; +const NAME = "Alice"; + +function getMemberTileByName(page: Page, name: string): Locator { + return page.locator(`.mx_EntityTile, [title="${name}"]`); +} + +test.describe("Dehydration", () => { + test.skip(isDendrite, "does not yet support dehydration v2"); + + test.use({ + displayName: NAME, + }); + + test("Create dehydrated device", async ({ page, user, app }, workerInfo) => { + test.skip(workerInfo.project.name === "Legacy Crypto", "This test only works with Rust crypto."); + + // Create a backup (which will create SSSS, and dehydrated device) + + const securityTab = await app.settings.openUserSettings("Security & Privacy"); + + await expect(securityTab.getByRole("heading", { name: "Secure Backup" })).toBeVisible(); + await expect(securityTab.getByText("Offline device enabled")).not.toBeVisible(); + await securityTab.getByRole("button", { name: "Set up", exact: true }).click(); + + const currentDialogLocator = page.locator(".mx_Dialog"); + + // It's the first time and secure storage is not set up, so it will create one + await expect(currentDialogLocator.getByRole("heading", { name: "Set up Secure Backup" })).toBeVisible(); + await currentDialogLocator.getByRole("button", { name: "Continue", exact: true }).click(); + await expect(currentDialogLocator.getByRole("heading", { name: "Save your Security Key" })).toBeVisible(); + await currentDialogLocator.getByRole("button", { name: "Copy", exact: true }).click(); + await currentDialogLocator.getByRole("button", { name: "Continue", exact: true }).click(); + + await expect(currentDialogLocator.getByRole("heading", { name: "Secure Backup successful" })).toBeVisible(); + await currentDialogLocator.getByRole("button", { name: "Done", exact: true }).click(); + + // Open the settings again + await app.settings.openUserSettings("Security & Privacy"); + + // The Security tab should indicate that there is a dehydrated device present + await expect(securityTab.getByText("Offline device enabled")).toBeVisible(); + + await app.settings.closeDialog(); + + // the dehydrated device gets created with the name "Dehydrated + // device". We want to make sure that it is not visible as a normal + // device. + const sessionsTab = await app.settings.openUserSettings("Sessions"); + await expect(sessionsTab.getByText("Dehydrated device")).not.toBeVisible(); + + await app.settings.closeDialog(); + + // now check that the user info right-panel shows the dehydrated device + // as a feature rather than as a normal device + await app.client.createRoom({ name: ROOM_NAME }); + + await viewRoomSummaryByName(page, app, ROOM_NAME); + + await page.getByRole("menuitem", { name: "People" }).click(); + await expect(page.locator(".mx_MemberList")).toBeVisible(); + + await getMemberTileByName(page, NAME).click(); + await page.locator(".mx_UserInfo_devices .mx_UserInfo_expand").click(); + + await expect(page.locator(".mx_UserInfo_devices").getByText("Offline device enabled")).toBeVisible(); + await expect(page.locator(".mx_UserInfo_devices").getByText("Dehydrated device")).not.toBeVisible(); + }); +}); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/utils.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/utils.ts index 0362148d39..d43e4c7f94 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/utils.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/utils.ts @@ -22,8 +22,8 @@ import type { Verifier, EmojiMapping, VerifierEvent, -} from "matrix-js-sdk/src/crypto-api/verification"; -import type { ISasEvent } from "matrix-js-sdk/src/crypto/verification/SAS"; + ShowSasCallbacks, +} from "matrix-js-sdk/src/crypto-api"; import { Credentials, HomeserverInstance } from "../../plugins/homeserver"; import { Client } from "../../pages/client"; import { ElementAppPage } from "../../pages/ElementAppPage"; @@ -63,7 +63,7 @@ export function handleSasVerification(verifier: JSHandle): Promise((resolve) => { - const onShowSas = (event: ISasEvent) => { + const onShowSas = (event: ShowSasCallbacks) => { verifier.off("show_sas" as VerifierEvent, onShowSas); event.confirm(); resolve(event.sas.emoji); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/verification.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/verification.spec.ts index 55d65a9b08..6819606b64 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/verification.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/crypto/verification.spec.ts @@ -15,9 +15,9 @@ limitations under the License. */ import jsQR from "jsqr"; +import { type Preset, type Visibility } from "matrix-js-sdk/src/matrix"; import type { JSHandle, Locator, Page } from "@playwright/test"; -import type { Preset, Visibility } from "matrix-js-sdk/src/matrix"; import type { VerificationRequest, Verifier } from "matrix-js-sdk/src/crypto-api"; import { test, expect } from "../../element-web-test"; import { diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/knock/knock-into-room.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/knock/knock-into-room.spec.ts index 1a4974e891..5ee366fcf2 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/knock/knock-into-room.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/knock/knock-into-room.spec.ts @@ -16,7 +16,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import type { Visibility } from "matrix-js-sdk/src/matrix"; +import { type Visibility } from "matrix-js-sdk/src/matrix"; + import { test, expect } from "../../element-web-test"; import { waitForRoom } from "../utils"; import { Filter } from "../../pages/Spotlight"; diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/presence/presence.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/presence/presence.spec.ts index 62c14b7ed5..861181ba56 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/presence/presence.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/presence/presence.spec.ts @@ -23,7 +23,9 @@ test.describe("Presence tests", () => { }); test.describe("bob unreachable", () => { - test("renders unreachable presence state correctly", async ({ page, app, user, bot: bob }) => { + // This is failing on CI (https://github.com/element-hq/element-web/issues/27270) + // but not locally, so debugging this is going to be tricky. Let's disable it for now. + test.skip("renders unreachable presence state correctly", async ({ page, app, user, bot: bob }) => { await app.client.createRoom({ name: "My Room", invite: [bob.credentials.userId] }); await app.viewRoomByName("My Room"); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/release-announcement/index.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/release-announcement/index.ts new file mode 100644 index 0000000000..d5ea4f2917 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/release-announcement/index.ts @@ -0,0 +1,77 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import { Page } from "@playwright/test"; + +import { test as base, expect } from "../../element-web-test"; + +/** + * Set up for release announcement tests. + */ +export const test = base.extend<{ + util: Helpers; +}>({ + displayName: "Alice", + botCreateOpts: { displayName: "Other User" }, + + util: async ({ page, app, bot }, use) => { + await use(new Helpers(page)); + }, +}); + +export class Helpers { + constructor(private page: Page) {} + + /** + * Get the release announcement with the given name. + * @param name + * @private + */ + private getReleaseAnnouncement(name: string) { + return this.page.getByRole("dialog", { name }); + } + + /** + * Assert that the release announcement with the given name is visible. + * @param name + */ + async assertReleaseAnnouncementIsVisible(name: string) { + await expect(this.getReleaseAnnouncement(name)).toBeVisible(); + await expect(this.page).toMatchScreenshot(`release-announcement-${name}.png`); + } + + /** + * Assert that the release announcement with the given name is not visible. + * @param name + */ + assertReleaseAnnouncementIsNotVisible(name: string) { + return expect(this.getReleaseAnnouncement(name)).not.toBeVisible(); + } + + /** + * Mark the release announcement with the given name as read. + * If the release announcement is not visible, this will throw an error. + * @param name + */ + async markReleaseAnnouncementAsRead(name: string) { + const dialog = this.getReleaseAnnouncement(name); + await dialog.getByRole("button", { name: "Ok" }).click(); + } +} + +export { expect }; diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/release-announcement/releaseAnnouncement.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/release-announcement/releaseAnnouncement.spec.ts new file mode 100644 index 0000000000..24854560c8 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/release-announcement/releaseAnnouncement.spec.ts @@ -0,0 +1,44 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import { test, expect } from "./"; + +test.describe("Release announcement", () => { + test.use({ + config: { + features: { + feature_release_announcement: true, + }, + }, + labsFlags: ["threadsActivityCentre"], + }); + + test("should display the release announcement process", async ({ page, app, util }) => { + // The TAC release announcement should be displayed + await util.assertReleaseAnnouncementIsVisible("Threads Activity Centre"); + // Hide the release announcement + await util.markReleaseAnnouncementAsRead("Threads Activity Centre"); + await util.assertReleaseAnnouncementIsNotVisible("Threads Activity Centre"); + + await page.reload(); + // Wait for EW to load + await expect(page.getByRole("navigation", { name: "Spaces" })).toBeVisible(); + // Check that once the release announcement has been marked as viewed, it does not appear again + await util.assertReleaseAnnouncementIsNotVisible("Threads Activity Centre"); + }); +}); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room-header.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room-header.spec.ts index 2d0af8a6df..a3c5e8c8bc 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room-header.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room-header.spec.ts @@ -18,6 +18,7 @@ import { Page } from "@playwright/test"; import { test, expect } from "../../element-web-test"; import { ElementAppPage } from "../../pages/ElementAppPage"; +import type { Container } from "../../../src/stores/widgets/types"; test.describe("Room Header", () => { test.use({ @@ -227,7 +228,7 @@ test.describe("Room Header", () => { { widgets: { [id]: { - container: "top", + container: "top" as Container, index: 1, width: 100, height: 0, diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room.spec.ts index 43edeaab38..5b60e6f3bb 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/room/room.spec.ts @@ -92,6 +92,10 @@ test.describe("Room Directory", () => { // Display Room B await app.viewRoomById(roomBId); + + // Let the app settle to avoid flakiness + await page.waitForTimeout(500); + // Display Room A await app.viewRoomById(roomAId); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/room_options/marked_unread.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/room_options/marked_unread.spec.ts new file mode 100644 index 0000000000..799acf2250 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/room_options/marked_unread.spec.ts @@ -0,0 +1,61 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { test, expect } from "../../element-web-test"; + +const TEST_ROOM_NAME = "The mark unread test room"; + +test.describe("Mark as Unread", () => { + test.use({ + displayName: "Tom", + botCreateOpts: { + displayName: "BotBob", + autoAcceptInvites: true, + }, + }); + + test("should mark a room as unread", async ({ page, app, bot }) => { + const roomId = await app.client.createRoom({ + name: TEST_ROOM_NAME, + }); + const dummyRoomId = await app.client.createRoom({ + name: "Room of no consequence", + }); + await app.client.inviteUser(roomId, bot.credentials.userId); + await bot.joinRoom(roomId); + await bot.sendMessage(roomId, "I am a robot. Beep."); + + // Regular notification on new message + await expect(page.getByLabel(TEST_ROOM_NAME + " 1 unread message.")).toBeVisible(); + await expect(page).toHaveTitle("Element [1]"); + + await page.goto("/#/room/" + roomId); + + // should now be read, since we viewed the room (we have to assert the page title: + // the room badge isn't visible since we're viewing the room) + await expect(page).toHaveTitle("Element | " + TEST_ROOM_NAME); + + // navigate away from the room again + await page.goto("/#/room/" + dummyRoomId); + + const roomTile = page.getByLabel(TEST_ROOM_NAME); + await roomTile.focus(); + await roomTile.getByRole("button", { name: "Room options" }).click(); + await page.getByRole("menuitem", { name: "Mark as unread" }).click(); + + expect(page.getByLabel(TEST_ROOM_NAME + " Unread messages.")).toBeVisible(); + }); +}); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/settings/roles-permissions-room-settings-tab.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/settings/roles-permissions-room-settings-tab.spec.ts new file mode 100644 index 0000000000..8d8c2ebffa --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/settings/roles-permissions-room-settings-tab.spec.ts @@ -0,0 +1,58 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import { Locator } from "@playwright/test"; + +import { test, expect } from "../../element-web-test"; + +test.describe("Roles & Permissions room settings tab", () => { + const roomName = "Test room"; + + test.use({ + displayName: "Alice", + }); + + let settings: Locator; + + test.beforeEach(async ({ user, app }) => { + await app.client.createRoom({ name: roomName }); + await app.viewRoomByName(roomName); + settings = await app.settings.openRoomSettings("Roles & Permissions"); + }); + + test("should be able to change the role of a user", async ({ page, app, user }) => { + const privilegedUserSection = settings.locator(".mx_SettingsFieldset").first(); + const applyButton = privilegedUserSection.getByRole("button", { name: "Apply" }); + + // Alice is admin (100) and the Apply button should be disabled + await expect(applyButton).toBeDisabled(); + let combobox = privilegedUserSection.getByRole("combobox", { name: user.userId }); + await expect(combobox).toHaveValue("100"); + + // Change the role of Alice to Moderator (50) + await combobox.selectOption("Moderator"); + await expect(combobox).toHaveValue("50"); + await applyButton.click(); + + // Reload and check Alice is still Moderator (50) + await page.reload(); + settings = await app.settings.openRoomSettings("Roles & Permissions"); + combobox = privilegedUserSection.getByRole("combobox", { name: user.userId }); + await expect(combobox).toHaveValue("50"); + }); +}); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/index.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/index.ts index b0fcd4648a..7ad477541a 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/index.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/index.ts @@ -30,30 +30,30 @@ import { ElementAppPage } from "../../../pages/ElementAppPage"; * - Invite the bot to both rooms and ensure that it has joined */ export const test = base.extend<{ - roomAlphaName?: string; - roomAlpha: { name: string; roomId: string }; - roomBetaName?: string; - roomBeta: { name: string; roomId: string }; + room1Name?: string; + room1: { name: string; roomId: string }; + room2Name?: string; + room2: { name: string; roomId: string }; msg: MessageBuilder; util: Helpers; }>({ displayName: "Mae", botCreateOpts: { displayName: "Other User" }, - roomAlphaName: "Room Alpha", - roomAlpha: async ({ roomAlphaName: name, app, user, bot }, use) => { + room1Name: "Room 1", + room1: async ({ room1Name: name, app, user, bot }, use) => { const roomId = await app.client.createRoom({ name, invite: [bot.credentials.userId] }); await use({ name, roomId }); }, - roomBetaName: "Room Beta", - roomBeta: async ({ roomBetaName: name, app, user, bot }, use) => { + room2Name: "Room 2", + room2: async ({ room2Name: name, app, user, bot }, use) => { const roomId = await app.client.createRoom({ name, invite: [bot.credentials.userId] }); await use({ name, roomId }); }, msg: async ({ page, app, util }, use) => { await use(new MessageBuilder(page, app, util)); }, - util: async ({ roomAlpha, roomBeta, page, app, bot }, use) => { + util: async ({ room1, room2, page, app, bot }, use) => { await use(new Helpers(page, app, bot)); }, }); @@ -265,6 +265,13 @@ export class Helpers { return this.getTacButton().click(); } + /** + * Hover over the Threads Activity Centre button + */ + hoverTacButton() { + return this.getTacButton().hover(); + } + /** * Click on a room in the Threads Activity Centre * @param name - room name @@ -276,8 +283,12 @@ export class Helpers { /** * Assert that the threads activity centre button has no indicator */ - assertNoTacIndicator() { - return expect(this.getTacButton()).toMatchScreenshot("tac-no-indicator.png"); + async assertNoTacIndicator() { + // Assert by checkng neither of the known indicators are visible first. This will wait + // if it takes a little time to disappear, but the screenshot comparison won't. + await expect(this.getTacButton().locator("[data-indicator='success']")).not.toBeVisible(); + await expect(this.getTacButton().locator("[data-indicator='critical']")).not.toBeVisible(); + await expect(this.getTacButton()).toMatchScreenshot("tac-no-indicator.png"); } /** @@ -325,28 +336,41 @@ export class Helpers { return expect(this.page.locator(".mx_ThreadPanel")).toBeVisible(); } + /** + * Assert that the thread panel is focused (actually the 'close' button, specifically) + */ + assertThreadPanelFocused() { + return expect( + this.page.locator(".mx_ThreadPanel").locator(".mx_BaseCard_header").getByTitle("Close"), + ).toBeFocused(); + } + /** * Populate the rooms with messages and threads * @param room1 * @param room2 * @param msg - MessageBuilder + * @param hasMention - whether to include a mention in the first message */ async populateThreads( room1: { name: string; roomId: string }, room2: { name: string; roomId: string }, msg: MessageBuilder, + hasMention = true, ) { - await this.receiveMessages(room2, [ - "Msg1", - msg.threadedOff("Msg1", { - "body": "User", - "format": "org.matrix.custom.html", - "formatted_body": "User", - "m.mentions": { - user_ids: ["@user:localhost"], - }, - }), - ]); + if (hasMention) { + await this.receiveMessages(room2, [ + "Msg1", + msg.threadedOff("Msg1", { + "body": "User", + "format": "org.matrix.custom.html", + "formatted_body": "User", + "m.mentions": { + user_ids: ["@user:localhost"], + }, + }), + ]); + } await this.receiveMessages(room2, ["Msg2", msg.threadedOff("Msg2", "Resp2")]); await this.receiveMessages(room1, ["Msg3", msg.threadedOff("Msg3", "Resp3")]); } @@ -364,6 +388,13 @@ export class Helpers { expandSpacePanel() { return this.page.getByRole("button", { name: "Expand" }).click(); } + + /** + * Clicks the button to mark all threads as read in the current room + */ + clickMarkAllThreadsRead() { + return this.page.getByLabel("Mark all as read").click(); + } } export { expect }; diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts index 1b237c0b53..7d0b694ef5 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/spaces/threads-activity-centre/threadsActivityCentre.spec.ts @@ -17,6 +17,7 @@ */ import { expect, test } from "."; +import { CommandOrControl } from "../../utils"; test.describe("Threads Activity Centre", () => { test.use({ @@ -34,7 +35,7 @@ test.describe("Threads Activity Centre", () => { await expect(util.getSpacePanel()).toMatchScreenshot("tac-button-expanded.png"); }); - test("should not show indicator when there is no thread", async ({ roomAlpha: room1, util }) => { + test("should not show indicator when there is no thread", async ({ room1, util }) => { // No indicator should be shown await util.assertNoTacIndicator(); @@ -45,11 +46,7 @@ test.describe("Threads Activity Centre", () => { await util.assertNoTacIndicator(); }); - test("should show a notification indicator when there is a message in a thread", async ({ - roomAlpha: room1, - util, - msg, - }) => { + test("should show a notification indicator when there is a message in a thread", async ({ room1, util, msg }) => { await util.goTo(room1); await util.receiveMessages(room1, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); @@ -57,11 +54,7 @@ test.describe("Threads Activity Centre", () => { await util.assertNotificationTac(); }); - test("should show a highlight indicator when there is a mention in a thread", async ({ - roomAlpha: room1, - util, - msg, - }) => { + test("should show a highlight indicator when there is a mention in a thread", async ({ room1, util, msg }) => { await util.goTo(room1); await util.receiveMessages(room1, [ "Msg1", @@ -79,7 +72,7 @@ test.describe("Threads Activity Centre", () => { await util.assertHighlightIndicator(); }); - test("should show the rooms with unread threads", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { + test("should show the rooms with unread threads", async ({ room1, room2, util, msg }) => { await util.goTo(room2); await util.populateThreads(room1, room2, msg); // The indicator should be shown @@ -96,7 +89,7 @@ test.describe("Threads Activity Centre", () => { await expect(util.getTacPanel()).toMatchScreenshot("tac-panel-mix-unread.png"); }); - test("should update with a thread is read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { + test("should update with a thread is read", async ({ room1, room2, util, msg }) => { await util.goTo(room2); await util.populateThreads(room1, room2, msg); @@ -118,4 +111,67 @@ test.describe("Threads Activity Centre", () => { ]); await expect(util.getTacPanel()).toMatchScreenshot("tac-panel-notification-unread.png"); }); + + test("should order by recency after notification level", async ({ room1, room2, util, msg }) => { + await util.goTo(room2); + await util.populateThreads(room1, room2, msg, false); + + await util.openTac(); + await util.assertRoomsInTac([ + { room: room1.name, notificationLevel: "notification" }, + { room: room2.name, notificationLevel: "notification" }, + ]); + }); + + test("should block the Spotlight to open when the TAC is opened", async ({ util, page }) => { + const toggleSpotlight = () => page.keyboard.press(`${CommandOrControl}+k`); + + // Sanity check + // Open and close the spotlight + await toggleSpotlight(); + await expect(page.locator(".mx_SpotlightDialog")).toBeVisible(); + await toggleSpotlight(); + + await util.openTac(); + // The spotlight should not be opened + await toggleSpotlight(); + await expect(page.locator(".mx_SpotlightDialog")).not.toBeVisible(); + }); + + test("should have the correct hover state", async ({ util, page }) => { + await util.hoverTacButton(); + await expect(util.getSpacePanel()).toMatchScreenshot("tac-hovered.png"); + + // Expand the space panel, hover the button and take a screenshot + await util.expandSpacePanel(); + await util.hoverTacButton(); + await expect(util.getSpacePanel()).toMatchScreenshot("tac-hovered-expanded.png"); + }); + + test("should mark all threads as read", async ({ room1, room2, util, msg, page }) => { + await util.receiveMessages(room1, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + + await util.assertNotificationTac(); + + await util.openTac(); + await util.clickRoomInTac(room1.name); + + util.clickMarkAllThreadsRead(); + + await util.assertNoTacIndicator(); + }); + + test("should focus the thread panel close button when clicking an item in the TAC", async ({ + room1, + room2, + util, + msg, + }) => { + await util.receiveMessages(room1, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + + await util.openTac(); + await util.clickRoomInTac(room1.name); + + await util.assertThreadPanelFocused(); + }); }); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/threads/threads.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/threads/threads.spec.ts index 34fe287d47..5e32516646 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/threads/threads.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/threads/threads.spec.ts @@ -447,4 +447,72 @@ test.describe("Threads", () => { await expect(locator.locator(".mx_EventTile").first().getByText("Hello Mr. Bot")).toBeAttached(); await expect(locator.locator(".mx_EventTile").last().getByText("Hello Mr. User")).toBeAttached(); }); + + test("navigate through right panel", async ({ page, app, user }) => { + // Create room + const roomId = await app.client.createRoom({}); + await page.goto("/#/room/" + roomId); + + /** + * Send a message in the main timeline + * @param message + */ + const sendMessage = async (message: string) => { + const messageComposer = page.getByRole("region", { name: "Message composer" }); + const textbox = messageComposer.getByRole("textbox", { name: "Send a message…" }); + await textbox.fill(message); + await textbox.press("Enter"); + }; + + /** + * Create a thread from the rootMessage and send a message in the thread + * @param rootMessage + * @param threadMessage + */ + const createThread = async (rootMessage: string, threadMessage: string) => { + // First create a thread + const roomViewBody = page.locator(".mx_RoomView_body"); + const messageTile = roomViewBody + .locator(".mx_EventTile[data-scroll-tokens]") + .filter({ hasText: rootMessage }); + await messageTile.hover(); + await messageTile.getByRole("button", { name: "Reply in thread" }).click(); + await expect(page.locator(".mx_ThreadView_timelinePanelWrapper")).toHaveCount(1); + + // Send a message in the thread + const threadPanel = page.locator(".mx_ThreadPanel"); + const textbox = threadPanel.getByRole("textbox", { name: "Send a message…" }); + await textbox.fill(threadMessage); + await textbox.press("Enter"); + await expect(threadPanel.locator(".mx_EventTile_last").getByText(threadMessage)).toBeVisible(); + // Close thread + await threadPanel.getByRole("button", { name: "Close" }).click(); + }; + + await sendMessage("Hello Mr. Bot"); + await sendMessage("Hello again Mr. Bot"); + await createThread("Hello Mr. Bot", "Hello Mr. User in a thread"); + await createThread("Hello again Mr. Bot", "Hello again Mr. User in a thread"); + + // Open thread panel + await page.getByRole("button", { name: "Threads" }).click(); + const threadPanel = page.locator(".mx_ThreadPanel"); + await expect( + threadPanel.locator(".mx_EventTile_last").getByText("Hello again Mr. User in a thread"), + ).toBeVisible(); + + // Open threads list + await threadPanel.getByRole("button", { name: "Threads" }).click(); + const rightPanel = page.locator(".mx_RightPanel"); + // Check that the threads are listed + await expect(rightPanel.locator(".mx_EventTile").getByText("Hello Mr. User in a thread")).toBeVisible(); + await expect(rightPanel.locator(".mx_EventTile").getByText("Hello again Mr. User in a thread")).toBeVisible(); + + // Open the first thread + await rightPanel.locator(".mx_EventTile").getByText("Hello Mr. User in a thread").click(); + await expect(rightPanel.locator(".mx_EventTile").getByText("Hello Mr. User in a thread")).toBeVisible(); + await expect( + rightPanel.locator(".mx_EventTile").getByText("Hello again Mr. User in a thread"), + ).not.toBeVisible(); + }); }); diff --git a/linked-dependencies/matrix-react-sdk/playwright/e2e/timeline/timeline.spec.ts b/linked-dependencies/matrix-react-sdk/playwright/e2e/timeline/timeline.spec.ts index 67d7bb84d2..2ca507fc9e 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/e2e/timeline/timeline.spec.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/e2e/timeline/timeline.spec.ts @@ -1032,6 +1032,16 @@ test.describe("Timeline", () => { "et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut " + "aliquip"; + const newDisplayName = `${LONG_STRING} 2`; + + // Set the display name to "LONG_STRING 2" in order to avoid screenshot tests from failing + // due to the generated random mxid being displayed inside the GELS summary. + // Note that we set it here as the test was failing on CI (but not locally!) if the name + // was changed afterwards. This is quite concerning, but maybe better than just disabling the + // whole test? + // https://github.com/element-hq/element-web/issues/27109 + await app.client.setDisplayName(newDisplayName); + // Create a bot with a long display name const bot = new Bot(page, homeserver, { displayName: LONG_STRING, @@ -1049,13 +1059,9 @@ test.describe("Timeline", () => { await expect( page .locator(".mx_GenericEventListSummary_summary") - .getByText(OLD_NAME + " created and configured the room."), + .getByText(newDisplayName + " created and configured the room."), ).toBeVisible(); - // Set the display name to "LONG_STRING 2" in order to avoid screenshot tests from failing - // due to the generated random mxid being displayed inside the GELS summary. - await app.client.setDisplayName(`${LONG_STRING} 2`); - // Have the bot send a long message await bot.sendMessage(testRoomId, { body: LONG_STRING, diff --git a/linked-dependencies/matrix-react-sdk/playwright/element-web-test.ts b/linked-dependencies/matrix-react-sdk/playwright/element-web-test.ts index 21407d2585..e67cca6ab8 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/element-web-test.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/element-web-test.ts @@ -52,6 +52,11 @@ const CONFIG_JSON: Partial = { // the location tests want a map style url. map_style_url: "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx", + + features: { + // We don't want to go through the feature announcement during the e2e test + feature_release_announcement: false, + }, }; export type TestOptions = { @@ -66,12 +71,32 @@ export const test = base.extend< TestOptions & { axe: AxeBuilder; checkA11y: () => Promise; - // The contents of the config.json to send + + /** + * The contents of the config.json to send when the client requests it. + */ config: typeof CONFIG_JSON; - // The options with which to run the `homeserver` fixture + + /** + * The options with which to run the {@link #homeserver} fixture. + */ startHomeserverOpts: StartHomeserverOpts | string; + homeserver: HomeserverInstance; oAuthServer: { port: number }; + + /** + * The displayname to use for the user registered in {@link #credentials}. + * + * To set it, call `test.use({ displayName: "myDisplayName" })` in the test file or `describe` block. + * See {@link https://playwright.dev/docs/api/class-test#test-use}. + */ + displayName?: string; + + /** + * A test fixture which registers a test user on the {@link #homeserver} and supplies the details + * of the registered user. + */ credentials: CredentialsWithDisplayName; /** @@ -83,9 +108,20 @@ export const test = base.extend< */ pageWithCredentials: Page; + /** + * A (rather poorly-named) test fixture which registers a user per {@link #credentials}, stores + * the credentials into localStorage per {@link #homeserver}, and then loads the front page of the + * app. + */ user: CredentialsWithDisplayName; - displayName?: string; + + /** + * The same as {@link https://playwright.dev/docs/api/class-fixtures#fixtures-page|`page`}, + * but wraps the returned `Page` in a class of utilities for interacting with the Element-Web UI, + * {@link ElementAppPage}. + */ app: ElementAppPage; + mailhog: { api: mailhog.API; instance: Instance }; crypto: Crypto; room?: { roomId: string }; diff --git a/linked-dependencies/matrix-react-sdk/playwright/global.d.ts b/linked-dependencies/matrix-react-sdk/playwright/global.d.ts index 166bfbe993..9663b9310f 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/global.d.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/global.d.ts @@ -31,3 +31,10 @@ declare global { matrixcs: typeof Matrix; } } + +// Workaround for lack of strict mode not resolving complex types correctly +declare module "matrix-js-sdk/src/http-api/index.ts" { + interface UploadResponse { + json(): Promise; + } +} diff --git a/linked-dependencies/matrix-react-sdk/playwright/pages/ElementAppPage.ts b/linked-dependencies/matrix-react-sdk/playwright/pages/ElementAppPage.ts index babb44f881..ac9b4ffef8 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/pages/ElementAppPage.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/pages/ElementAppPage.ts @@ -21,6 +21,9 @@ import { Client } from "./client"; import { Timeline } from "./timeline"; import { Spotlight } from "./Spotlight"; +/** + * A set of utility methods for interacting with the Element-Web UI. + */ export class ElementAppPage { public constructor(public readonly page: Page) {} diff --git a/linked-dependencies/matrix-react-sdk/playwright/pages/bot.ts b/linked-dependencies/matrix-react-sdk/playwright/pages/bot.ts index d6b729420c..333d895dfe 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/pages/bot.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/pages/bot.ts @@ -16,8 +16,8 @@ limitations under the License. import { JSHandle, Page } from "@playwright/test"; import { uniqueId } from "lodash"; +import { type MatrixClient } from "matrix-js-sdk/src/matrix"; -import type { MatrixClient } from "matrix-js-sdk/src/matrix"; import type { Logger } from "matrix-js-sdk/src/logger"; import type { SecretStorageKeyDescription } from "matrix-js-sdk/src/secret-storage"; import type { Credentials, HomeserverInstance } from "../plugins/homeserver"; diff --git a/linked-dependencies/matrix-react-sdk/playwright/pages/client.ts b/linked-dependencies/matrix-react-sdk/playwright/pages/client.ts index 054b946845..94ee5d8813 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/pages/client.ts +++ b/linked-dependencies/matrix-react-sdk/playwright/pages/client.ts @@ -31,7 +31,10 @@ import type { Visibility, UploadOpts, Upload, + StateEvents, + TimelineEvents, } from "matrix-js-sdk/src/matrix"; +import type { RoomMessageEventContent } from "matrix-js-sdk/src/types"; import { Credentials } from "../plugins/homeserver"; export class Client { @@ -97,7 +100,12 @@ export class Client { const client = await this.prepareClient(); return client.evaluate( async (client, { roomId, threadId, eventType, content }) => { - return client.sendEvent(roomId, threadId, eventType, content); + return client.sendEvent( + roomId, + threadId, + eventType as keyof TimelineEvents, + content as TimelineEvents[keyof TimelineEvents], + ); }, { roomId, threadId, eventType, content }, ); @@ -124,7 +132,7 @@ export class Client { const client = await this.prepareClient(); return client.evaluate( (client, { roomId, content, threadId }) => { - return client.sendMessage(roomId, threadId, content); + return client.sendMessage(roomId, threadId, content as RoomMessageEventContent); }, { roomId, @@ -407,7 +415,7 @@ export class Client { const client = await this.prepareClient(); return client.evaluate( async (client, { roomId, eventType, content, stateKey }) => { - return client.sendStateEvent(roomId, eventType, content, stateKey); + return client.sendStateEvent(roomId, eventType as keyof StateEvents, content, stateKey); }, { roomId, eventType, content, stateKey }, ); diff --git a/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/README.md b/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/README.md new file mode 100644 index 0000000000..18f7923e6d --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/README.md @@ -0,0 +1 @@ +A synapse configured with device dehydration v2 enabled diff --git a/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/homeserver.yaml b/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/homeserver.yaml new file mode 100644 index 0000000000..c3ac5d6536 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/homeserver.yaml @@ -0,0 +1,102 @@ +server_name: "localhost" +pid_file: /data/homeserver.pid +public_baseurl: "{{PUBLIC_BASEURL}}" +listeners: + - port: 8008 + tls: false + bind_addresses: ["::"] + type: http + x_forwarded: true + + resources: + - names: [client] + compress: false + +database: + name: "sqlite3" + args: + database: ":memory:" + +log_config: "/data/log.config" + +rc_messages_per_second: 10000 +rc_message_burst_count: 10000 +rc_registration: + per_second: 10000 + burst_count: 10000 +rc_joins: + local: + per_second: 9999 + burst_count: 9999 + remote: + per_second: 9999 + burst_count: 9999 +rc_joins_per_room: + per_second: 9999 + burst_count: 9999 +rc_3pid_validation: + per_second: 1000 + burst_count: 1000 + +rc_invites: + per_room: + per_second: 1000 + burst_count: 1000 + per_user: + per_second: 1000 + burst_count: 1000 + +rc_login: + address: + per_second: 10000 + burst_count: 10000 + account: + per_second: 10000 + burst_count: 10000 + failed_attempts: + per_second: 10000 + burst_count: 10000 + +media_store_path: "/data/media_store" +uploads_path: "/data/uploads" +enable_registration: true +enable_registration_without_verification: true +disable_msisdn_registration: false +registration_shared_secret: "{{REGISTRATION_SECRET}}" +report_stats: false +macaroon_secret_key: "{{MACAROON_SECRET_KEY}}" +form_secret: "{{FORM_SECRET}}" +signing_key_path: "/data/localhost.signing.key" + +trusted_key_servers: + - server_name: "matrix.org" +suppress_key_server_warning: true + +ui_auth: + session_timeout: "300s" + +oidc_providers: + - idp_id: test + idp_name: "OAuth test" + issuer: "http://localhost:{{OAUTH_SERVER_PORT}}/oauth" + authorization_endpoint: "http://localhost:{{OAUTH_SERVER_PORT}}/oauth/auth.html" + # the token endpoint receives requests from synapse, rather than the webapp, so needs to escape the docker container. + token_endpoint: "http://host.containers.internal:{{OAUTH_SERVER_PORT}}/oauth/token" + userinfo_endpoint: "http://host.containers.internal:{{OAUTH_SERVER_PORT}}/oauth/userinfo" + client_id: "synapse" + discover: false + scopes: ["profile"] + skip_verification: true + client_auth_method: none + user_mapping_provider: + config: + display_name_template: "{{ user.name }}" + +# Inhibit background updates as this Synapse isn't long-lived +background_updates: + min_batch_size: 100000 + sleep_duration_ms: 100000 + +experimental_features: + msc2697_enabled: false + msc3814_enabled: true diff --git a/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/log.config b/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/log.config new file mode 100644 index 0000000000..b9123d0f5b --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/playwright/plugins/homeserver/synapse/templates/dehydration/log.config @@ -0,0 +1,50 @@ +# Log configuration for Synapse. +# +# This is a YAML file containing a standard Python logging configuration +# dictionary. See [1] for details on the valid settings. +# +# Synapse also supports structured logging for machine readable logs which can +# be ingested by ELK stacks. See [2] for details. +# +# [1]: https://docs.python.org/3.7/library/logging.config.html#configuration-dictionary-schema +# [2]: https://matrix-org.github.io/synapse/latest/structured_logging.html + +version: 1 + +formatters: + precise: + format: '%(asctime)s - %(name)s - %(lineno)d - %(levelname)s - %(request)s - %(message)s' + +handlers: + # A handler that writes logs to stderr. Unused by default, but can be used + # instead of "buffer" and "file" in the logger handlers. + console: + class: logging.StreamHandler + formatter: precise + +loggers: + synapse.storage.SQL: + # beware: increasing this to DEBUG will make synapse log sensitive + # information such as access tokens. + level: DEBUG + + twisted: + # We send the twisted logging directly to the file handler, + # to work around https://github.com/matrix-org/synapse/issues/3471 + # when using "buffer" logger. Use "console" to log to stderr instead. + handlers: [console] + propagate: false + +root: + level: DEBUG + + # Write logs to the `buffer` handler, which will buffer them together in memory, + # then write them to a file. + # + # Replace "buffer" with "console" to log to stderr instead. (Note that you'll + # also need to update the configuration for the `twisted` logger above, in + # this case.) + # + handlers: [console] + +disable_existing_loggers: false diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--group-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--group-layout-linux.png index 9a0a24ae56..7ece029188 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--group-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--dark-theme--group-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--bubble-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--bubble-layout-linux.png index 7e22dea5df..4993fec9b6 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--bubble-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--bubble-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--group-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--group-layout-linux.png index 655baf15a2..b6c259785e 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--group-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--group-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--irc-layout-linux.png index f230fe06da..921117c945 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--high-contrast--irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--group-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--group-layout-linux.png index deedd2d703..fb80e1645c 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--group-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--group-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--monospace-font--group-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--monospace-font--group-layout-linux.png index 9fa8fcd008..ca0fab0f78 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--monospace-font--group-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/audio-player/audio-player.spec.ts/Selected-EventTile-of-audio-player--light-theme--monospace-font--group-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/editing/editing.spec.ts/message-edit-history-dialog-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/editing/editing.spec.ts/message-edit-history-dialog-linux.png index 8d3d371dcc..9f46fce516 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/editing/editing.spec.ts/message-edit-history-dialog-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/editing/editing.spec.ts/message-edit-history-dialog-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-with-user-pill-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-with-user-pill-linux.png index fb63492564..7e8992dca1 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-with-user-pill-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-with-user-pill-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-without-user-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-without-user-linux.png index 07b7a02ed3..dfa6d4f0aa 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-without-user-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-dm-without-user-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-with-user-pill-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-with-user-pill-linux.png index 427b8228f5..9cc13698cf 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-with-user-pill-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-with-user-pill-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-without-user-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-without-user-linux.png index 4c1bec3fa9..44d8129404 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-without-user-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/invite/invite-dialog.spec.ts/invite-dialog-room-without-user-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png index 300b7e011a..db91140763 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/permalinks/permalinks.spec.ts/permalink-rendering-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-bubble-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-bubble-layout-linux.png index 58a97c40b7..2fc33b1f0b 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-bubble-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-bubble-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-group-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-group-layout-linux.png index c4b69dd6e6..a4c053e7a7 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-group-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-group-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/email-prompt-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/email-prompt-linux.png index 52193fdcc5..3d4ea984a4 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/email-prompt-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/email-prompt-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/server-picker-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/server-picker-linux.png index 3bfc6affca..94b5505b7a 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/server-picker-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/register/register.spec.ts/server-picker-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/release-announcement/releaseAnnouncement.spec.ts/release-announcement-Threads-Activity-Centre-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/release-announcement/releaseAnnouncement.spec.ts/release-announcement-Threads-Activity-Centre-linux.png new file mode 100644 index 0000000000..6439fe305b Binary files /dev/null and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/release-announcement/releaseAnnouncement.spec.ts/release-announcement-Threads-Activity-Centre-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-no-results-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-no-results-linux.png index c827248e12..e0fc9cc5bd 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-no-results-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-no-results-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-one-result-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-one-result-linux.png index bf7be29b02..a962c3cbad 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-one-result-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room-directory/room-directory.spec.ts/filtered-one-result-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-highlighted-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-highlighted-linux.png index 6d6ea59ae8..5fa24a887f 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-highlighted-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-highlighted-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-with-apps-button-not-highlighted-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-with-apps-button-not-highlighted-linux.png index ad2bf20e94..84eb8fcccc 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-with-apps-button-not-highlighted-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/room/room-header.spec.ts/room-header-with-apps-button-not-highlighted-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png index 13d3c5b7d3..e5680339f4 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/window-12px-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/window-12px-linux.png index 7162ce0e3c..23b77fd751 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/window-12px-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/window-12px-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-room-settings-tab.spec.ts/General-room-settings-tab-should-be-rendered-properly-1-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-room-settings-tab.spec.ts/General-room-settings-tab-should-be-rendered-properly-1-linux.png index cc8eb610e8..253b230419 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-room-settings-tab.spec.ts/General-room-settings-tab-should-be-rendered-properly-1-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-room-settings-tab.spec.ts/General-room-settings-tab-should-be-rendered-properly-1-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-user-settings-tab.spec.ts/general-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-user-settings-tab.spec.ts/general-linux.png index 5950cb28b1..f0b18bc950 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-user-settings-tab.spec.ts/general-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/general-user-settings-tab.spec.ts/general-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/preferences-user-settings-tab.spec.ts/Preferences-user-settings-tab-should-be-rendered-properly-1-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/preferences-user-settings-tab.spec.ts/Preferences-user-settings-tab-should-be-rendered-properly-1-linux.png index e864d3962c..02ce908efa 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/preferences-user-settings-tab.spec.ts/Preferences-user-settings-tab-should-be-rendered-properly-1-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/preferences-user-settings-tab.spec.ts/Preferences-user-settings-tab-should-be-rendered-properly-1-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/security-user-settings-tab.spec.ts/Security-user-settings-tab-with-posthog-enable-b5d89-csLearnMoreDialog-should-be-rendered-properly-1-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/security-user-settings-tab.spec.ts/Security-user-settings-tab-with-posthog-enable-b5d89-csLearnMoreDialog-should-be-rendered-properly-1-linux.png index a94f93b33c..c59d60178d 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/security-user-settings-tab.spec.ts/Security-user-settings-tab-with-posthog-enable-b5d89-csLearnMoreDialog-should-be-rendered-properly-1-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/settings/security-user-settings-tab.spec.ts/Security-user-settings-tab-with-posthog-enable-b5d89-csLearnMoreDialog-should-be-rendered-properly-1-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-create-menu-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-create-menu-linux.png index d3b002a5fa..6d2e83b23d 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-create-menu-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-create-menu-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-panel-expanded-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-panel-expanded-linux.png index e112e5edfa..a2edd3d88f 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-panel-expanded-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/spaces.spec.ts/space-panel-expanded-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-button-expanded-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-button-expanded-linux.png index 6e03d93862..dcac67dc1f 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-button-expanded-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-button-expanded-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-expanded-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-expanded-linux.png new file mode 100644 index 0000000000..37405cd821 Binary files /dev/null and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-expanded-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-linux.png new file mode 100644 index 0000000000..26f5bfdfa9 Binary files /dev/null and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-hovered-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-mix-unread-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-mix-unread-linux.png index f02a943d6b..ec5a8193d2 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-mix-unread-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-mix-unread-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-notification-unread-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-notification-unread-linux.png index 1a94524d68..f0f6cee3e6 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-notification-unread-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/spaces/threads-activity-centre/threadsActivityCentre.spec.ts/tac-panel-notification-unread-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/threads/threads.spec.ts/Reply-to-the-location-on-ThreadView-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/threads/threads.spec.ts/Reply-to-the-location-on-ThreadView-linux.png index 747bf1b5d1..7ef5b40543 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/threads/threads.spec.ts/Reply-to-the-location-on-ThreadView-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/threads/threads.spec.ts/Reply-to-the-location-on-ThreadView-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-and-messages-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-and-messages-irc-layout-linux.png index 8ea537d424..5703f38449 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-and-messages-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-and-messages-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-bubble-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-bubble-layout-linux.png index 2ee588be13..0a3d265a60 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-bubble-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/collapsed-gels-bubble-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/configured-room-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/configured-room-irc-layout-linux.png index 27425c6326..0453bf932a 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/configured-room-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/configured-room-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-line-inline-start-margin-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-line-inline-start-margin-irc-layout-linux.png index 02fec4dee6..077ecbf717 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-line-inline-start-margin-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-line-inline-start-margin-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-bubble-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-bubble-layout-linux.png index ee983ee3a5..c0a01c99fb 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-bubble-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-bubble-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-compact-modern-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-compact-modern-layout-linux.png index fbee0bb1de..87e65a86ae 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-compact-modern-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-compact-modern-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-layout-linux.png index 80359800e7..45c43f06fe 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-modern-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-modern-linux.png index cdab9fe054..445d616ea4 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-modern-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tile-reply-chains-irc-modern-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-bubble-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-bubble-layout-linux.png index 629435b639..194ecd07fb 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-bubble-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-bubble-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-compact-modern-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-compact-modern-layout-linux.png index 497fd62e78..2b990bb3b8 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-compact-modern-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-compact-modern-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-irc-layout-linux.png index 3255574339..294cd3ec7a 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-modern-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-modern-layout-linux.png index c9feb4ef4a..f0064c81e1 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-modern-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/event-tiles-modern-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-and-messages-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-and-messages-irc-layout-linux.png index 8d5fd4adcb..001ac64f2a 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-and-messages-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-and-messages-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-bubble-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-bubble-layout-linux.png index 83d022391e..f7a276d2f7 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-bubble-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-bubble-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-emote-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-emote-irc-layout-linux.png index 431953837a..de056e0fa5 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-emote-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-emote-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-irc-layout-linux.png index 02fec4dee6..077ecbf717 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-modern-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-modern-layout-linux.png index 8d1a239a1d..e1cd5ab19c 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-modern-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-modern-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-redaction-placeholder-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-redaction-placeholder-linux.png index 502d4e64df..4fb2902456 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-redaction-placeholder-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/expanded-gels-redaction-placeholder-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-padding-modern-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-padding-modern-layout-linux.png index d221eea7d0..ceddab3312 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-padding-modern-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-padding-modern-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-zero-padding-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-zero-padding-irc-layout-linux.png index b9aa65ab58..5fba124a92 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-zero-padding-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-zero-padding-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-bubble-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-bubble-layout-linux.png index 3761779af0..800ceefc6e 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-bubble-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-bubble-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-irc-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-irc-layout-linux.png index 9236c30efa..9d2fcdf272 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-irc-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-irc-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-modern-layout-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-modern-layout-linux.png index b495f35733..f85715b076 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-modern-layout-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/timeline/timeline.spec.ts/long-strings-with-reply-modern-layout-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/snapshots/user-onboarding/user-onboarding-new.spec.ts/User-Onboarding-new-user-app-download-dialog-1-linux.png b/linked-dependencies/matrix-react-sdk/playwright/snapshots/user-onboarding/user-onboarding-new.spec.ts/User-Onboarding-new-user-app-download-dialog-1-linux.png index 297f35e215..589cb34cb4 100644 Binary files a/linked-dependencies/matrix-react-sdk/playwright/snapshots/user-onboarding/user-onboarding-new.spec.ts/User-Onboarding-new-user-app-download-dialog-1-linux.png and b/linked-dependencies/matrix-react-sdk/playwright/snapshots/user-onboarding/user-onboarding-new.spec.ts/User-Onboarding-new-user-app-download-dialog-1-linux.png differ diff --git a/linked-dependencies/matrix-react-sdk/playwright/tsconfig.json b/linked-dependencies/matrix-react-sdk/playwright/tsconfig.json index cea25ebab7..55f979f3ce 100644 --- a/linked-dependencies/matrix-react-sdk/playwright/tsconfig.json +++ b/linked-dependencies/matrix-react-sdk/playwright/tsconfig.json @@ -10,6 +10,7 @@ }, "include": [ "**/*.ts", + "../src/@types/matrix-js-sdk.d.ts", "../node_modules/matrix-js-sdk/src/@types/*.d.ts", "../node_modules/matrix-js-sdk/node_modules/@matrix-org/olm/index.d.ts" ] diff --git a/linked-dependencies/matrix-react-sdk/res/css/_common.pcss b/linked-dependencies/matrix-react-sdk/res/css/_common.pcss index c6b5e14c5b..20ed9dfa39 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/_common.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/_common.pcss @@ -329,16 +329,27 @@ legend { justify-content: center; } +.mx_Dialog_border { + z-index: var(--dialog-zIndex-standard); + position: relative; + max-height: calc(100% - var(--cpd-space-12x)); + display: flex; + flex-direction: column; + + .mx_Dialog_lightbox & { + /* The lightbox isn't so much of a dialog as a fullscreen overlay. We + don't want the glass border. */ + display: contents; + } +} + .mx_Dialog { background-color: $background; color: $light-fg-color; - z-index: var(--dialog-zIndex-standard); font-size: $font-15px; position: relative; - padding: 24px; - max-height: 80%; - box-shadow: 2px 15px 30px 0 $dialog-shadow-color; - border-radius: 8px; + padding: var(--cpd-space-8x) var(--cpd-space-10x); + box-sizing: border-box; overflow-y: auto; .mx_Dialog_staticWrapper & { @@ -439,7 +450,6 @@ legend { width: 100%; height: 100%; background-color: $dialog-backdrop-color; - opacity: 0.8; z-index: var(--dialog-zIndex-standard-background); &.mx_Dialog_staticBackground { @@ -483,21 +493,13 @@ legend { .mx_Dialog_header { position: relative; - padding: 3px 0; - margin-bottom: 10px; + padding: 0; + padding-inline-end: 20px; /* Reserve room for the close button */ + margin-bottom: var(--cpd-space-2x); &.mx_Dialog_headerWithButton > .mx_Dialog_title { text-align: center; } - - &.mx_Dialog_headerWithCancel { - padding-right: 20px; /* leave space for the 'X' cancel button */ - } - - &.mx_Dialog_headerWithCancelOnly { - padding: 0 20px 0 0; - margin: 0; - } } @define-mixin customisedCancelButton { @@ -528,8 +530,8 @@ legend { .mx_Dialog_cancelButton { @mixin customisedCancelButton; position: absolute; - top: 4px; - right: 0; + top: var(--cpd-space-4x); + right: var(--cpd-space-4x); } .mx_Dialog_content { @@ -644,7 +646,7 @@ legend { .mx_Dialog button.warning:not(.mx_Dialog_nonDialogButton):not([class|="maplibregl"]), .mx_Dialog input[type="submit"].warning { - border: solid 1px var(--cpd-color-border-critical-primary); + border: solid 1px var(--cpd-color-border-critical-subtle); color: var(--cpd-color-text-critical-primary); } @@ -658,15 +660,23 @@ legend { } /* Spinner Dialog overide */ -.mx_Dialog_wrapper.mx_Dialog_spinner .mx_Dialog { - width: auto; - border-radius: 8px; - padding: 8px; - box-shadow: none; +.mx_Dialog_wrapper.mx_Dialog_spinner { + /* This is not a real dialog, so we shouldn't show a glass border */ + .mx_Dialog_border { + display: contents; + } - /* Don't show scroll-bars on spinner dialogs */ - overflow-x: hidden; - overflow-y: hidden; + .mx_Dialog { + inline-size: auto; + block-size: auto; + border-radius: 8px; + padding: 8px; + box-shadow: none; + + /* Don't show scroll-bars on spinner dialogs */ + overflow-x: hidden; + overflow-y: hidden; + } } /* TODO: Review mx_GeneralButton usage to see if it can use a different class */ diff --git a/linked-dependencies/matrix-react-sdk/res/css/_components.pcss b/linked-dependencies/matrix-react-sdk/res/css/_components.pcss index a29e7e9857..cc7e41bc99 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/_components.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/_components.pcss @@ -209,7 +209,6 @@ @import "./views/elements/_SearchWarning.pcss"; @import "./views/elements/_ServerPicker.pcss"; @import "./views/elements/_SettingsFlag.pcss"; -@import "./views/elements/_Slider.pcss"; @import "./views/elements/_Spinner.pcss"; @import "./views/elements/_StyledCheckbox.pcss"; @import "./views/elements/_StyledRadioButton.pcss"; @@ -273,6 +272,7 @@ @import "./views/rooms/_Autocomplete.pcss"; @import "./views/rooms/_AuxPanel.pcss"; @import "./views/rooms/_BasicMessageComposer.pcss"; +@import "./views/rooms/_CallGuestLinkButton.pcss"; @import "./views/rooms/_DecryptionFailureBar.pcss"; @import "./views/rooms/_E2EIcon.pcss"; @import "./views/rooms/_EditMessageComposer.pcss"; @@ -336,6 +336,7 @@ @import "./views/settings/_NotificationSettings2.pcss"; @import "./views/settings/_Notifications.pcss"; @import "./views/settings/_PhoneNumbers.pcss"; +@import "./views/settings/_PowerLevelSelector.pcss"; @import "./views/settings/_ProfileSettings.pcss"; @import "./views/settings/_SecureBackupPanel.pcss"; @import "./views/settings/_SetIdServer.pcss"; diff --git a/linked-dependencies/matrix-react-sdk/res/css/structures/_ContextualMenu.pcss b/linked-dependencies/matrix-react-sdk/res/css/structures/_ContextualMenu.pcss index 6aff7738fc..eeb066fd4e 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/structures/_ContextualMenu.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/structures/_ContextualMenu.pcss @@ -30,9 +30,10 @@ limitations under the License. } .mx_ContextualMenu { - border-radius: 8px; - box-shadow: 4px 4px 12px 0 $menu-box-shadow-color; - background-color: $menu-bg-color; + border-radius: 12px; + box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.1); + background-color: var(--cpd-color-bg-canvas-default); + border: var(--cpd-border-width-1) solid var(--cpd-color-border-interactive-secondary); color: $primary-content; position: absolute; z-index: 5001; diff --git a/linked-dependencies/matrix-react-sdk/res/css/structures/_QuickSettingsButton.pcss b/linked-dependencies/matrix-react-sdk/res/css/structures/_QuickSettingsButton.pcss index f5dc45356f..569effd3ae 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/structures/_QuickSettingsButton.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/structures/_QuickSettingsButton.pcss @@ -62,7 +62,7 @@ limitations under the License. font-weight: var(--cpd-font-weight-semibold); font-size: $font-15px; line-height: $font-24px; - color: $primary-content; + color: var(--cpd-color-text-secondary); margin: 0 0 16px; } @@ -76,7 +76,7 @@ limitations under the License. font-size: $font-12px; line-height: $font-15px; text-transform: uppercase; - color: $tertiary-content; + color: var(--cpd-color-text-secondary); margin: 20px 0 12px; } @@ -97,7 +97,7 @@ limitations under the License. margin-left: 6px; font-size: $font-15px; line-height: $font-24px; - color: $secondary-content; + color: var(--cpd-color-text-primary); } } @@ -106,7 +106,7 @@ limitations under the License. margin-left: 22px; font-size: $font-15px; line-height: $font-24px; - color: $secondary-content; + color: var(--cpd-color-text-primary); position: relative; margin-bottom: 16px; } diff --git a/linked-dependencies/matrix-react-sdk/res/css/structures/_SpacePanel.pcss b/linked-dependencies/matrix-react-sdk/res/css/structures/_SpacePanel.pcss index 63f8559660..0252da01b7 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/structures/_SpacePanel.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/structures/_SpacePanel.pcss @@ -203,7 +203,8 @@ limitations under the License. &.mx_SpaceButton_home, &.mx_SpaceButton_favourites, &.mx_SpaceButton_people, - &.mx_SpaceButton_orphans { + &.mx_SpaceButton_orphans, + &.mx_SpaceButton_videoRooms { .mx_SpaceButton_icon { background-color: $panel-actions; @@ -229,6 +230,10 @@ limitations under the License. mask-image: url("$(res)/img/element-icons/roomlist/hash-circle.svg"); } + &.mx_SpaceButton_videoRooms .mx_SpaceButton_icon::before { + mask-image: url("@vector-im/compound-design-tokens/icons/video-call-solid.svg"); + } + &.mx_SpaceButton_new .mx_SpaceButton_icon { &::before { background-color: $primary-content; diff --git a/linked-dependencies/matrix-react-sdk/res/css/structures/_TabbedView.pcss b/linked-dependencies/matrix-react-sdk/res/css/structures/_TabbedView.pcss index 191c554405..756f6ab864 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/structures/_TabbedView.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/structures/_TabbedView.pcss @@ -18,7 +18,7 @@ limitations under the License. .mx_TabbedView { margin: 0; - padding: 0 0 0 16px; + padding: 0 0 0 var(--cpd-space-8x); display: flex; flex-direction: column; inset: 0; diff --git a/linked-dependencies/matrix-react-sdk/res/css/structures/_ThreadsActivityCentre.pcss b/linked-dependencies/matrix-react-sdk/res/css/structures/_ThreadsActivityCentre.pcss index 7c597d95ea..76b38d6c07 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/structures/_ThreadsActivityCentre.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/structures/_ThreadsActivityCentre.pcss @@ -16,11 +16,21 @@ * / */ +.mx_ThreadsActivityCentre_container { + display: flex; +} + .mx_ThreadsActivityCentreButton { border-radius: 8px; margin: 18px auto auto auto; &.expanded { + /** + * override compound default background color when hovered + * should disappear when the space panel will be migrated to compound + */ + background-color: transparent !important; + /* align with settings icon */ margin-left: 21px; @@ -58,12 +68,12 @@ } } -.mx_ThreadsActivity_rows { +.mx_ThreadsActivityCentre_rows { overflow-y: scroll; /* Let some space at the top and the bottom of the pop-up */ max-height: calc(100vh - 200px); - .mx_ThreadsActivityRow { + .mx_ThreadsActivityCentreRow { height: 48px; /* Make the label of the MenuItem stay on one line and truncate with ellipsis if needed */ @@ -72,7 +82,7 @@ overflow: hidden; text-overflow: ellipsis; /* Arbitrary size, keep the TAC as the wanted width */ - width: 194px; + width: 202px; } } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/structures/_ToastContainer.pcss b/linked-dependencies/matrix-react-sdk/res/css/structures/_ToastContainer.pcss index a485afe129..6b18836776 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/structures/_ToastContainer.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/structures/_ToastContainer.pcss @@ -36,16 +36,17 @@ limitations under the License. .mx_Toast_toast { grid-row: 1 / 3; grid-column: 1; - background-color: $system; + background-color: var(--cpd-color-bg-canvas-default); color: $primary-content; - box-shadow: 0px 4px 20px rgba(0, 0, 0, 0.5); - border-radius: 8px; + box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.1); + border: var(--cpd-border-width-1) solid var(--cpd-color-border-interactive-secondary); + border-radius: 12px; overflow: hidden; display: grid; grid-template-columns: 22px 1fr; column-gap: 8px; row-gap: 4px; - padding: 8px; + padding: var(--cpd-space-3x); &.mx_Toast_hasIcon { &::before, diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/auth/_LoginWithQR.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/auth/_LoginWithQR.pcss index 665c351eb7..6a112c7c82 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/auth/_LoginWithQR.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/auth/_LoginWithQR.pcss @@ -14,7 +14,12 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_LoginWithQRSection .mx_AccessibleButton { +.mx_LoginWithQRSection p { + margin-top: 0; + margin-bottom: $spacing-16; +} + +.mx_LoginWithQRSection .mx_AccessibleButton svg { margin-right: $spacing-12; } @@ -69,7 +74,6 @@ limitations under the License. } .mx_QRCode { - padding: $spacing-12 $spacing-40; margin: $spacing-28 0; } @@ -89,7 +93,7 @@ limitations under the License. .mx_LoginWithQR_centreTitle { h1 { - text-align: centre; + text-align: center; } } @@ -141,14 +145,28 @@ limitations under the License. } } + .mx_LoginWithQR_heading { + display: flex; + gap: $spacing-12; + align-items: center; + } + .mx_LoginWithQR_BackButton { - height: $spacing-12; - margin-bottom: $spacing-24; + height: $spacing-28; + border-radius: $spacing-28; + padding: $spacing-4; + box-sizing: border-box; + background-color: var(--cpd-color-bg-subtle-secondary); svg { height: 100%; } } + .mx_LoginWithQR_breadcrumbs { + font-size: $font-13px; + color: var(--cpd-color-text-secondary); + } + .mx_LoginWithQR_main { display: flex; flex-direction: column; @@ -156,7 +174,6 @@ limitations under the License. } .mx_QRCode { - border: 1px solid $quinary-content; border-radius: $spacing-8; display: flex; justify-content: center; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_IconizedContextMenu.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_IconizedContextMenu.pcss index f36c807b60..d15e63e9f9 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_IconizedContextMenu.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_IconizedContextMenu.pcss @@ -36,26 +36,7 @@ limitations under the License. /* the notFirst class is for cases where the optionList might be under a header of sorts. */ &:nth-child(n + 2), .mx_IconizedContextMenu_optionList_notFirst { - /* This is a bit of a hack when we could just use a simple border-top property, */ - /* however we have a (kinda) good reason for doing it this way: we need opacity. */ - /* To get the right color, we need an opacity modifier which means we have to work */ - /* around the problem. PostCSS doesn't support the opacity() function, and if we */ - /* use something like postcss-functions we quickly run into an issue where the */ - /* function we would define gets passed a CSS variable for custom themes, which */ - /* can't be converted easily even when considering https://stackoverflow.com/a/41265350/7037379 */ - // - /* Therefore, we just hack in a line and border the thing ourselves */ - &::before { - border-top: 1px solid $primary-content; - opacity: 0.1; - content: ""; - - /* Counteract the padding problems (width: 100% ignores the 40px padding, */ - /* unless we position it absolutely then it does the right thing). */ - width: 100%; - position: absolute; - left: 0; - } + border-top: var(--cpd-border-width-1) solid var(--cpd-color-gray-400); } /* round the top corners of the top button for the hover effect to be bounded */ @@ -87,7 +68,7 @@ limitations under the License. &:hover, &:focus-visible { - background-color: $menu-selected-color; + background-color: var(--cpd-color-bg-action-secondary-hovered); } &.mx_AccessibleButton_disabled { @@ -137,7 +118,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background-color: $icon-button-color; + background-color: var(--cpd-color-icon-primary); } } @@ -147,7 +128,7 @@ limitations under the License. } .mx_IconizedContextMenu_icon::before { - background-color: $alert; + background-color: var(--cpd-color-icon-critical-primary); } } @@ -172,7 +153,7 @@ limitations under the License. &.mx_IconizedContextMenu_compact { .mx_IconizedContextMenu_optionList > * { - padding: 8px 16px 8px 11px; + padding: 8px 16px 8px 12px; } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_MessageContextMenu.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_MessageContextMenu.pcss index abb48b6b7c..be113c770f 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_MessageContextMenu.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_MessageContextMenu.pcss @@ -29,7 +29,6 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $icon-button-color; } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_RoomGeneralContextMenu.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_RoomGeneralContextMenu.pcss index b5162bb1bb..4017a53f20 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_RoomGeneralContextMenu.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/context_menus/_RoomGeneralContextMenu.pcss @@ -10,6 +10,10 @@ mask-image: url("$(res)/img/element-icons/roomlist/mark-as-read.svg"); } +.mx_RoomGeneralContextMenu_iconMarkAsUnread::before { + mask-image: url("$(res)/img/element-icons/roomlist/mark-as-unread.svg"); +} + .mx_RoomGeneralContextMenu_iconNotificationsDefault::before { mask-image: url("$(res)/img/element-icons/notifications.svg"); } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_CompoundDialog.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_CompoundDialog.pcss index 3675678ed9..addf210863 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_CompoundDialog.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_CompoundDialog.pcss @@ -21,7 +21,7 @@ limitations under the License. /* -------------------------------------------------------------------------------- */ /* Override legacy/default styles for dialogs */ -.mx_Dialog_wrapper.mx_CompoundDialog > .mx_Dialog { +.mx_Dialog_wrapper.mx_CompoundDialog .mx_Dialog { padding: 0; /* we'll manage it ourselves */ color: $primary-content; } @@ -41,14 +41,14 @@ limitations under the License. font-size: $font-24px; margin: 0; /* managed by header class */ } + } - .mx_CompoundDialog_cancelButton { - @mixin customisedCancelButton; - /* Align with middle of title, 30px from right edge */ - position: absolute; - top: 30px; - right: 30px; - } + .mx_CompoundDialog_cancelButton { + @mixin customisedCancelButton; + /* Align with corner radius of dialog */ + position: absolute; + top: var(--cpd-space-4x); + right: var(--cpd-space-4x); } .mx_CompoundDialog_form { diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_ForwardDialog.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_ForwardDialog.pcss index e6c322a77c..69c9bafc89 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_ForwardDialog.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_ForwardDialog.pcss @@ -96,7 +96,8 @@ limitations under the License. padding: 6px; border-radius: 8px; - &:hover { + &:hover, + &.mx_ForwardList_entry_active { background-color: $spacePanel-bg-color; } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_LocationViewDialog.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_LocationViewDialog.pcss index 600c308265..8e04b5f428 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_LocationViewDialog.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_LocationViewDialog.pcss @@ -16,11 +16,6 @@ limitations under the License. .mx_LocationViewDialog_wrapper .mx_Dialog { padding: 0px; - - /* Unset contain and position to allow the close button - to appear outside the dialog */ - contain: unset; - position: unset; } .mx_LocationViewDialog { @@ -37,16 +32,13 @@ limitations under the License. .mx_Dialog_title { display: none; } + } - .mx_Dialog_cancelButton { - z-index: 4010; - position: absolute; - right: 5vw; - top: 5vh; - width: 20px; - height: 20px; - background-color: $dialog-close-external-color; - } + .mx_Dialog_cancelButton { + z-index: 4010; + position: absolute; + left: var(--cpd-space-4x); + top: var(--cpd-space-4x); } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SettingsDialog.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SettingsDialog.pcss index 71dedd3fe3..9b0205a3b4 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SettingsDialog.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SettingsDialog.pcss @@ -20,12 +20,12 @@ limitations under the License. .mx_SpaceSettingsDialog, .mx_SpacePreferencesDialog { width: 90vw; - max-width: 1000px; + max-width: 980px; /* set the height too since tabbed view scrolls itself. */ height: 80vh; .mx_TabbedView { - top: 65px; + top: 90px; } .mx_TabbedView .mx_SettingsTab { diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SpotlightDialog.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SpotlightDialog.pcss index 78346e9b7e..32c14bca9d 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SpotlightDialog.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_SpotlightDialog.pcss @@ -14,38 +14,46 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_SpotlightDialog_wrapper .mx_Dialog { - border-radius: 8px; - overflow-y: initial; - position: relative; - height: 60%; - padding: 0; - contain: unset; /* needed for #mx_SpotlightDialog_keyboardPrompt to not be culled */ - - #mx_SpotlightDialog_keyboardPrompt { - position: absolute; - padding: $spacing-8; +.mx_SpotlightDialog_wrapper { + .mx_Dialog_border { + /* Disable the glass border as this dialog wasn't designed with it in mind */ + display: contents; + } + + .mx_Dialog { + width: fit-content; border-radius: 8px; - background-color: $background; - top: -60px; /* relative to the top of the modal */ - left: 50%; - transform: translateX(-50%); - font-size: $font-12px; - line-height: $font-15px; - color: $secondary-content; - - kbd { - display: inline-block; - padding: 2px $spacing-4; - margin: 0 $spacing-4; - border-radius: 6px; - background-color: $quinary-content; - vertical-align: middle; - color: $tertiary-content; - /* To avoid any styling inherent with elements */ - font-family: inherit; - font-weight: inherit; - font-size: inherit; + overflow-y: initial; + position: relative; + height: 60%; + padding: 0; + contain: unset; /* needed for #mx_SpotlightDialog_keyboardPrompt to not be culled */ + + #mx_SpotlightDialog_keyboardPrompt { + position: absolute; + padding: $spacing-8; + border-radius: 8px; + background-color: $background; + top: -60px; /* relative to the top of the modal */ + left: 50%; + transform: translateX(-50%); + font-size: $font-12px; + line-height: $font-15px; + color: $secondary-content; + + kbd { + display: inline-block; + padding: 2px $spacing-4; + margin: 0 $spacing-4; + border-radius: 6px; + background-color: $quinary-content; + vertical-align: middle; + color: $tertiary-content; + /* To avoid any styling inherent with elements */ + font-family: inherit; + font-weight: inherit; + font-size: inherit; + } } } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_TermsDialog.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_TermsDialog.pcss index 99d7eb720b..9b48cb8945 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_TermsDialog.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/_TermsDialog.pcss @@ -19,7 +19,7 @@ limitations under the License. * terms dialog sizing when it will appear for the integration manager so that * it gets the same basic size as the IM's own modal. */ -.mx_TermsDialog_forIntegrationManager .mx_Dialog { +.mx_TermsDialog_forIntegrationManager .mx_Dialog_border { width: 60%; height: 70%; box-sizing: border-box; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss index 85e5c08258..82e490c781 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/dialogs/security/_AccessSecretStorageDialog.pcss @@ -117,6 +117,8 @@ limitations under the License. .mx_AccessSecretStorageDialog_reset { position: relative; padding-inline-start: $spacingStart; + /* To avoid bold styling inherent with elements */ + font-weight: inherit; &::before { content: ""; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Pill.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Pill.pcss index c697b63de5..8363fc6641 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Pill.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Pill.pcss @@ -26,7 +26,7 @@ limitations under the License. overflow: hidden; cursor: pointer; - color: $accent-fg-color !important; /* To override .markdown-body */ + color: var(--cpd-color-text-on-solid-primary) !important; /* To override .markdown-body */ background-color: $pill-bg-color !important; /* To override .markdown-body */ > * { @@ -35,20 +35,26 @@ limitations under the License. &.mx_UserPill_me, &.mx_AtRoomPill { - background-color: $alert !important; /* To override .markdown-body */ + background-color: var(--cpd-color-bg-critical-primary) !important; /* To override .markdown-body */ } &:hover { background-color: $pill-hover-bg-color !important; /* To override .markdown-body */ } + &:active { + background-color: $pill-press-bg-color !important; /* To override .markdown-body */ + } + &.mx_UserPill_me:hover { - background-color: #ff6b75 !important; /* To override .markdown-body | same on both themes */ + background-color: var( + --cpd-color-bg-critical-hovered + ) !important; /* To override .markdown-body | same on both themes */ } /* We don't want to indicate clickability */ &.mx_AtRoomPill:hover { - background-color: $alert !important; /* To override .markdown-body */ + background-color: var(--cpd-color-bg-critical-primary) !important; /* To override .markdown-body */ cursor: unset; } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Slider.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Slider.pcss deleted file mode 100644 index 2477d542c6..0000000000 --- a/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Slider.pcss +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_Slider { - position: relative; - margin: 0; - flex-grow: 1; - - input[type="range"] { - height: 2.4em; - appearance: none; - width: 100%; - background: none; - font-size: 1em; /* set base multiplier for em units applied later */ - - --active-color: var(--cpd-color-bg-action-primary-rest); - --selection-dot-size: 2.4em; - - &:disabled { - cursor: not-allowed; - - --active-color: $slider-background-color; - } - - &:focus:not(:focus-visible) { - outline: none; - } - - &::-webkit-slider-runnable-track { - width: 100%; - height: 0.4em; - background: $slider-background-color; - border-radius: 5px; - border: 0 solid #000000; - } - &::-webkit-slider-thumb { - border: 0 solid #000000; - width: var(--selection-dot-size); - height: var(--selection-dot-size); - background: var(--active-color); - border-radius: 50%; - -webkit-appearance: none; - margin-top: calc(2px + 1.2em - var(--selection-dot-size)); - } - &:focus::-webkit-slider-runnable-track { - background: $slider-background-color; - } - - &::-moz-range-track { - width: 100%; - height: 0.4em; - background: $slider-background-color; - border-radius: 5px; - border: 0 solid #000000; - } - &::-moz-range-progress { - height: 0.4em; - background: var(--active-color); - border-radius: 5px; - border: 0 solid #000000; - } - &::-moz-range-thumb { - border: 0 solid #000000; - width: var(--selection-dot-size); - height: var(--selection-dot-size); - background: var(--active-color); - border-radius: 50%; - } - - &::-ms-track { - width: 100%; - height: 0.4em; - background: transparent; - border-color: transparent; - color: transparent; - } - &::-ms-fill-lower, - &::-ms-fill-upper { - background: $slider-background-color; - border: 0 solid #000000; - border-radius: 10px; - } - &::-ms-thumb { - margin-top: 1px; - width: var(--selection-dot-size); - height: var(--selection-dot-size); - background: var(--active-color); - border-radius: 50%; - } - &:focus::-ms-fill-upper { - background: $slider-background-color; - } - &::-ms-fill-lower, - &:focus::-ms-fill-lower { - background: var(--active-color); - } - } - - output { - position: absolute; - left: 50%; - transform: translateX(-50%); - - font-size: 1em; /* set base multiplier for em units applied later */ - text-align: center; - top: 3em; - - .mx_Slider_selection_label { - color: $muted-fg-color; - font: var(--cpd-font-body-md-regular); - } - } -} diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Tooltip.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Tooltip.pcss index d35e55db09..54a16a0cbf 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Tooltip.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/elements/_Tooltip.pcss @@ -71,8 +71,8 @@ limitations under the License. max-width: 300px; word-break: break-word; - background-color: #21262c; /* Same on both themes */ - color: $accent-fg-color; + background-color: var(--cpd-color-alpha-gray-1400); + color: var(--cpd-color-text-on-solid-primary); border: 0; text-align: center; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/messages/_DateSeparator.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/messages/_DateSeparator.pcss index de0cd66832..39cffc0f33 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/messages/_DateSeparator.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/messages/_DateSeparator.pcss @@ -39,5 +39,5 @@ limitations under the License. mask-size: contain; mask-repeat: no-repeat; mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); - background-color: $tertiary-content; + background-color: var(--cpd-color-icon-secondary); } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/messages/_MessageActionBar.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/messages/_MessageActionBar.pcss index 040442b8af..64c51972e1 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/messages/_MessageActionBar.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/messages/_MessageActionBar.pcss @@ -18,7 +18,7 @@ limitations under the License. .mx_MessageActionBar { --MessageActionBar-size-button: 28px; --MessageActionBar-size-box: 32px; /* 28px + 2px (margin) * 2 */ - --MessageActionBar-item-hover-background: $panel-actions; + --MessageActionBar-item-hover-background: var(--cpd-color-bg-subtle-secondary); --MessageActionBar-item-hover-borderRadius: 6px; --MessageActionBar-item-hover-zIndex: 1; @@ -30,7 +30,7 @@ limitations under the License. line-height: $font-24px; border-radius: 8px; background: $background; - border: 1px solid $input-border-color; + border: var(--cpd-border-width-1) solid var(--cpd-color-border-disabled); top: -32px; right: 8px; user-select: none; @@ -96,7 +96,7 @@ limitations under the License. --MessageActionBar-icon-size: 18px; width: var(--MessageActionBar-size-button); height: var(--MessageActionBar-size-button); - color: $secondary-content; + color: var(--cpd-color-icon-secondary); display: flex; align-items: center; justify-content: center; @@ -114,7 +114,7 @@ limitations under the License. } &:hover { - color: $primary-content; + color: var(--cpd-color-icon-primary); } &.mx_MessageActionBar_downloadButton { diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/messages/_TimelineSeparator.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/messages/_TimelineSeparator.pcss index 40ca0967a6..d8550179a6 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/messages/_TimelineSeparator.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/messages/_TimelineSeparator.pcss @@ -20,12 +20,12 @@ limitations under the License. display: flex; align-items: center; font: var(--cpd-font-body-md-regular); - color: $roomtopic-color; + color: var(--cpd-color-text-secondary); } .mx_TimelineSeparator > hr { flex: 1 1 0; height: 0; border: none; - border-bottom: 1px solid $menu-selected-color; + border-bottom: 1px solid var(--cpd-color-gray-400); } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_BaseCard.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_BaseCard.pcss index 41552ac578..6d17930fce 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_BaseCard.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_BaseCard.pcss @@ -215,19 +215,19 @@ limitations under the License. padding-top: 10px; padding-bottom: 10px; - border: 1px solid $quinary-content; - box-shadow: 0px 1px 3px rgba(23, 25, 28, 0.05); + border: var(--cpd-border-width-1) solid var(--cpd-color-border-interactive-secondary); + box-shadow: 0px 4px 24px rgba(0, 0, 0, 0.1); } .mx_ContextualMenu_chevron_top { left: auto; right: 22px; - border-bottom-color: $quinary-content; + border-bottom-color: var(--cpd-color-border-interactive-secondary); &::after { content: ""; border: inherit; - border-bottom-color: $menu-bg-color; + border-bottom-color: var(--cpd-color-bg-canvas-default); position: absolute; top: 1px; left: -8px; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_PinnedMessagesCard.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_PinnedMessagesCard.pcss index 7b6396a8ec..5cdafcf7c5 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_PinnedMessagesCard.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_PinnedMessagesCard.pcss @@ -42,7 +42,7 @@ limitations under the License. background: var(--MessageActionBar-item-hover-background); border-radius: var(--MessageActionBar-item-hover-borderRadius); z-index: var(--MessageActionBar-item-hover-zIndex); - color: $primary-content; + color: var(--cpd-color-icon-primary); } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_ThreadPanel.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_ThreadPanel.pcss index 9d14c993df..104430c190 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_ThreadPanel.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/right_panel/_ThreadPanel.pcss @@ -1,5 +1,5 @@ /* -Copyright 2021 The Matrix.org Foundation C.I.C. +Copyright 2021,2024 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -20,11 +20,22 @@ limitations under the License. .mx_BaseCard_header { .mx_BaseCard_header_title { + .mx_BaseCard_header_title_heading { + margin-right: auto; + } + .mx_AccessibleButton { font-size: 12px; color: $secondary-content; } + .mx_ThreadPanel_vertical_separator { + height: 16px; + margin-left: var(--cpd-space-3x); + margin-right: var(--cpd-space-1x); + border-left: 1px solid var(--cpd-color-gray-400); + } + .mx_ThreadPanel_dropdown { padding: 3px $spacing-4 3px $spacing-8; border-radius: 4px; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_BasicMessageComposer.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_BasicMessageComposer.pcss index e09eaa5a04..3add788b12 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_BasicMessageComposer.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_BasicMessageComposer.pcss @@ -20,7 +20,7 @@ limitations under the License. .mx_BasicMessageComposer_inputEmpty > :first-child::before { content: var(--placeholder); - opacity: 0.333; + color: var(--cpd-color-text-secondary); width: 0; height: 0; overflow: visible; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_CallGuestLinkButton.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_CallGuestLinkButton.pcss new file mode 100644 index 0000000000..b11668e547 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_CallGuestLinkButton.pcss @@ -0,0 +1,7 @@ +.mx_JoinRuleDialog { + .mx_JoinRuleDialogButtons { + display: flex; + column-gap: 5px; + justify-content: center; + } +} diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_E2EIcon.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_E2EIcon.pcss index 18ff3f28f9..d6c184f103 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_E2EIcon.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_E2EIcon.pcss @@ -37,15 +37,6 @@ limitations under the License. } } -/* white infill for the transparency */ -.mx_E2EIcon::before { - background-color: #ffffff; - mask-image: url("$(res)/img/e2e/normal.svg"); - mask-repeat: no-repeat; - mask-position: center; - mask-size: 80%; -} - /* transparent-looking border surrounding the shield for when overlain over avatars */ .mx_E2EIcon_bordered { mask-image: url("$(res)/img/e2e/normal.svg"); @@ -59,6 +50,7 @@ limitations under the License. /* shrink the infill of the badge */ &::before { mask-size: 60%; + background: var(--cpd-color-bg-canvas-default); } } @@ -69,7 +61,7 @@ limitations under the License. .mx_E2EIcon_normal::after { mask-image: url("$(res)/img/e2e/normal.svg"); - background-color: $header-panel-text-primary-color; + background-color: var(--cpd-color-icon-tertiary); } .mx_E2EIcon_verified::after { diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_EventTile.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_EventTile.pcss index 4e11f64e77..ad88a7c786 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_EventTile.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_EventTile.pcss @@ -53,7 +53,7 @@ $left-gutter: 64px; height: 16px; &::before { - background-color: $tertiary-content; + background-color: var(--cpd-color-icon-tertiary); mask-repeat: no-repeat; mask-position: center; mask-size: 16px; @@ -858,12 +858,12 @@ $left-gutter: 64px; &.mx_EventTile_e2eIcon_normal::after { mask-image: url("$(res)/img/e2e/normal.svg"); /* regular shield */ - background-color: $header-panel-text-primary-color; /* grey */ + background-color: var(--cpd-color-icon-tertiary); /* grey */ } &.mx_EventTile_e2eIcon_decryption_failure::after { mask-image: url("$(res)/img/e2e/decryption-failure.svg"); /* key in a circle */ - background-color: $secondary-content; + background-color: var(--cpd-color-icon-tertiary); } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_JumpToBottomButton.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_JumpToBottomButton.pcss index 0a760e2cd6..5bf2c0c0ba 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_JumpToBottomButton.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_JumpToBottomButton.pcss @@ -39,13 +39,12 @@ limitations under the License. /* with text-align in parent */ display: inline-block; padding: 0 4px; - color: $accent-fg-color; - background-color: $muted-fg-color; + color: var(--cpd-color-text-on-solid-primary); + background-color: var(--cpd-color-icon-secondary); } .mx_JumpToBottomButton_highlight .mx_JumpToBottomButton_badge { - color: $secondary-accent-color; - background-color: $alert; + background-color: var(--cpd-color-icon-critical-primary); } .mx_JumpToBottomButton_scrollDown { @@ -55,7 +54,7 @@ limitations under the License. border-radius: 19px; box-sizing: border-box; background: $background; - border: 1.3px solid $muted-fg-color; + border: 1.3px solid var(--cpd-color-icon-tertiary); cursor: pointer; } @@ -68,5 +67,5 @@ limitations under the License. mask-size: 20px; mask-position: center 6px; transform: rotate(180deg); - background: $muted-fg-color; + background: var(--cpd-color-icon-tertiary); } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_LegacyRoomHeader.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_LegacyRoomHeader.pcss index 8a92f6e586..ce088f7deb 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_LegacyRoomHeader.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_LegacyRoomHeader.pcss @@ -185,10 +185,10 @@ limitations under the License. } &:hover { - background: $accent-300; + background: var(--cpd-color-bg-subtle-primary); &::before { - background-color: $accent; + background-color: var(--cpd-color-icon-primary); } } } @@ -213,8 +213,8 @@ limitations under the License. margin: 4px; &.mx_Indicator_highlight { - background: $alert; - box-shadow: $alert; + background: var(--cpd-color-icon-critical-primary); + box-shadow: var(--cpd-color-icon-critical-primary); } &.mx_Indicator_notification { @@ -223,8 +223,8 @@ limitations under the License. } &.mx_Indicator_activity { - background: $primary-content; - box-shadow: $primary-content; + background: var(--cpd-color-icon-primary); + box-shadow: var(--cpd-color-icon-primary); } } @@ -234,10 +234,9 @@ limitations under the License. } } -.mx_LegacyRoomHeader_button--highlight, -.mx_LegacyRoomHeader_button:hover { +.mx_LegacyRoomHeader_button--highlight { &::before { - background-color: $accent !important; + background-color: var(--cpd-color-icon-primary) !important; } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposer.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposer.pcss index cb42db35ec..2c8fe592c4 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposer.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposer.pcss @@ -191,7 +191,7 @@ limitations under the License. } .mx_MessageComposer_button { - @mixin composerButton 50%, var(--cpd-color-icon-secondary), var(--cpd-color-bg-subtle-secondary); + @mixin composerButton 50%, var(--cpd-color-icon-primary), var(--cpd-color-bg-subtle-primary); &:last-child { margin-right: auto; @@ -314,74 +314,6 @@ limitations under the License. } } -.mx_MessageComposer_formatting { - cursor: pointer; - margin: 0 11px; - width: 24px; - height: 18px; -} - -.mx_MessageComposer_formatbar_wrapper { - width: 100%; - background-color: $menu-bg-color; - box-shadow: inset 0 1px 0 0 rgba(0, 0, 0, 0.08); -} - -.mx_MessageComposer_formatbar { - margin: auto; - display: flex; - - height: 30px; - - box-sizing: border-box; - padding-left: 62px; - - flex-direction: row; - align-items: center; - font-size: $font-10px; - color: $info-plinth-fg-color; - - * { - margin-right: 4px; - } -} - -.mx_MessageComposer_format_button, -.mx_MessageComposer_formatbar_cancel, -.mx_MessageComposer_formatbar_markdown { - cursor: pointer; -} - -.mx_MessageComposer_formatbar_cancel { - margin-right: 22px; -} - -.mx_MessageComposer_formatbar_markdown { - height: 17px; - width: 30px; - margin-right: 64px; -} - -.mx_MessageComposer_input_markdownIndicator { - height: 10px; - width: 12px; - padding: 4px 4px 4px 0; -} - -.mx_MessageComposer_formatbar_markdown, -.mx_MessageComposer_input_markdownIndicator { - cursor: pointer; - mask-image: url("$(res)/img/markdown.svg"); - mask-size: contain; - mask-position: center; - mask-repeat: no-repeat; - background-color: $icon-button-color; - - &.mx_MessageComposer_markdownDisabled { - opacity: 0.2; - } -} - .mx_MatrixChat_useCompactLayout { .mx_MessageComposer_input { min-height: 50px; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposerFormatBar.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposerFormatBar.pcss index 182e03fed0..68520cc741 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposerFormatBar.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_MessageComposerFormatBar.pcss @@ -22,7 +22,7 @@ limitations under the License. cursor: pointer; border-radius: 8px; background-color: $background; - border: 1px solid $input-border-color; + border: var(--cpd-border-width-1) solid var(--cpd-color-border-disabled); user-select: none; /* equal to z-index of mx_ReplyPreview and mx_RoomView_statusArea (1000) */ /* but as it appears after them in the DOM, will appear on top. */ @@ -48,7 +48,7 @@ limitations under the License. border: none; &:hover { - background: $panel-actions; + background: var(--cpd-color-bg-subtle-secondary); border-radius: 6px; z-index: 1; } @@ -63,11 +63,11 @@ limitations under the License. width: 100%; mask-repeat: no-repeat; mask-position: center; - background-color: $secondary-content; + background-color: var(--cpd-color-icon-secondary); } .mx_MessageComposerFormatBar_button:hover::after { - background-color: $primary-content; + background-color: var(--cpd-color-icon-primary); } .mx_MessageComposerFormatBar_buttonIconBold::after { diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_NotificationBadge.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_NotificationBadge.pcss index 41b1e0f530..6ffe7d9da7 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_NotificationBadge.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_NotificationBadge.pcss @@ -39,7 +39,7 @@ limitations under the License. width: 8px; height: 8px; border-radius: 8px; - background-color: var(--cpd-color-text-primary); + background-color: var(--cpd-color-icon-primary); .mx_NotificationBadge_count { display: none; @@ -86,7 +86,8 @@ limitations under the License. .mx_NotificationBadge_count { font-size: $font-10px; line-height: $font-14px; - color: #fff; /* TODO: Variable */ + font-weight: var(--cpd-font-weight-semibold); + color: var(--cpd-color-text-on-solid-primary); } } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomSublist.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomSublist.pcss index 24898b8925..0e9ad1a9bb 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomSublist.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomSublist.pcss @@ -118,7 +118,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $muted-fg-color; + background: var(--cpd-color-icon-secondary); } } @@ -167,7 +167,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background-color: $tertiary-content; + background-color: var(--cpd-color-icon-secondary); mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomTile.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomTile.pcss index bf68e4035e..decd1067b1 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomTile.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_RoomTile.pcss @@ -131,7 +131,7 @@ limitations under the License. mask-position: center; mask-size: contain; mask-repeat: no-repeat; - background: $primary-content; + background: var(--cpd-color-icon-primary); } } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_TopUnreadMessagesBar.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_TopUnreadMessagesBar.pcss index d26c2b5bfe..6c25ff8e74 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_TopUnreadMessagesBar.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/_TopUnreadMessagesBar.pcss @@ -40,7 +40,7 @@ limitations under the License. border-radius: 19px; box-sizing: border-box; background: $background; - border: 1.3px solid $muted-fg-color; + border: 1.3px solid var(--cpd-color-icon-tertiary); cursor: pointer; } @@ -53,7 +53,7 @@ limitations under the License. mask-repeat: no-repeat; mask-size: 20px; mask-position: center; - background: $muted-fg-color; + background: var(--cpd-color-icon-tertiary); } .mx_TopUnreadMessagesBar_markAsRead { @@ -61,7 +61,7 @@ limitations under the License. width: 18px; height: 18px; background: $background; - border: 1.3px solid $muted-fg-color; + border: 1.3px solid var(--cpd-color-icon-tertiary); border-radius: 10px; margin: 5px auto; } @@ -75,5 +75,5 @@ limitations under the License. mask-repeat: no-repeat; mask-size: 10px; mask-position: 4px 4px; - background: $muted-fg-color; + background: var(--cpd-color-icon-tertiary); } diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/wysiwyg_composer/components/_Editor.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/wysiwyg_composer/components/_Editor.pcss index d4194052fe..595a67b125 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/rooms/wysiwyg_composer/components/_Editor.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/rooms/wysiwyg_composer/components/_Editor.pcss @@ -115,7 +115,7 @@ limitations under the License. max-width: 100%; overflow: hidden; - color: $accent-fg-color; + color: var(--cpd-color-text-on-solid-primary); background-color: $pill-bg-color; /* ...with the overrides from _BasicMessageComposer.pcss */ diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/settings/_IntegrationManager.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/settings/_IntegrationManager.pcss index 505ccf86c2..0576a07246 100644 --- a/linked-dependencies/matrix-react-sdk/res/css/views/settings/_IntegrationManager.pcss +++ b/linked-dependencies/matrix-react-sdk/res/css/views/settings/_IntegrationManager.pcss @@ -15,16 +15,19 @@ limitations under the License. */ .mx_IntegrationManager { - .mx_Dialog { + .mx_Dialog_border { box-sizing: border-box; - padding: 0; width: 60%; height: 70%; - overflow: hidden; max-width: initial; max-height: initial; } + .mx_Dialog { + padding: 0; + overflow: hidden; + } + iframe { background-color: #fff; border: 0; diff --git a/linked-dependencies/matrix-react-sdk/res/css/views/settings/_PowerLevelSelector.pcss b/linked-dependencies/matrix-react-sdk/res/css/views/settings/_PowerLevelSelector.pcss new file mode 100644 index 0000000000..50745d1cd8 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/res/css/views/settings/_PowerLevelSelector.pcss @@ -0,0 +1,21 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +.mx_PowerLevelSelector_Button { + align-self: flex-start; +} diff --git a/linked-dependencies/matrix-react-sdk/res/img/element-icons/check-all.svg b/linked-dependencies/matrix-react-sdk/res/img/element-icons/check-all.svg new file mode 100644 index 0000000000..d81382504d --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/res/img/element-icons/check-all.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/linked-dependencies/matrix-react-sdk/res/img/element-icons/roomlist/mark-as-unread.svg b/linked-dependencies/matrix-react-sdk/res/img/element-icons/roomlist/mark-as-unread.svg new file mode 100644 index 0000000000..a3ea89e3e9 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/res/img/element-icons/roomlist/mark-as-unread.svg @@ -0,0 +1,4 @@ + + + + diff --git a/linked-dependencies/matrix-react-sdk/res/themes/dark/css/_dark.pcss b/linked-dependencies/matrix-react-sdk/res/themes/dark/css/_dark.pcss index eb37ab743a..326debc062 100644 --- a/linked-dependencies/matrix-react-sdk/res/themes/dark/css/_dark.pcss +++ b/linked-dependencies/matrix-react-sdk/res/themes/dark/css/_dark.pcss @@ -22,7 +22,7 @@ $separator: var(--cpd-color-alpha-gray-400); /* ******************** */ $roomlist-bg-color: rgba(38, 40, 45, 0.9); $roomsublist-skeleton-ui-bg: linear-gradient(180deg, $background 0%, #ffffff00 100%); -$roomtile-default-badge-bg-color: $muted-fg-color; +$roomtile-default-badge-bg-color: var(--cpd-color-icon-secondary); /* ******************** */ /** @@ -125,8 +125,9 @@ $roomheader-addroom-fg-color: $primary-content; /* Rich-text-editor */ /* ******************** */ -$pill-bg-color: $room-highlight-color; -$pill-hover-bg-color: #545a66; +$pill-bg-color: var(--cpd-color-bg-action-primary-rest); +$pill-hover-bg-color: var(--cpd-color-bg-action-primary-hovered); +$pill-press-bg-color: var(--cpd-color-bg-action-primary-pressed); /* ******************** */ /* Inputs */ @@ -141,7 +142,7 @@ $input-placeholder: var(--cpd-color-text-placeholder); /* Dialog */ /* ******************** */ $dialog-title-fg-color: $primary-content; -$dialog-backdrop-color: $menu-border-color; +$dialog-backdrop-color: #00000080; $dialog-close-fg-color: $icon-button-color; $dialog-close-external-color: $primary-content; /* ******************** */ @@ -150,7 +151,7 @@ $dialog-close-external-color: $primary-content; /* ******************** */ $system: var(--cpd-color-bg-subtle-secondary); $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #3e444c 0%, #3e444c00 100%); -$roomtile-default-badge-bg-color: $input-darker-fg-color; +$roomtile-default-badge-bg-color: var(--cpd-color-icon-secondary); /* ******************** */ /* Tabbed views */ @@ -199,10 +200,9 @@ $voice-record-icon-color: $quaternary-content; /* Bubble tiles */ /* ******************** */ -$eventbubble-self-bg: #133a34; -$eventbubble-others-bg: #21262c; -$eventbubble-bg-hover: #1c2026; -$eventbubble-reply-color: #c1c6cd; +$eventbubble-self-bg: var(--cpd-color-green-300); +$eventbubble-others-bg: var(--cpd-color-gray-300); +$eventbubble-bg-hover: var(--cpd-color-bg-subtle-secondary); /* ******************** */ /* Lightbox */ @@ -251,8 +251,6 @@ $progressbar-bg-color: var(--cpd-color-gray-200); $kbd-border-color: $strong-input-border-color; $visual-bell-bg-color: #800; $event-timestamp-color: $text-secondary-color; -$slider-background-color: $quinary-content; -$appearance-tab-border-color: $room-highlight-color; $composer-shadow-color: rgba(0, 0, 0, 0.28); $breadcrumb-placeholder-bg-color: #272c35; $theme-button-bg-color: #e3e8f0; diff --git a/linked-dependencies/matrix-react-sdk/res/themes/legacy-dark/css/_legacy-dark.pcss b/linked-dependencies/matrix-react-sdk/res/themes/legacy-dark/css/_legacy-dark.pcss index d9db846583..7e14e85f10 100644 --- a/linked-dependencies/matrix-react-sdk/res/themes/legacy-dark/css/_legacy-dark.pcss +++ b/linked-dependencies/matrix-react-sdk/res/themes/legacy-dark/css/_legacy-dark.pcss @@ -28,8 +28,9 @@ $light-fg-color: $header-panel-text-secondary-color; /* used for focusing form controls */ $focus-bg-color: $room-highlight-color; -$pill-bg-color: $room-highlight-color; -$pill-hover-bg-color: #545a66; +$pill-bg-color: var(--cpd-color-bg-action-primary-rest); +$pill-hover-bg-color: var(--cpd-color-bg-action-primary-hovered); +$pill-press-bg-color: var(--cpd-color-bg-action-primary-pressed); /* informational plinth */ $info-plinth-bg-color: $header-panel-bg-color; @@ -72,8 +73,7 @@ $h3-color: $primary-fg-color; $icon-button-color: var(--cpd-color-icon-tertiary); $dialog-title-fg-color: $base-text-color; -$dialog-backdrop-color: #000; -$dialog-shadow-color: rgba(0, 0, 0, 0.48); +$dialog-backdrop-color: #00000080; $dialog-close-fg-color: $icon-button-color; $dialog-close-external-color: $text-primary-color; @@ -208,9 +208,6 @@ $breadcrumb-placeholder-bg-color: #272c35; $voice-record-stop-border-color: #6f7882; $voice-record-icon-color: #6f7882; -/* Appearance tab colors */ -$appearance-tab-border-color: $room-highlight-color; - $composer-shadow-color: tranparent; $codeblock-background-color: #2a3039; @@ -221,7 +218,6 @@ $inlinecode-background-color: #2a3039; $eventbubble-self-bg: #14322e; $eventbubble-others-bg: $event-selected-color; $eventbubble-bg-hover: #1c2026; -$eventbubble-reply-color: #c1c6cd; /* Location sharing */ /* ******************** */ diff --git a/linked-dependencies/matrix-react-sdk/res/themes/legacy-light/css/_legacy-light.pcss b/linked-dependencies/matrix-react-sdk/res/themes/legacy-light/css/_legacy-light.pcss index 290027e584..5f9b8fd452 100644 --- a/linked-dependencies/matrix-react-sdk/res/themes/legacy-light/css/_legacy-light.pcss +++ b/linked-dependencies/matrix-react-sdk/res/themes/legacy-light/css/_legacy-light.pcss @@ -97,7 +97,6 @@ $icon-button-color: var(--cpd-color-icon-tertiary); $dialog-title-fg-color: #45474a; $dialog-backdrop-color: rgba(46, 48, 51, 0.38); -$dialog-shadow-color: rgba(0, 0, 0, 0.48); $dialog-close-fg-color: $icon-button-color; $dialog-close-external-color: $primary-bg-color; @@ -124,8 +123,9 @@ $rte-code-bg-color: rgba(0, 0, 0, 0.04); $header-panel-text-primary-color: #91a1c0; -$pill-bg-color: #aaa; -$pill-hover-bg-color: #ccc; +$pill-bg-color: var(--cpd-color-bg-action-primary-rest); +$pill-hover-bg-color: var(--cpd-color-bg-action-primary-hovered); +$pill-press-bg-color: var(--cpd-color-bg-action-primary-pressed); $topleftmenu-color: #212121; $roomheader-bg-color: $primary-bg-color; @@ -269,9 +269,6 @@ $visual-bell-bg-color: #faa; $togglesw-off-color: #c1c9d6; $togglesw-ball-color: var(--cpd-color-bg-action-primary-rest); -/* Slider */ -$slider-background-color: #c1c9d6; - $progressbar-bg-color: rgba(141, 151, 165, 0.2); $authpage-bg-color: #2e3649; @@ -305,9 +302,6 @@ $voice-record-live-circle-color: #ff4b55; $voice-record-stop-border-color: #e3e8f0; $voice-record-icon-color: $tertiary-fg-color; -/* FontSlider colors */ -$appearance-tab-border-color: $input-darker-bg-color; - $composer-shadow-color: tranparent; $codeblock-background-color: $header-panel-bg-color; @@ -318,7 +312,6 @@ $inlinecode-background-color: $header-panel-bg-color; $eventbubble-self-bg: #f0fbf8; $eventbubble-others-bg: $system; $eventbubble-bg-hover: #fafbfd; -$eventbubble-reply-color: #c1c6cd; /* pinned events indicator */ $pinned-color: $tertiary-content; diff --git a/linked-dependencies/matrix-react-sdk/res/themes/light-custom/css/_custom.pcss b/linked-dependencies/matrix-react-sdk/res/themes/light-custom/css/_custom.pcss index 140fec60c7..7fadb2cd0a 100644 --- a/linked-dependencies/matrix-react-sdk/res/themes/light-custom/css/_custom.pcss +++ b/linked-dependencies/matrix-react-sdk/res/themes/light-custom/css/_custom.pcss @@ -116,7 +116,6 @@ $settings-grey-fg-color: $primary-content; $eventbubble-self-bg: var(--eventbubble-self-bg, $eventbubble-self-bg); $eventbubble-others-bg: var(--eventbubble-others-bg, $eventbubble-others-bg); $eventbubble-bg-hover: var(--eventbubble-bg-hover, $eventbubble-bg-hover); -$eventbubble-reply-color: var(--eventbubble-reply-color, $eventbubble-reply-color); $reaction-row-button-selected-bg-color: var( --reaction-row-button-selected-bg-color, @@ -126,6 +125,7 @@ $reaction-row-button-selected-bg-color: var( $menu-selected-color: var(--menu-selected-color, $menu-selected-color); $pill-bg-color: var(--other-user-pill-bg-color, $pill-bg-color); $pill-hover-bg-color: var(--other-user-pill-bg-color, $pill-hover-bg-color); +$pill-press-bg-color: var(--other-user-pill-bg-color, $pill-press-bg-color); $icon-button-color: var(--icon-button-color, $icon-button-color); $strong-input-border-color: var(--strong-input-border-color, $strong-input-border-color); diff --git a/linked-dependencies/matrix-react-sdk/res/themes/light-high-contrast/css/_light-high-contrast.pcss b/linked-dependencies/matrix-react-sdk/res/themes/light-high-contrast/css/_light-high-contrast.pcss index 396b494699..2ba97c5a72 100644 --- a/linked-dependencies/matrix-react-sdk/res/themes/light-high-contrast/css/_light-high-contrast.pcss +++ b/linked-dependencies/matrix-react-sdk/res/themes/light-high-contrast/css/_light-high-contrast.pcss @@ -31,8 +31,6 @@ $button-secondary-bg-color: $accent-fg-color; $message-action-bar-fg-color: $primary-content; $voice-record-stop-border-color: $quinary-content; $voice-record-icon-color: $tertiary-content; -$appearance-tab-border-color: $input-darker-bg-color; -$eventbubble-reply-color: $quaternary-content; $roomtopic-color: $secondary-content; /** @@ -104,10 +102,6 @@ $accent-1400: var(--cpd-color-green-1400); background-color: $panel-actions !important; } -.mx_FontScalingPanel_fontSlider { - background-color: $panel-actions !important; -} - .mx_ThemeChoicePanel_themeSelectors > .mx_StyledRadioButton input[type="radio"]:disabled + div { border-color: $primary-content; } diff --git a/linked-dependencies/matrix-react-sdk/res/themes/light/css/_light.pcss b/linked-dependencies/matrix-react-sdk/res/themes/light/css/_light.pcss index a201adbc44..730c115514 100644 --- a/linked-dependencies/matrix-react-sdk/res/themes/light/css/_light.pcss +++ b/linked-dependencies/matrix-react-sdk/res/themes/light/css/_light.pcss @@ -159,8 +159,9 @@ $roomheader-addroom-fg-color: #5c6470; /* Rich-text-editor */ /* ******************** */ -$pill-bg-color: #aaa; -$pill-hover-bg-color: #ccc; +$pill-bg-color: var(--cpd-color-bg-action-primary-rest); +$pill-hover-bg-color: var(--cpd-color-bg-action-primary-hovered); +$pill-press-bg-color: var(--cpd-color-bg-action-primary-pressed); $rte-bg-color: #e9e9e9; $rte-code-bg-color: rgba(0, 0, 0, 0.04); /* ******************** */ @@ -189,10 +190,9 @@ $input-placeholder: var(--cpd-color-text-placeholder); /* Dialog */ /* ******************** */ $dialog-title-fg-color: var(--cpd-color-text-primary); -$dialog-backdrop-color: rgba(46, 48, 51, 0.38); +$dialog-backdrop-color: #030c1b4d; $dialog-close-fg-color: $icon-button-color; $dialog-close-external-color: $background; -$dialog-shadow-color: rgba(0, 0, 0, 0.48); /* ******************** */ /* ImageBody */ @@ -206,13 +206,13 @@ $imagebody-giflabel-color: $accent-fg-color; /* ******************** */ $roomlist-bg-color: rgba(245, 245, 245, 0.9); $roomsublist-skeleton-ui-bg: linear-gradient(180deg, $background 0%, #ffffff00 100%); -$roomtile-default-badge-bg-color: $muted-fg-color; +$roomtile-default-badge-bg-color: var(--cpd-color-icon-secondary); /* ******************** */ /* e2e */ /* ******************** */ -$e2e-verified-color: var(--cpd-color-green-900); -$e2e-warning-color: var(--cpd-color-red-900); +$e2e-verified-color: var(--cpd-color-icon-success-primary); +$e2e-warning-color: var(--cpd-color-icon-critical-primary); $e2e-verified-color-light: var(--cpd-color-green-300); $e2e-warning-color-light: var(--cpd-color-red-300); /* ******************** */ @@ -275,10 +275,9 @@ $voice-record-icon-color: $tertiary-content; /* Bubble tiles */ /* ******************** */ -$eventbubble-self-bg: #e7f8f3; -$eventbubble-others-bg: #e8edf4; -$eventbubble-bg-hover: #f6f7f8; -$eventbubble-reply-color: $quaternary-content; +$eventbubble-self-bg: var(--cpd-color-green-300); +$eventbubble-others-bg: var(--cpd-color-gray-300); +$eventbubble-bg-hover: var(--cpd-color-bg-subtle-secondary); /* ******************** */ /* Lightbox */ @@ -316,8 +315,6 @@ $progressbar-bg-color: var(--cpd-color-gray-200); $kbd-border-color: $strong-input-border-color; $visual-bell-bg-color: #faa; $event-timestamp-color: #acacac; -$slider-background-color: $togglesw-off-color; -$appearance-tab-border-color: $input-darker-bg-color; $composer-shadow-color: rgba(0, 0, 0, 0.04); $breadcrumb-placeholder-bg-color: #e8eef5; $theme-button-bg-color: $quinary-content; diff --git a/linked-dependencies/matrix-react-sdk/src/@types/common.ts b/linked-dependencies/matrix-react-sdk/src/@types/common.ts index 4141418ac4..50e02e6a8f 100644 --- a/linked-dependencies/matrix-react-sdk/src/@types/common.ts +++ b/linked-dependencies/matrix-react-sdk/src/@types/common.ts @@ -16,12 +16,7 @@ limitations under the License. import { JSXElementConstructor } from "react"; -export type { NonEmptyArray } from "matrix-js-sdk/src/matrix"; - -// Based on https://stackoverflow.com/a/53229857/3532235 -export type Without = { [P in Exclude]?: never }; -export type XOR = T | U extends object ? (Without & U) | (Without & T) : T | U; -export type Writeable = { -readonly [P in keyof T]: T[P] }; +export type { NonEmptyArray, XOR, Writeable } from "matrix-js-sdk/src/matrix"; export type ComponentClass = keyof JSX.IntrinsicElements | JSXElementConstructor; diff --git a/linked-dependencies/matrix-react-sdk/src/@types/global.d.ts b/linked-dependencies/matrix-react-sdk/src/@types/global.d.ts index b1c8a4ec14..c62733c0f0 100644 --- a/linked-dependencies/matrix-react-sdk/src/@types/global.d.ts +++ b/linked-dependencies/matrix-react-sdk/src/@types/global.d.ts @@ -151,16 +151,10 @@ declare global { interface HTMLAudioElement { type?: string; - // sinkId & setSinkId are experimental and typescript doesn't know about them - sinkId: string; - setSinkId(outputId: string): void; } interface HTMLVideoElement { type?: string; - // sinkId & setSinkId are experimental and typescript doesn't know about them - sinkId: string; - setSinkId(outputId: string): void; } // Add Chrome-specific `instant` ScrollBehaviour diff --git a/linked-dependencies/matrix-react-sdk/src/@types/matrix-js-sdk.d.ts b/linked-dependencies/matrix-react-sdk/src/@types/matrix-js-sdk.d.ts new file mode 100644 index 0000000000..a58eea55bc --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/@types/matrix-js-sdk.d.ts @@ -0,0 +1,85 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import type { IWidget } from "matrix-widget-api"; +import type { BLURHASH_FIELD } from "../utils/image-media"; +import type { JitsiCallMemberEventType, JitsiCallMemberContent } from "../call-types"; +import type { ILayoutStateEvent, WIDGET_LAYOUT_EVENT_TYPE } from "../stores/widgets/types"; +import type { VoiceBroadcastInfoEventContent, VoiceBroadcastInfoEventType } from "../voice-broadcast/types"; +import type { EncryptedFile } from "matrix-js-sdk/src/types"; + +// Extend Matrix JS SDK types via Typescript declaration merging to support unspecced event fields and types +declare module "matrix-js-sdk/src/types" { + export interface FileInfo { + /** + * @see https://github.com/matrix-org/matrix-spec-proposals/pull/2448 + */ + [BLURHASH_FIELD]?: string; + } + + export interface StateEvents { + // Jitsi-backed video room state events + [JitsiCallMemberEventType]: JitsiCallMemberContent; + + // Unstable widgets state events + "im.vector.modular.widgets": IWidget | {}; + [WIDGET_LAYOUT_EVENT_TYPE]: ILayoutStateEvent; + + // Unstable voice broadcast state events + [VoiceBroadcastInfoEventType]: VoiceBroadcastInfoEventContent; + + // Element custom state events + "im.vector.web.settings": Record; + "org.matrix.room.preview_urls": { disable: boolean }; + + // XXX unspecced usages of `m.room.*` events + "m.room.plumbing": { + status: string; + }; + "m.room.bot.options": unknown; + } + + export interface TimelineEvents { + "io.element.performance_metric": { + "io.element.performance_metrics": { + forEventId: string; + responseTs: number; + kind: "send_time"; + }; + }; + } + + export interface AudioContent { + // MSC1767 + Ideals of MSC2516 as MSC3245 + // https://github.com/matrix-org/matrix-doc/pull/3245 + "org.matrix.msc1767.text"?: string; + "org.matrix.msc1767.file"?: { + url?: string; + file?: EncryptedFile; + name: string; + mimetype: string; + size: number; + }; + "org.matrix.msc1767.audio"?: { + duration: number; + // https://github.com/matrix-org/matrix-doc/pull/3246 + waveform?: number[]; + }; + "org.matrix.msc3245.voice"?: {}; + + "io.element.voice_broadcast_chunk"?: { sequence: number }; + } +} diff --git a/linked-dependencies/matrix-react-sdk/src/ContentMessages.ts b/linked-dependencies/matrix-react-sdk/src/ContentMessages.ts index 9a8a1d7c4f..7999095681 100644 --- a/linked-dependencies/matrix-react-sdk/src/ContentMessages.ts +++ b/linked-dependencies/matrix-react-sdk/src/ContentMessages.ts @@ -19,7 +19,6 @@ limitations under the License. import { MatrixClient, MsgType, - IImageInfo, HTTPError, IEventRelation, ISendEventResponse, @@ -28,19 +27,19 @@ import { UploadProgress, THREAD_RELATION_TYPE, } from "matrix-js-sdk/src/matrix"; +import { + ImageInfo, + AudioInfo, + VideoInfo, + EncryptedFile, + MediaEventContent, + MediaEventInfo, +} from "matrix-js-sdk/src/types"; import encrypt from "matrix-encrypt-attachment"; import extractPngChunks from "png-chunks-extract"; import { logger } from "matrix-js-sdk/src/logger"; import { removeElement } from "matrix-js-sdk/src/utils"; -import { - AudioInfo, - EncryptedFile, - ImageInfo, - IMediaEventContent, - IMediaEventInfo, - VideoInfo, -} from "./customisations/models/IMediaEventContent"; import dis from "./dispatcher/dispatcher"; import { _t } from "./languageHandler"; import Modal from "./Modal"; @@ -390,7 +389,7 @@ export default class ContentMessages { url: string, roomId: string, threadId: string | null, - info: IImageInfo, + info: ImageInfo, text: string, matrixClient: MatrixClient, ): Promise { @@ -537,7 +536,7 @@ export default class ContentMessages { promBefore?: Promise, ): Promise { const fileName = file.name || _t("common|attachment"); - const content: Omit & { info: Partial } = { + const content: Omit & { info: Partial } = { body: fileName, info: { size: file.size, @@ -623,7 +622,7 @@ export default class ContentMessages { if (upload.cancelled) throw new UploadCanceledError(); const threadId = relation?.rel_type === THREAD_RELATION_TYPE.name ? relation.event_id : null; - const response = await matrixClient.sendMessage(roomId, threadId ?? null, content); + const response = await matrixClient.sendMessage(roomId, threadId ?? null, content as MediaEventContent); if (SettingsStore.getValue("Performance.addSendMessageTimingMetadata")) { sendRoundTripMetric(matrixClient, roomId, response.event_id); diff --git a/linked-dependencies/matrix-react-sdk/src/HtmlUtils.tsx b/linked-dependencies/matrix-react-sdk/src/HtmlUtils.tsx index 9a37e76ca8..b518c43973 100644 --- a/linked-dependencies/matrix-react-sdk/src/HtmlUtils.tsx +++ b/linked-dependencies/matrix-react-sdk/src/HtmlUtils.tsx @@ -17,32 +17,25 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { LegacyRef, ReactElement, ReactNode } from "react"; +import React, { LegacyRef, ReactNode } from "react"; import sanitizeHtml from "sanitize-html"; import classNames from "classnames"; import EMOJIBASE_REGEX from "emojibase-regex"; -import { merge } from "lodash"; import katex from "katex"; import { decode } from "html-entities"; import { IContent } from "matrix-js-sdk/src/matrix"; import { Optional } from "matrix-events-sdk"; -import _Linkify from "linkify-react"; import escapeHtml from "escape-html"; import GraphemeSplitter from "graphemer"; import { getEmojiFromUnicode } from "@matrix-org/emojibase-bindings"; -import { - _linkifyElement, - _linkifyString, - ELEMENT_URL_PATTERN, - options as linkifyMatrixOptions, -} from "./linkify-matrix"; import { IExtendedSanitizeOptions } from "./@types/sanitize-html"; import SettingsStore from "./settings/SettingsStore"; -import { tryTransformPermalinkToLocalHref } from "./utils/permalinks/Permalinks"; -import { mediaFromMxc } from "./customisations/Media"; import { stripHTMLReply, stripPlainReply } from "./utils/Reply"; import { PERMITTED_URL_SCHEMES } from "./utils/UrlUtils"; +import { sanitizeHtmlParams, transformTags } from "./Linkify"; + +export { Linkify, linkifyElement, linkifyAndSanitizeHtml } from "./Linkify"; // Anything outside the basic multilingual plane will be a surrogate pair const SURROGATE_PAIR_PATTERN = /([\ud800-\udbff])([\udc00-\udfff])/; @@ -58,10 +51,6 @@ const EMOJI_SEPARATOR_REGEX = /[\u200D\u200B\s]|\uFE0F/g; const BIGEMOJI_REGEX = new RegExp(`^(${EMOJIBASE_REGEX.source})+$`, "i"); -const COLOR_REGEX = /^#[0-9a-fA-F]{6}$/; - -const MEDIA_API_MXC_REGEX = /\/_matrix\/media\/r0\/(?:download|thumbnail)\/(.+?)\/(.+?)(?:[?/]|$)/; - /* * Return true if the given string contains emoji * Uses a much, much simpler regex than emojibase's so will give false @@ -120,182 +109,6 @@ export function isUrlPermitted(inputUrl: string): boolean { } } -const transformTags: IExtendedSanitizeOptions["transformTags"] = { - // custom to matrix - // add blank targets to all hyperlinks except vector URLs - "a": function (tagName: string, attribs: sanitizeHtml.Attributes) { - if (attribs.href) { - attribs.target = "_blank"; // by default - - const transformed = tryTransformPermalinkToLocalHref(attribs.href); // only used to check if it is a link that can be handled locally - if ( - transformed !== attribs.href || // it could be converted so handle locally symbols e.g. @user:server.tdl, matrix: and matrix.to - attribs.href.match(ELEMENT_URL_PATTERN) // for https links to Element domains - ) { - delete attribs.target; - } - } else { - // Delete the href attrib if it is falsy - delete attribs.href; - } - - attribs.rel = "noreferrer noopener"; // https://mathiasbynens.github.io/rel-noopener/ - return { tagName, attribs }; - }, - "img": function (tagName: string, attribs: sanitizeHtml.Attributes) { - let src = attribs.src; - // Strip out imgs that aren't `mxc` here instead of using allowedSchemesByTag - // because transformTags is used _before_ we filter by allowedSchemesByTag and - // we don't want to allow images with `https?` `src`s. - // We also drop inline images (as if they were not present at all) when the "show - // images" preference is disabled. Future work might expose some UI to reveal them - // like standalone image events have. - if (!src || !SettingsStore.getValue("showImages")) { - return { tagName, attribs: {} }; - } - - if (!src.startsWith("mxc://")) { - const match = MEDIA_API_MXC_REGEX.exec(src); - if (match) { - src = `mxc://${match[1]}/${match[2]}`; - } - } - - if (!src.startsWith("mxc://")) { - return { tagName, attribs: {} }; - } - - const requestedWidth = Number(attribs.width); - const requestedHeight = Number(attribs.height); - const width = Math.min(requestedWidth || 800, 800); - const height = Math.min(requestedHeight || 600, 600); - // specify width/height as max values instead of absolute ones to allow object-fit to do its thing - // we only allow our own styles for this tag so overwrite the attribute - attribs.style = `max-width: ${width}px; max-height: ${height}px;`; - if (requestedWidth) { - attribs.style += "width: 100%;"; - } - if (requestedHeight) { - attribs.style += "height: 100%;"; - } - - attribs.src = mediaFromMxc(src).getThumbnailOfSourceHttp(width, height)!; - return { tagName, attribs }; - }, - "code": function (tagName: string, attribs: sanitizeHtml.Attributes) { - if (typeof attribs.class !== "undefined") { - // Filter out all classes other than ones starting with language- for syntax highlighting. - const classes = attribs.class.split(/\s/).filter(function (cl) { - return cl.startsWith("language-") && !cl.startsWith("language-_"); - }); - attribs.class = classes.join(" "); - } - return { tagName, attribs }; - }, - // eslint-disable-next-line @typescript-eslint/naming-convention - "*": function (tagName: string, attribs: sanitizeHtml.Attributes) { - // Delete any style previously assigned, style is an allowedTag for font, span & img, - // because attributes are stripped after transforming. - // For img this is trusted as it is generated wholly within the img transformation method. - if (tagName !== "img") { - delete attribs.style; - } - - // Sanitise and transform data-mx-color and data-mx-bg-color to their CSS - // equivalents - const customCSSMapper: Record = { - "data-mx-color": "color", - "data-mx-bg-color": "background-color", - // $customAttributeKey: $cssAttributeKey - }; - - let style = ""; - Object.keys(customCSSMapper).forEach((customAttributeKey) => { - const cssAttributeKey = customCSSMapper[customAttributeKey]; - const customAttributeValue = attribs[customAttributeKey]; - if ( - customAttributeValue && - typeof customAttributeValue === "string" && - COLOR_REGEX.test(customAttributeValue) - ) { - style += cssAttributeKey + ":" + customAttributeValue + ";"; - delete attribs[customAttributeKey]; - } - }); - - if (style) { - attribs.style = style + (attribs.style || ""); - } - - return { tagName, attribs }; - }, -}; - -const sanitizeHtmlParams: IExtendedSanitizeOptions = { - allowedTags: [ - "font", // custom to matrix for IRC-style font coloring - "del", // for markdown - "h1", - "h2", - "h3", - "h4", - "h5", - "h6", - "blockquote", - "p", - "a", - "ul", - "ol", - "sup", - "sub", - "nl", - "li", - "b", - "i", - "u", - "strong", - "em", - "strike", - "code", - "hr", - "br", - "div", - "table", - "thead", - "caption", - "tbody", - "tr", - "th", - "td", - "pre", - "span", - "img", - "details", - "summary", - ], - allowedAttributes: { - // attribute sanitization happens after transformations, so we have to accept `style` for font, span & img - // but strip during the transformation. - // custom ones first: - font: ["color", "data-mx-bg-color", "data-mx-color", "style"], // custom to matrix - span: ["data-mx-maths", "data-mx-bg-color", "data-mx-color", "data-mx-spoiler", "style"], // custom to matrix - div: ["data-mx-maths"], - a: ["href", "name", "target", "rel"], // remote target: custom to matrix - // img tags also accept width/height, we just map those to max-width & max-height during transformation - img: ["src", "alt", "title", "style"], - ol: ["start"], - code: ["class"], // We don't actually allow all classes, we filter them in transformTags - }, - // Lots of these won't come up by default because we don't allow them - selfClosing: ["img", "br", "hr", "area", "base", "basefont", "input", "link", "meta"], - // URL schemes we permit - allowedSchemes: PERMITTED_URL_SCHEMES, - allowProtocolRelative: false, - transformTags, - // 50 levels deep "should be enough for anyone" - nestingLimit: 50, -}; - // this is the same as the above except with less rewriting const composerSanitizeHtmlParams: IExtendedSanitizeOptions = { ...sanitizeHtmlParams, @@ -657,48 +470,6 @@ export function topicToHtml( ); } -/* Wrapper around linkify-react merging in our default linkify options */ -export function Linkify({ as, options, children }: React.ComponentProps): ReactElement { - return ( - <_Linkify as={as} options={merge({}, linkifyMatrixOptions, options)}> - {children} - - ); -} - -/** - * Linkifies the given string. This is a wrapper around 'linkifyjs/string'. - * - * @param {string} str string to linkify - * @param {object} [options] Options for linkifyString. Default: linkifyMatrixOptions - * @returns {string} Linkified string - */ -export function linkifyString(str: string, options = linkifyMatrixOptions): string { - return _linkifyString(str, options); -} - -/** - * Linkifies the given DOM element. This is a wrapper around 'linkifyjs/element'. - * - * @param {object} element DOM element to linkify - * @param {object} [options] Options for linkifyElement. Default: linkifyMatrixOptions - * @returns {object} - */ -export function linkifyElement(element: HTMLElement, options = linkifyMatrixOptions): HTMLElement { - return _linkifyElement(element, options); -} - -/** - * Linkify the given string and sanitize the HTML afterwards. - * - * @param {string} dirtyHtml The HTML string to sanitize and linkify - * @param {object} [options] Options for linkifyString. Default: linkifyMatrixOptions - * @returns {string} - */ -export function linkifyAndSanitizeHtml(dirtyHtml: string, options = linkifyMatrixOptions): string { - return sanitizeHtml(linkifyString(dirtyHtml, options), sanitizeHtmlParams); -} - /** * Returns if a node is a block element or not. * Only takes html nodes into account that are allowed in matrix messages. diff --git a/linked-dependencies/matrix-react-sdk/src/IConfigOptions.ts b/linked-dependencies/matrix-react-sdk/src/IConfigOptions.ts index 0f9757dd23..0e9645349b 100644 --- a/linked-dependencies/matrix-react-sdk/src/IConfigOptions.ts +++ b/linked-dependencies/matrix-react-sdk/src/IConfigOptions.ts @@ -119,6 +119,7 @@ export interface IConfigOptions { }; element_call: { url?: string; + guest_spa_url?: string; use_exclusively?: boolean; participant_limit?: number; brand?: string; diff --git a/linked-dependencies/matrix-react-sdk/src/Lifecycle.ts b/linked-dependencies/matrix-react-sdk/src/Lifecycle.ts index b6fce3b636..61097c13c2 100644 --- a/linked-dependencies/matrix-react-sdk/src/Lifecycle.ts +++ b/linked-dependencies/matrix-react-sdk/src/Lifecycle.ts @@ -19,13 +19,12 @@ limitations under the License. import { ReactNode } from "react"; import { createClient, MatrixClient, SSOAction, OidcTokenRefresher } from "matrix-js-sdk/src/matrix"; -import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { IEncryptedPayload } from "matrix-js-sdk/src/crypto/aes"; import { QueryDict } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; import { IMatrixClientCreds, MatrixClientPeg } from "./MatrixClientPeg"; -import SecurityCustomisations from "./customisations/Security"; +import { ModuleRunner } from "./modules/ModuleRunner"; import EventIndexPeg from "./indexing/EventIndexPeg"; import createMatrixClient from "./utils/createMatrixClient"; import Notifier from "./Notifier"; @@ -52,8 +51,6 @@ import LegacyCallHandler from "./LegacyCallHandler"; import LifecycleCustomisations from "./customisations/Lifecycle"; import ErrorDialog from "./components/views/dialogs/ErrorDialog"; import { _t } from "./languageHandler"; -import LazyLoadingResyncDialog from "./components/views/dialogs/LazyLoadingResyncDialog"; -import LazyLoadingDisabledDialog from "./components/views/dialogs/LazyLoadingDisabledDialog"; import SessionRestoreErrorDialog from "./components/views/dialogs/SessionRestoreErrorDialog"; import StorageEvictedDialog from "./components/views/dialogs/StorageEvictedDialog"; import { setSentryUser } from "./sentry"; @@ -439,39 +436,6 @@ async function onFailedDelegatedAuthLogin(description: string | ReactNode, tryAg }); } -export function handleInvalidStoreError(e: InvalidStoreError): Promise | void { - if (e.reason === InvalidStoreError.TOGGLED_LAZY_LOADING) { - return Promise.resolve() - .then(() => { - const lazyLoadEnabled = e.value; - if (lazyLoadEnabled) { - return new Promise((resolve) => { - Modal.createDialog(LazyLoadingResyncDialog, { - onFinished: resolve, - }); - }); - } else { - // show warning about simultaneous use - // between LL/non-LL version on same host. - // as disabling LL when previously enabled - // is a strong indicator of this (/develop & /app) - return new Promise((resolve) => { - Modal.createDialog(LazyLoadingDisabledDialog, { - onFinished: resolve, - host: window.location.host, - }); - }); - } - }) - .then(() => { - return MatrixClientPeg.safeGet().store.deleteAllData(); - }) - .then(() => { - PlatformPeg.get()?.reload(); - }); - } -} - function registerAsGuest(hsUrl: string, isUrl?: string, defaultDeviceDisplayName?: string): Promise { logger.log(`Doing guest login on ${hsUrl}`); @@ -899,7 +863,7 @@ async function persistCredentials(credentials: IMatrixClientCreds): Promise = { + // custom to matrix + // add blank targets to all hyperlinks except vector URLs + "a": function (tagName: string, attribs: sanitizeHtml.Attributes) { + if (attribs.href) { + attribs.target = "_blank"; // by default + + const transformed = tryTransformPermalinkToLocalHref(attribs.href); // only used to check if it is a link that can be handled locally + if ( + transformed !== attribs.href || // it could be converted so handle locally symbols e.g. @user:server.tdl, matrix: and matrix.to + attribs.href.match(ELEMENT_URL_PATTERN) // for https links to Element domains + ) { + delete attribs.target; + } + } else { + // Delete the href attrib if it is falsy + delete attribs.href; + } + + attribs.rel = "noreferrer noopener"; // https://mathiasbynens.github.io/rel-noopener/ + return { tagName, attribs }; + }, + "img": function (tagName: string, attribs: sanitizeHtml.Attributes) { + let src = attribs.src; + // Strip out imgs that aren't `mxc` here instead of using allowedSchemesByTag + // because transformTags is used _before_ we filter by allowedSchemesByTag and + // we don't want to allow images with `https?` `src`s. + // We also drop inline images (as if they were not present at all) when the "show + // images" preference is disabled. Future work might expose some UI to reveal them + // like standalone image events have. + if (!src || !SettingsStore.getValue("showImages")) { + return { tagName, attribs: {} }; + } + + if (!src.startsWith("mxc://")) { + const match = MEDIA_API_MXC_REGEX.exec(src); + if (match) { + src = `mxc://${match[1]}/${match[2]}`; + } + } + + if (!src.startsWith("mxc://")) { + return { tagName, attribs: {} }; + } + + const requestedWidth = Number(attribs.width); + const requestedHeight = Number(attribs.height); + const width = Math.min(requestedWidth || 800, 800); + const height = Math.min(requestedHeight || 600, 600); + // specify width/height as max values instead of absolute ones to allow object-fit to do its thing + // we only allow our own styles for this tag so overwrite the attribute + attribs.style = `max-width: ${width}px; max-height: ${height}px;`; + if (requestedWidth) { + attribs.style += "width: 100%;"; + } + if (requestedHeight) { + attribs.style += "height: 100%;"; + } + + attribs.src = mediaFromMxc(src).getThumbnailOfSourceHttp(width, height)!; + return { tagName, attribs }; + }, + "code": function (tagName: string, attribs: sanitizeHtml.Attributes) { + if (typeof attribs.class !== "undefined") { + // Filter out all classes other than ones starting with language- for syntax highlighting. + const classes = attribs.class.split(/\s/).filter(function (cl) { + return cl.startsWith("language-") && !cl.startsWith("language-_"); + }); + attribs.class = classes.join(" "); + } + return { tagName, attribs }; + }, + // eslint-disable-next-line @typescript-eslint/naming-convention + "*": function (tagName: string, attribs: sanitizeHtml.Attributes) { + // Delete any style previously assigned, style is an allowedTag for font, span & img, + // because attributes are stripped after transforming. + // For img this is trusted as it is generated wholly within the img transformation method. + if (tagName !== "img") { + delete attribs.style; + } + + // Sanitise and transform data-mx-color and data-mx-bg-color to their CSS + // equivalents + const customCSSMapper: Record = { + "data-mx-color": "color", + "data-mx-bg-color": "background-color", + // $customAttributeKey: $cssAttributeKey + }; + + let style = ""; + Object.keys(customCSSMapper).forEach((customAttributeKey) => { + const cssAttributeKey = customCSSMapper[customAttributeKey]; + const customAttributeValue = attribs[customAttributeKey]; + if ( + customAttributeValue && + typeof customAttributeValue === "string" && + COLOR_REGEX.test(customAttributeValue) + ) { + style += cssAttributeKey + ":" + customAttributeValue + ";"; + delete attribs[customAttributeKey]; + } + }); + + if (style) { + attribs.style = style + (attribs.style || ""); + } + + return { tagName, attribs }; + }, +}; + +export const sanitizeHtmlParams: IExtendedSanitizeOptions = { + allowedTags: [ + "font", // custom to matrix for IRC-style font coloring + "del", // for markdown + "h1", + "h2", + "h3", + "h4", + "h5", + "h6", + "blockquote", + "p", + "a", + "ul", + "ol", + "sup", + "sub", + "nl", + "li", + "b", + "i", + "u", + "strong", + "em", + "strike", + "code", + "hr", + "br", + "div", + "table", + "thead", + "caption", + "tbody", + "tr", + "th", + "td", + "pre", + "span", + "img", + "details", + "summary", + ], + allowedAttributes: { + // attribute sanitization happens after transformations, so we have to accept `style` for font, span & img + // but strip during the transformation. + // custom ones first: + font: ["color", "data-mx-bg-color", "data-mx-color", "style"], // custom to matrix + span: ["data-mx-maths", "data-mx-bg-color", "data-mx-color", "data-mx-spoiler", "style"], // custom to matrix + div: ["data-mx-maths"], + a: ["href", "name", "target", "rel"], // remote target: custom to matrix + // img tags also accept width/height, we just map those to max-width & max-height during transformation + img: ["src", "alt", "title", "style"], + ol: ["start"], + code: ["class"], // We don't actually allow all classes, we filter them in transformTags + }, + // Lots of these won't come up by default because we don't allow them + selfClosing: ["img", "br", "hr", "area", "base", "basefont", "input", "link", "meta"], + // URL schemes we permit + allowedSchemes: PERMITTED_URL_SCHEMES, + allowProtocolRelative: false, + transformTags, + // 50 levels deep "should be enough for anyone" + nestingLimit: 50, +}; + +/* Wrapper around linkify-react merging in our default linkify options */ +export function Linkify({ as, options, children }: React.ComponentProps): ReactElement { + return ( + <_Linkify as={as} options={merge({}, linkifyMatrixOptions, options)}> + {children} + + ); +} + +/** + * Linkifies the given string. This is a wrapper around 'linkifyjs/string'. + * + * @param {string} str string to linkify + * @param {object} [options] Options for linkifyString. Default: linkifyMatrixOptions + * @returns {string} Linkified string + */ +export function linkifyString(str: string, options = linkifyMatrixOptions): string { + return _linkifyString(str, options); +} + +/** + * Linkifies the given DOM element. This is a wrapper around 'linkifyjs/element'. + * + * @param {object} element DOM element to linkify + * @param {object} [options] Options for linkifyElement. Default: linkifyMatrixOptions + * @returns {object} + */ +export function linkifyElement(element: HTMLElement, options = linkifyMatrixOptions): HTMLElement { + return _linkifyElement(element, options); +} + +/** + * Linkify the given string and sanitize the HTML afterwards. + * + * @param {string} dirtyHtml The HTML string to sanitize and linkify + * @param {object} [options] Options for linkifyString. Default: linkifyMatrixOptions + * @returns {string} + */ +export function linkifyAndSanitizeHtml(dirtyHtml: string, options = linkifyMatrixOptions): string { + return sanitizeHtml(linkifyString(dirtyHtml, options), sanitizeHtmlParams); +} diff --git a/linked-dependencies/matrix-react-sdk/src/Login.ts b/linked-dependencies/matrix-react-sdk/src/Login.ts index 4f198fc634..abfdcedf83 100644 --- a/linked-dependencies/matrix-react-sdk/src/Login.ts +++ b/linked-dependencies/matrix-react-sdk/src/Login.ts @@ -27,7 +27,7 @@ import { import { logger } from "matrix-js-sdk/src/logger"; import { IMatrixClientCreds } from "./MatrixClientPeg"; -import SecurityCustomisations from "./customisations/Security"; +import { ModuleRunner } from "./modules/ModuleRunner"; import { getOidcClientId } from "./utils/oidc/registerClient"; import { IConfigOptions } from "./IConfigOptions"; import SdkConfig from "./SdkConfig"; @@ -291,7 +291,7 @@ export async function sendLoginRequest( accessToken: data.access_token, }; - SecurityCustomisations.examineLoginResponse?.(data, creds); + ModuleRunner.instance.extensions.cryptoSetup.examineLoginResponse(data, creds); return creds; } diff --git a/linked-dependencies/matrix-react-sdk/src/MatrixClientPeg.ts b/linked-dependencies/matrix-react-sdk/src/MatrixClientPeg.ts index 4758517390..07ff3c7178 100644 --- a/linked-dependencies/matrix-react-sdk/src/MatrixClientPeg.ts +++ b/linked-dependencies/matrix-react-sdk/src/MatrixClientPeg.ts @@ -29,9 +29,8 @@ import { RoomNameType, TokenRefreshFunction, } from "matrix-js-sdk/src/matrix"; +import { VerificationMethod } from "matrix-js-sdk/src/types"; import * as utils from "matrix-js-sdk/src/utils"; -import { verificationMethods } from "matrix-js-sdk/src/crypto"; -import { SHOW_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode"; import { logger } from "matrix-js-sdk/src/logger"; import createMatrixClient from "./utils/createMatrixClient"; @@ -42,7 +41,7 @@ import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientB import * as StorageManager from "./utils/StorageManager"; import IdentityAuthClient from "./IdentityAuthClient"; import { crossSigningCallbacks, tryToUnlockSecretStorageWithDehydrationKey } from "./SecurityManager"; -import SecurityCustomisations from "./customisations/Security"; +import { ModuleRunner } from "./modules/ModuleRunner"; import { SlidingSyncManager } from "./SlidingSyncManager"; import CryptoStoreTooNewDialog from "./components/views/dialogs/CryptoStoreTooNewDialog"; import { _t, UserFriendlyError } from "./languageHandler"; @@ -433,9 +432,9 @@ class MatrixClientPegClass implements IMatrixClientPeg { // the call arrives. iceCandidatePoolSize: 20, verificationMethods: [ - verificationMethods.SAS, - SHOW_QR_CODE_METHOD, - verificationMethods.RECIPROCATE_QR_CODE, + VerificationMethod.Sas, + VerificationMethod.ShowQrCode, + VerificationMethod.Reciprocate, ], identityServer: new IdentityAuthClient(), // These are always installed regardless of the labs flag so that cross-signing features @@ -464,8 +463,9 @@ class MatrixClientPegClass implements IMatrixClientPeg { }, }; - if (SecurityCustomisations.getDehydrationKey) { - opts.cryptoCallbacks!.getDehydrationKey = SecurityCustomisations.getDehydrationKey; + const dehydrationKeyCallback = ModuleRunner.instance.extensions.cryptoSetup.getDehydrationKeyCallback(); + if (dehydrationKeyCallback) { + opts.cryptoCallbacks!.getDehydrationKey = dehydrationKeyCallback; } this.matrixClient = createMatrixClient(opts); diff --git a/linked-dependencies/matrix-react-sdk/src/Modal.tsx b/linked-dependencies/matrix-react-sdk/src/Modal.tsx index f2835799fd..aa4ba691dc 100644 --- a/linked-dependencies/matrix-react-sdk/src/Modal.tsx +++ b/linked-dependencies/matrix-react-sdk/src/Modal.tsx @@ -20,7 +20,7 @@ import ReactDOM from "react-dom"; import classNames from "classnames"; import { defer, sleep } from "matrix-js-sdk/src/utils"; import { TypedEventEmitter } from "matrix-js-sdk/src/matrix"; -import { TooltipProvider } from "@vector-im/compound-web"; +import { Glass, TooltipProvider } from "@vector-im/compound-web"; import dis from "./dispatcher/dispatcher"; import AsyncWrapper from "./AsyncWrapper"; @@ -376,7 +376,9 @@ export class ModalManager extends TypedEventEmitter
-
{this.staticModal.elem}
+ +
{this.staticModal.elem}
+
-
{modal.elem}
+ +
{modal.elem}
+
0) { + const markedUnreadState = getMarkedUnreadState(room); + if (greyNotifs > 0 || markedUnreadState) { return { symbol: null, count: trueCount, level: NotificationLevel.Notification }; } diff --git a/linked-dependencies/matrix-react-sdk/src/ScalarMessaging.ts b/linked-dependencies/matrix-react-sdk/src/ScalarMessaging.ts index fb2801c9b6..0ee6921a24 100644 --- a/linked-dependencies/matrix-react-sdk/src/ScalarMessaging.ts +++ b/linked-dependencies/matrix-react-sdk/src/ScalarMessaging.ts @@ -291,7 +291,8 @@ Response: */ -import { IContent, MatrixEvent, IEvent } from "matrix-js-sdk/src/matrix"; +import { IContent, MatrixEvent, IEvent, StateEvents } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClientPeg } from "./MatrixClientPeg"; @@ -357,7 +358,10 @@ function inviteUser(event: MessageEvent, roomId: string, userId: string): v if (room) { // if they are already invited or joined we can resolve immediately. const member = room.getMember(userId); - if (member && ["join", "invite"].includes(member.membership!)) { + if ( + member && + ([KnownMembership.Join, KnownMembership.Invite] as Array).includes(member.membership) + ) { sendResponse(event, { success: true, }); @@ -608,15 +612,7 @@ async function setBotPower( }); } } - await client.setPowerLevel( - roomId, - userId, - level, - new MatrixEvent({ - type: "m.room.power_levels", - content: powerLevels, - }), - ); + await client.setPowerLevel(roomId, userId, level); return sendResponse(event, { success: true, }); @@ -669,7 +665,7 @@ function canSendEvent(event: MessageEvent, roomId: string): void { sendError(event, _t("scalar|error_room_unknown")); return; } - if (room.getMyMembership() !== "join") { + if (room.getMyMembership() !== KnownMembership.Join) { sendError(event, _t("scalar|error_membership")); return; } @@ -721,7 +717,7 @@ async function getOpenIdToken(event: MessageEvent): Promise { async function sendEvent( event: MessageEvent<{ - type: string; + type: keyof StateEvents; state_key?: string; content?: IContent; }>, diff --git a/linked-dependencies/matrix-react-sdk/src/SecurityManager.ts b/linked-dependencies/matrix-react-sdk/src/SecurityManager.ts index ff8946614f..6d43d83f61 100644 --- a/linked-dependencies/matrix-react-sdk/src/SecurityManager.ts +++ b/linked-dependencies/matrix-react-sdk/src/SecurityManager.ts @@ -14,8 +14,13 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { DeviceVerificationStatus, ICryptoCallbacks, MatrixClient, encodeBase64 } from "matrix-js-sdk/src/matrix"; -import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api"; +import { + DeviceVerificationStatus, + ICryptoCallbacks, + MatrixClient, + encodeBase64, + SecretStorage, +} from "matrix-js-sdk/src/matrix"; import { deriveKey } from "matrix-js-sdk/src/crypto/key_passphrase"; import { decodeRecoveryKey } from "matrix-js-sdk/src/crypto/recoverykey"; import { logger } from "matrix-js-sdk/src/logger"; @@ -28,7 +33,7 @@ import { isSecureBackupRequired } from "./utils/WellKnownUtils"; import AccessSecretStorageDialog, { KeyParams } from "./components/views/dialogs/security/AccessSecretStorageDialog"; import RestoreKeyBackupDialog from "./components/views/dialogs/security/RestoreKeyBackupDialog"; import SettingsStore from "./settings/SettingsStore"; -import SecurityCustomisations from "./customisations/Security"; +import { ModuleRunner } from "./modules/ModuleRunner"; import QuestionDialog from "./components/views/dialogs/QuestionDialog"; import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDialog"; @@ -38,14 +43,14 @@ import InteractiveAuthDialog from "./components/views/dialogs/InteractiveAuthDia // single secret storage operation, as it will clear the cached keys once the // operation ends. let secretStorageKeys: Record = {}; -let secretStorageKeyInfo: Record = {}; +let secretStorageKeyInfo: Record = {}; let secretStorageBeingAccessed = false; let nonInteractive = false; let dehydrationCache: { key?: Uint8Array; - keyInfo?: ISecretStorageKeyInfo; + keyInfo?: SecretStorage.SecretStorageKeyDescription; } = {}; function isCachingAllowed(): boolean { @@ -80,7 +85,9 @@ async function confirmToDismiss(): Promise { return !sure; } -function makeInputToKey(keyInfo: ISecretStorageKeyInfo): (keyParams: KeyParams) => Promise { +function makeInputToKey( + keyInfo: SecretStorage.SecretStorageKeyDescription, +): (keyParams: KeyParams) => Promise { return async ({ passphrase, recoveryKey }): Promise => { if (passphrase) { return deriveKey(passphrase, keyInfo.passphrase.salt, keyInfo.passphrase.iterations); @@ -94,11 +101,11 @@ function makeInputToKey(keyInfo: ISecretStorageKeyInfo): (keyParams: KeyParams) async function getSecretStorageKey({ keys: keyInfos, }: { - keys: Record; + keys: Record; }): Promise<[string, Uint8Array]> { const cli = MatrixClientPeg.safeGet(); let keyId = await cli.getDefaultSecretStorageKeyId(); - let keyInfo!: ISecretStorageKeyInfo; + let keyInfo!: SecretStorage.SecretStorageKeyDescription; if (keyId) { // use the default SSSS key if set keyInfo = keyInfos[keyId]; @@ -130,9 +137,9 @@ async function getSecretStorageKey({ } } - const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); + const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup.getSecretStorageKey(); if (keyFromCustomisations) { - logger.log("Using key from security customisations (secret storage)"); + logger.log("CryptoSetupExtension: Using key from extension (secret storage)"); cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations); return [keyId, keyFromCustomisations]; } @@ -177,12 +184,12 @@ async function getSecretStorageKey({ } export async function getDehydrationKey( - keyInfo: ISecretStorageKeyInfo, + keyInfo: SecretStorage.SecretStorageKeyDescription, checkFunc: (data: Uint8Array) => void, ): Promise { - const keyFromCustomisations = SecurityCustomisations.getSecretStorageKey?.(); + const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup.getSecretStorageKey(); if (keyFromCustomisations) { - logger.log("Using key from security customisations (dehydration)"); + logger.log("CryptoSetupExtension: Using key from extension (dehydration)"); return keyFromCustomisations; } @@ -226,7 +233,11 @@ export async function getDehydrationKey( return key; } -function cacheSecretStorageKey(keyId: string, keyInfo: ISecretStorageKeyInfo, key: Uint8Array): void { +function cacheSecretStorageKey( + keyId: string, + keyInfo: SecretStorage.SecretStorageKeyDescription, + key: Uint8Array, +): void { if (isCachingAllowed()) { secretStorageKeys[keyId] = key; secretStorageKeyInfo[keyId] = keyInfo; @@ -419,7 +430,7 @@ async function doAccessSecretStorage(func: () => Promise, forceReset: bool // inner operation completes. return await func(); } catch (e) { - SecurityCustomisations.catchAccessSecretStorageError?.(e); + ModuleRunner.instance.extensions.cryptoSetup.catchAccessSecretStorageError(e as Error); logger.error(e); // Re-throw so that higher level logic can abort as needed throw e; diff --git a/linked-dependencies/matrix-react-sdk/src/SlashCommands.tsx b/linked-dependencies/matrix-react-sdk/src/SlashCommands.tsx index f309ca4bc5..682145bd38 100644 --- a/linked-dependencies/matrix-react-sdk/src/SlashCommands.tsx +++ b/linked-dependencies/matrix-react-sdk/src/SlashCommands.tsx @@ -18,8 +18,9 @@ limitations under the License. */ import * as React from "react"; -import { User, IContent, Direction, ContentHelpers, MRoomTopicEventContent } from "matrix-js-sdk/src/matrix"; +import { ContentHelpers, Direction, EventType, IContent, MRoomTopicEventContent, User } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; +import { KnownMembership, RoomMemberEventContent } from "matrix-js-sdk/src/types"; import dis from "./dispatcher/dispatcher"; import { _t, _td, UserFriendlyError } from "./languageHandler"; @@ -239,12 +240,12 @@ export const Commands = [ isEnabled: (cli) => !isCurrentLocalRoom(cli), runFn: function (cli, roomId, threadId, args) { if (args) { - const ev = cli.getRoom(roomId)?.currentState.getStateEvents("m.room.member", cli.getSafeUserId()); - const content = { - ...(ev ? ev.getContent() : { membership: "join" }), + const ev = cli.getRoom(roomId)?.currentState.getStateEvents(EventType.RoomMember, cli.getSafeUserId()); + const content: RoomMemberEventContent = { + ...(ev ? ev.getContent() : { membership: KnownMembership.Join }), displayname: args, }; - return success(cli.sendStateEvent(roomId, "m.room.member", content, cli.getSafeUserId())); + return success(cli.sendStateEvent(roomId, EventType.RoomMember, content, cli.getSafeUserId())); } return reject(this.getUsage()); }, @@ -265,7 +266,7 @@ export const Commands = [ return success( promise.then((url) => { if (!url) return; - return cli.sendStateEvent(roomId, "m.room.avatar", { url }, ""); + return cli.sendStateEvent(roomId, EventType.RoomAvatar, { url }, ""); }), ); }, @@ -289,12 +290,12 @@ export const Commands = [ return success( promise.then((url) => { if (!url) return; - const ev = room?.currentState.getStateEvents("m.room.member", userId); - const content = { - ...(ev ? ev.getContent() : { membership: "join" }), + const ev = room?.currentState.getStateEvents(EventType.RoomMember, userId); + const content: RoomMemberEventContent = { + ...(ev ? ev.getContent() : { membership: KnownMembership.Join }), avatar_url: url, }; - return cli.sendStateEvent(roomId, "m.room.member", content, userId); + return cli.sendStateEvent(roomId, EventType.RoomMember, content, userId); }), ); }, diff --git a/linked-dependencies/matrix-react-sdk/src/TextForEvent.tsx b/linked-dependencies/matrix-react-sdk/src/TextForEvent.tsx index 3389e7d838..96eb38f01b 100644 --- a/linked-dependencies/matrix-react-sdk/src/TextForEvent.tsx +++ b/linked-dependencies/matrix-react-sdk/src/TextForEvent.tsx @@ -26,6 +26,7 @@ import { M_POLL_START, M_POLL_END, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { removeDirectionOverrideChars } from "matrix-js-sdk/src/utils"; import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent"; @@ -122,7 +123,7 @@ function textForMemberEvent( const reason = content.reason; switch (content.membership) { - case "invite": { + case KnownMembership.Invite: { const threePidContent = content.third_party_invite; if (threePidContent) { if (threePidContent.display_name) { @@ -138,13 +139,13 @@ function textForMemberEvent( return () => _t("timeline|m.room.member|invite", { senderName, targetName }); } } - case "ban": + case KnownMembership.Ban: return () => reason ? _t("timeline|m.room.member|ban_reason", { senderName, targetName, reason }) : _t("timeline|m.room.member|ban", { senderName, targetName }); - case "join": - if (prevContent && prevContent.membership === "join") { + case KnownMembership.Join: + if (prevContent && prevContent.membership === KnownMembership.Join) { const modDisplayname = getModification(prevContent.displayname, content.displayname); const modAvatarUrl = getModification(prevContent.avatar_url, content.avatar_url); @@ -194,9 +195,9 @@ function textForMemberEvent( if (!ev.target) logger.warn("Join message has no target! -- " + ev.getContent().state_key); return () => _t("timeline|m.room.member|join", { targetName }); } - case "leave": + case KnownMembership.Leave: if (ev.getSender() === ev.getStateKey()) { - if (prevContent.membership === "invite") { + if (prevContent.membership === KnownMembership.Invite) { return () => _t("timeline|m.room.member|reject_invite", { targetName }); } else { return () => @@ -204,9 +205,9 @@ function textForMemberEvent( ? _t("timeline|m.room.member|left_reason", { targetName, reason }) : _t("timeline|m.room.member|left", { targetName }); } - } else if (prevContent.membership === "ban") { + } else if (prevContent.membership === KnownMembership.Ban) { return () => _t("timeline|m.room.member|unban", { senderName, targetName }); - } else if (prevContent.membership === "invite") { + } else if (prevContent.membership === KnownMembership.Invite) { return () => reason ? _t("timeline|m.room.member|withdrew_invite_reason", { @@ -215,7 +216,7 @@ function textForMemberEvent( reason, }) : _t("timeline|m.room.member|withdrew_invite", { senderName, targetName }); - } else if (prevContent.membership === "join") { + } else if (prevContent.membership === KnownMembership.Join) { return () => reason ? _t("timeline|m.room.member|kick_reason", { diff --git a/linked-dependencies/matrix-react-sdk/src/VoipUserMapper.ts b/linked-dependencies/matrix-react-sdk/src/VoipUserMapper.ts index d03a38b333..09e7cbd1af 100644 --- a/linked-dependencies/matrix-react-sdk/src/VoipUserMapper.ts +++ b/linked-dependencies/matrix-react-sdk/src/VoipUserMapper.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { Room, EventType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { ensureVirtualRoomExists } from "./createRoom"; @@ -95,7 +96,7 @@ export default class VoipUserMapper { if (!virtualRoomEvent || !virtualRoomEvent.getContent()) return null; const nativeRoomID = virtualRoomEvent.getContent()["native_room"]; const nativeRoom = cli.getRoom(nativeRoomID); - if (!nativeRoom || nativeRoom.getMyMembership() !== "join") return null; + if (!nativeRoom || nativeRoom.getMyMembership() !== KnownMembership.Join) return null; return nativeRoomID; } diff --git a/linked-dependencies/matrix-react-sdk/src/accessibility/RovingTabIndex.tsx b/linked-dependencies/matrix-react-sdk/src/accessibility/RovingTabIndex.tsx index 5f3901a391..9a2a855242 100644 --- a/linked-dependencies/matrix-react-sdk/src/accessibility/RovingTabIndex.tsx +++ b/linked-dependencies/matrix-react-sdk/src/accessibility/RovingTabIndex.tsx @@ -175,6 +175,8 @@ interface IProps { handleHomeEnd?: boolean; handleUpDown?: boolean; handleLeftRight?: boolean; + handleInputFields?: boolean; + scrollIntoView?: boolean | ScrollIntoViewOptions; children(renderProps: { onKeyDownHandler(ev: React.KeyboardEvent): void; onDragEndHandler(): void }): ReactNode; onKeyDown?(ev: React.KeyboardEvent, state: IState, dispatch: Dispatch): void; } @@ -212,6 +214,8 @@ export const RovingTabIndexProvider: React.FC = ({ handleUpDown, handleLeftRight, handleLoop, + handleInputFields, + scrollIntoView, onKeyDown, }) => { const [state, dispatch] = useReducer>(reducer, { @@ -234,7 +238,7 @@ export const RovingTabIndexProvider: React.FC = ({ let focusRef: RefObject | undefined; // Don't interfere with input default keydown behaviour // but allow people to move focus from it with Tab. - if (checkInputableElement(ev.target as HTMLElement)) { + if (!handleInputFields && checkInputableElement(ev.target as HTMLElement)) { switch (action) { case KeyBindingAction.Tab: handled = true; @@ -311,9 +315,21 @@ export const RovingTabIndexProvider: React.FC = ({ ref: focusRef, }, }); + if (scrollIntoView) { + focusRef.current?.scrollIntoView(scrollIntoView); + } } }, - [context, onKeyDown, handleHomeEnd, handleUpDown, handleLeftRight, handleLoop], + [ + context, + onKeyDown, + handleHomeEnd, + handleUpDown, + handleLeftRight, + handleLoop, + handleInputFields, + scrollIntoView, + ], ); const onDragEndHandler = useCallback(() => { diff --git a/linked-dependencies/matrix-react-sdk/src/accessibility/Toolbar.tsx b/linked-dependencies/matrix-react-sdk/src/accessibility/Toolbar.tsx index a606f9aae8..c5a81aeda3 100644 --- a/linked-dependencies/matrix-react-sdk/src/accessibility/Toolbar.tsx +++ b/linked-dependencies/matrix-react-sdk/src/accessibility/Toolbar.tsx @@ -53,8 +53,9 @@ const Toolbar = forwardRef(({ children, ...props }, ref) } }; + // We handle both up/down and left/right as is allowed in the above WAI ARIA best practices return ( - + {({ onKeyDownHandler }) => (
{children} diff --git a/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx b/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx index ce002fd8f9..7d9dd7d55f 100644 --- a/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx @@ -19,10 +19,9 @@ import React, { createRef } from "react"; import FileSaver from "file-saver"; import { logger } from "matrix-js-sdk/src/logger"; import { AuthDict, CrossSigningKeys, MatrixError, UIAFlow, UIAResponse } from "matrix-js-sdk/src/matrix"; -import { IRecoveryKey } from "matrix-js-sdk/src/crypto/api"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; import classNames from "classnames"; -import { BackupTrustInfo, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; +import { BackupTrustInfo, GeneratedSecretStorageKey, KeyBackupInfo } from "matrix-js-sdk/src/crypto-api"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import { _t, _td } from "../../../../languageHandler"; @@ -41,7 +40,7 @@ import { isSecureBackupRequired, SecureBackupSetupMethod, } from "../../../../utils/WellKnownUtils"; -import SecurityCustomisations from "../../../../customisations/Security"; +import { ModuleRunner } from "../../../../modules/ModuleRunner"; import Field from "../../../../components/views/elements/Field"; import BaseDialog from "../../../../components/views/dialogs/BaseDialog"; import Spinner from "../../../../components/views/elements/Spinner"; @@ -49,6 +48,7 @@ import InteractiveAuthDialog from "../../../../components/views/dialogs/Interact import { IValidationResult } from "../../../../components/views/elements/Validation"; import { Icon as CheckmarkIcon } from "../../../../../res/img/element-icons/check.svg"; import PassphraseConfirmField from "../../../../components/views/auth/PassphraseConfirmField"; +import { initialiseDehydration } from "../../../../utils/device/dehydration"; // I made a mistake while converting this and it has to be fixed! enum Phase { @@ -122,7 +122,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent(); private passphraseField = createRef(); @@ -181,9 +181,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent const newMethodDetected =

{_t("encryption|new_recovery_method_detected|description_1")}

; - const hackWarning =

{_t("encryption|new_recovery_method_detected|warning")}

; + const hackWarning = ( + {_t("encryption|new_recovery_method_detected|warning")} + ); let content: JSX.Element | undefined; if (MatrixClientPeg.safeGet().getKeyBackupEnabled()) { diff --git a/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.tsx b/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.tsx index 4dafcfa518..c864eb1abb 100644 --- a/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/async-components/views/dialogs/security/RecoveryMethodRemovedDialog.tsx @@ -55,7 +55,7 @@ export default class RecoveryMethodRemovedDialog extends React.PureComponent

{_t("encryption|recovery_method_removed|description_1")}

{_t("encryption|recovery_method_removed|description_2")}

-

{_t("encryption|recovery_method_removed|warning")}

+ {_t("encryption|recovery_method_removed|warning")} userId !== currentUserId); - this.users = this.users.concat(this.room.getMembersWithMembership("invite")); + this.users = this.users.concat(this.room.getMembersWithMembership(KnownMembership.Invite)); this.users = sortBy(this.users, (member) => 1e20 - lastSpoken[member.userId] || 1e20); diff --git a/linked-dependencies/matrix-react-sdk/src/call-types.ts b/linked-dependencies/matrix-react-sdk/src/call-types.ts index d042faaaf3..40cd006dcc 100644 --- a/linked-dependencies/matrix-react-sdk/src/call-types.ts +++ b/linked-dependencies/matrix-react-sdk/src/call-types.ts @@ -17,3 +17,12 @@ limitations under the License. // Event type for room account data and room creation content used to mark rooms as virtual rooms // (and store the ID of their native room) export const VIRTUAL_ROOM_EVENT_TYPE = "im.vector.is_virtual_room"; + +export const JitsiCallMemberEventType = "io.element.video.member"; + +export interface JitsiCallMemberContent { + // Connected device IDs + devices: string[]; + // Time at which this state event should be considered stale + expires_ts: number; +} diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/InteractiveAuth.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/InteractiveAuth.tsx index 2547af77a1..1ca2b6e5ce 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/InteractiveAuth.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/InteractiveAuth.tsx @@ -18,7 +18,7 @@ import React, { createRef } from "react"; import { AuthType, IAuthData, - IAuthDict, + AuthDict, IInputs, InteractiveAuth, IStageStatus, @@ -64,7 +64,7 @@ export interface InteractiveAuthProps { continueText?: string; continueKind?: ContinueKind; // callback - makeRequest(auth: IAuthDict | null): Promise; + makeRequest(auth: AuthDict | null): Promise; // callback called when the auth process has finished, // successfully or unsuccessfully. // @param {boolean} status True if the operation requiring @@ -213,7 +213,7 @@ export default class InteractiveAuthComponent extends React.Component => { + private requestCallback = (auth: AuthDict | null, background: boolean): Promise => { // This wrapper just exists because the js-sdk passes a second // 'busy' param for backwards compat. This throws the tests off // so discard it here. @@ -246,7 +246,7 @@ export default class InteractiveAuthComponent extends React.Component { + private submitAuthDict = (authData: AuthDict): void => { this.authLogic.submitAuthDict(authData); }; diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/LoggedInView.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/LoggedInView.tsx index c0707fba26..4481e4f603 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/LoggedInView.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/LoggedInView.tsx @@ -38,7 +38,6 @@ import SettingsStore from "../../settings/SettingsStore"; import { SettingLevel } from "../../settings/SettingLevel"; import ResizeHandle from "../views/elements/ResizeHandle"; import { CollapseDistributor, Resizer } from "../../resizer"; -import MatrixClientContext from "../../contexts/MatrixClientContext"; import ResizeNotifier from "../../utils/ResizeNotifier"; import PlatformPeg from "../../PlatformPeg"; import { DefaultTagID } from "../../stores/room-list/models"; @@ -75,6 +74,7 @@ import { UserOnboardingPage } from "../views/user-onboarding/UserOnboardingPage" import { PipContainer } from "./PipContainer"; import { monitorSyncedPushRules } from "../../utils/pushRules/monitorSyncedPushRules"; import { ConfigOptions } from "../../SdkConfig"; +import { MatrixClientContextProvider } from "./MatrixClientContextProvider"; // We need to fetch each pinned message individually (if we don't already have it) // so each pinned message may trigger a request. Limit the number per room for sanity. @@ -672,7 +672,7 @@ class LoggedInView extends React.Component { }); return ( - +
{ {audioFeedArraysForCalls} - + ); } } diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/MatrixChat.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/MatrixChat.tsx index cb586630ea..9cb455d236 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/MatrixChat.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/MatrixChat.tsx @@ -26,8 +26,8 @@ import { RoomType, SyncStateData, SyncState, + TimelineEvents, } from "matrix-js-sdk/src/matrix"; -import { InvalidStoreError } from "matrix-js-sdk/src/errors"; import { defer, IDeferred, QueryDict } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; import { throttle } from "lodash"; @@ -88,7 +88,7 @@ import { showToast as showMobileGuideToast } from "../../toasts/MobileGuideToast import { shouldUseLoginForWelcome } from "../../utils/pages"; import RoomListStore from "../../stores/room-list/RoomListStore"; import { RoomUpdateCause } from "../../stores/room-list/models"; -import SecurityCustomisations from "../../customisations/Security"; +import { ModuleRunner } from "../../modules/ModuleRunner"; import Spinner from "../views/elements/Spinner"; import QuestionDialog from "../views/dialogs/QuestionDialog"; import UserSettingsDialog from "../views/dialogs/UserSettingsDialog"; @@ -116,7 +116,7 @@ import { ButtonEvent } from "../views/elements/AccessibleButton"; import { ActionPayload } from "../../dispatcher/payloads"; import { SummarizedNotificationState } from "../../stores/notifications/SummarizedNotificationState"; import Views from "../../Views"; -import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; +import { FocusNextType, ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; import { ViewHomePagePayload } from "../../dispatcher/payloads/ViewHomePagePayload"; import { AfterLeaveRoomPayload } from "../../dispatcher/payloads/AfterLeaveRoomPayload"; import { DoAfterSyncPreparedPayload } from "../../dispatcher/payloads/DoAfterSyncPreparedPayload"; @@ -230,7 +230,8 @@ export default class MatrixChat extends React.PureComponent { private screenAfterLogin?: IScreen; private tokenLogin?: boolean; - private focusComposer: boolean; + // What to focus on next component update, if anything + private focusNext: FocusNextType; private subTitleStatus: string; private prevWindowWidth: number; private voiceBroadcastResumer?: VoiceBroadcastResumer; @@ -299,8 +300,6 @@ export default class MatrixChat extends React.PureComponent { this.themeWatcher.start(); this.fontWatcher.start(); - this.focusComposer = false; - // object field used for tracking the status info appended to the title tag. // we don't do it as react state as i'm scared about triggering needless react refreshes. this.subTitleStatus = ""; @@ -444,7 +443,9 @@ export default class MatrixChat extends React.PureComponent { if (crossSigningIsSetUp) { // if the user has previously set up cross-signing, verify this device so we can fetch the // private keys. - if (SecurityCustomisations.SHOW_ENCRYPTION_SETUP_UI === false) { + + const cryptoExtension = ModuleRunner.instance.extensions.cryptoSetup; + if (cryptoExtension.SHOW_ENCRYPTION_SETUP_UI == false) { this.onLoggedIn(); } else { this.setStateForNewView({ view: Views.COMPLETE_SECURITY }); @@ -484,9 +485,11 @@ export default class MatrixChat extends React.PureComponent { PosthogTrackers.instance.trackPageChange(this.state.view, this.state.page_type, durationMs); } } - if (this.focusComposer) { + if (this.focusNext === "composer") { dis.fire(Action.FocusSendMessageComposer); - this.focusComposer = false; + this.focusNext = undefined; + } else if (this.focusNext === "threadsPanel") { + dis.fire(Action.FocusThreadsPanel); } } @@ -986,7 +989,7 @@ export default class MatrixChat extends React.PureComponent { // switch view to the given room private async viewRoom(roomInfo: ViewRoomPayload): Promise { - this.focusComposer = true; + this.focusNext = roomInfo.focusNext ?? "composer"; if (roomInfo.room_alias) { logger.log(`Switching to room alias ${roomInfo.room_alias} at event ${roomInfo.event_id}`); @@ -1177,10 +1180,10 @@ export default class MatrixChat extends React.PureComponent { const memberCount = roomToLeave?.currentState.getJoinedMemberCount(); if (memberCount === 1) { warnings.push( - + {" " /* Whitespace, otherwise the sentences get smashed together */} {_t("leave_room_dialog|last_person_warning")} - , + , ); return warnings; @@ -1191,15 +1194,44 @@ export default class MatrixChat extends React.PureComponent { const rule = joinRules.getContent().join_rule; if (rule !== "public") { warnings.push( - + {" " /* Whitespace, otherwise the sentences get smashed together */} {isSpace ? _t("leave_room_dialog|space_rejoin_warning") : _t("leave_room_dialog|room_rejoin_warning")} - , + , ); } } + + const client = MatrixClientPeg.get(); + if (client && roomToLeave) { + const plEvent = roomToLeave.currentState.getStateEvents(EventType.RoomPowerLevels, ""); + const plContent = plEvent ? plEvent.getContent() : {}; + const userLevels = plContent.users || {}; + const currentUserLevel = userLevels[client.getUserId()!]; + const userLevelValues = Object.values(userLevels); + if (userLevelValues.every((x) => typeof x === "number")) { + const maxUserLevel = Math.max(...(userLevelValues as number[])); + // If the user is the only user with highest power level + if ( + maxUserLevel === currentUserLevel && + userLevelValues.lastIndexOf(maxUserLevel) == userLevelValues.indexOf(maxUserLevel) + ) { + const warning = + maxUserLevel >= 100 + ? _t("leave_room_dialog|room_leave_admin_warning") + : _t("leave_room_dialog|room_leave_mod_warning"); + warnings.push( + + {" " /* Whitespace, otherwise the sentences get smashed together */} + {warning} + , + ); + } + } + } + return warnings; } @@ -1224,6 +1256,7 @@ export default class MatrixChat extends React.PureComponent { ), button: _t("action|leave"), + danger: warnings.length > 0, onFinished: async (shouldLeave) => { if (shouldLeave) { await leaveRoomBehaviour(cli, roomId); @@ -1485,9 +1518,6 @@ export default class MatrixChat extends React.PureComponent { cli.on(ClientEvent.Sync, (state: SyncState, prevState: SyncState | null, data?: SyncStateData) => { if (state === SyncState.Error || state === SyncState.Reconnecting) { - if (data?.error instanceof InvalidStoreError) { - Lifecycle.handleInvalidStoreError(data.error); - } this.setState({ syncError: data?.error ?? null }); } else if (this.state.syncError) { this.setState({ syncError: null }); @@ -1914,7 +1944,7 @@ export default class MatrixChat extends React.PureComponent { const cli = MatrixClientPeg.get(); if (!cli) return; - cli.sendEvent(roomId, event.getType(), event.getContent()).then(() => { + cli.sendEvent(roomId, event.getType() as keyof TimelineEvents, event.getContent()).then(() => { dis.dispatch({ action: "message_sent" }); }); } @@ -2028,14 +2058,10 @@ export default class MatrixChat extends React.PureComponent { /> ); } else if (this.state.view === Views.LOGGED_IN) { - // store errors stop the client syncing and require user intervention, so we'll - // be showing a dialog. Don't show anything else. - const isStoreError = this.state.syncError && this.state.syncError instanceof InvalidStoreError; - // `ready` and `view==LOGGED_IN` may be set before `page_type` (because the // latter is set via the dispatcher). If we don't yet have a `page_type`, // keep showing the spinner for now. - if (this.state.ready && this.state.page_type && !isStoreError) { + if (this.state.ready && this.state.page_type) { /* for now, we stuff the entirety of our props and state into the LoggedInView. * we should go through and figure out what we actually need to pass down, as well * as using something like redux to avoid having a billion bits of state kicking around. @@ -2052,12 +2078,11 @@ export default class MatrixChat extends React.PureComponent { ); } else { // we think we are logged in, but are still waiting for the /sync to complete - // Suppress `InvalidStoreError`s here, since they have their own error dialog. view = ( ); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/MatrixClientContextProvider.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/MatrixClientContextProvider.tsx new file mode 100644 index 0000000000..2b675f8555 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/MatrixClientContextProvider.tsx @@ -0,0 +1,104 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React, { PropsWithChildren, useEffect, useState } from "react"; +import { CryptoEvent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { logger } from "matrix-js-sdk/src/logger"; + +import MatrixClientContext from "../../contexts/MatrixClientContext"; +import { useEventEmitter } from "../../hooks/useEventEmitter"; +import { LocalDeviceVerificationStateContext } from "../../contexts/LocalDeviceVerificationStateContext"; + +/** + * A React hook whose value is whether the local device has been "verified". + * + * Figuring out if we are verified is an async operation, so on the first render this always returns `false`, but + * fires off a background job to update a state variable. It also registers an event listener to update the state + * variable changes. + * + * @param client - Matrix client. + * @returns A boolean which is `true` if the local device has been verified. + * + * @remarks + * + * Some notes on implementation. + * + * It turns out "is this device verified?" isn't a question that is easy to answer as you might think. + * + * Roughly speaking, it normally means "do we believe this device actually belongs to the person it claims to belong + * to", and that data is available via `getDeviceVerificationStatus().isVerified()`. However, the problem is that for + * the local device, that "do we believe..." question is trivially true, and `isVerified()` always returns true. + * + * Instead, when we're talking about the local device, what we really mean is one of: + * * "have we completed a verification dance (either interactive verification with a device with access to the + * cross-signing secrets, or typing in the 4S key)?", or + * * "will other devices consider this one to be verified?" + * + * (The first is generally required but not sufficient for the second to be true.) + * + * The second question basically amounts to "has this device been signed by our cross-signing key". So one option here + * is to use `getDeviceVerificationStatus().isCrossSigningVerified()`. That might work, but it's a bit annoying because + * it needs a `/keys/query` request to complete after the actual verification process completes. + * + * A slightly less rigorous check is just to find out if we have validated our own public cross-signing keys. If we + * have, it's a good indication that we've at least completed a verification dance -- and hopefully, during that dance, + * a cross-signature of our own device was published. And it's also easy to monitor via `UserTrustStatusChanged` events. + * + * Sooo: TL;DR: `getUserVerificationStatus()` is a good proxy for "is the local device verified?". + */ +function useLocalVerificationState(client: MatrixClient): boolean { + const [value, setValue] = useState(false); + + // On the first render, initialise the state variable + useEffect(() => { + const userId = client.getUserId(); + if (!userId) return; + const crypto = client.getCrypto(); + crypto?.getUserVerificationStatus(userId).then( + (verificationStatus) => setValue(verificationStatus.isCrossSigningVerified()), + (error) => logger.error("Error fetching verification status", error), + ); + }, [client]); + + // Update the value whenever our own trust status changes. + useEventEmitter(client, CryptoEvent.UserTrustStatusChanged, (userId, verificationStatus) => { + if (userId === client.getUserId()) { + setValue(verificationStatus.isCrossSigningVerified()); + } + }); + + return value; +} + +interface Props { + /** Matrix client, which is exposed to all child components via {@link MatrixClientContext}. */ + client: MatrixClient; +} + +/** + * A React component which exposes a {@link MatrixClientContext} and a {@link LocalDeviceVerificationStateContext} + * to its children. + */ +export function MatrixClientContextProvider(props: PropsWithChildren): React.JSX.Element { + const verificationState = useLocalVerificationState(props.client); + return ( + + + {props.children} + + + ); +} diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/ReleaseAnnouncement.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/ReleaseAnnouncement.tsx new file mode 100644 index 0000000000..cc74c3b05b --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/ReleaseAnnouncement.tsx @@ -0,0 +1,54 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import React, { ComponentProps, JSX, PropsWithChildren } from "react"; +import { ReleaseAnnouncement as ReleaseAnnouncementCompound } from "@vector-im/compound-web"; + +import { ReleaseAnnouncementStore, Feature } from "../../stores/ReleaseAnnouncementStore"; +import { useIsReleaseAnnouncementOpen } from "../../hooks/useIsReleaseAnnouncementOpen"; + +interface ReleaseAnnouncementProps + extends Omit, "open" | "onClick"> { + feature: Feature; +} + +/** + * Display a release announcement component around the children + * Wrapper gluing the release announcement compound and the ReleaseAnnouncementStore + * @param feature - the feature to announce, should be listed in {@link Feature} + * @param children + * @param props + * @constructor + */ +export function ReleaseAnnouncement({ + feature, + children, + ...props +}: PropsWithChildren): JSX.Element { + const enabled = useIsReleaseAnnouncementOpen(feature); + + return ( + ReleaseAnnouncementStore.instance.nextReleaseAnnouncement()} + {...props} + > + {children} + + ); +} diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/RoomView.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/RoomView.tsx index db4a5e752f..a15ddbf774 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/RoomView.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/RoomView.tsx @@ -38,6 +38,7 @@ import { ISearchResults, THREAD_RELATION_TYPE, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { CallState, MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import { throttle } from "lodash"; @@ -706,6 +707,8 @@ export class RoomView extends React.Component { newState.initialEventPixelOffset = undefined; const thread = initialEvent?.getThread(); + // Handle the use case of a link to a thread message + // ie: #/room/roomId/eventId (eventId of a thread message) if (thread?.rootEvent && !initialEvent?.isThreadRoot) { dis.dispatch({ action: Action.ShowThread, @@ -718,16 +721,6 @@ export class RoomView extends React.Component { newState.initialEventId = initialEventId; newState.isInitialEventHighlighted = this.context.roomViewStore.isInitialEventHighlighted(); newState.initialEventScrollIntoView = this.context.roomViewStore.initialEventScrollIntoView(); - - if (thread?.rootEvent && initialEvent?.isThreadRoot) { - dis.dispatch({ - action: Action.ShowThread, - rootEvent: thread.rootEvent, - initialEvent, - highlighted: this.context.roomViewStore.isInitialEventHighlighted(), - scroll_into_view: this.context.roomViewStore.initialEventScrollIntoView(), - }); - } } } @@ -1267,7 +1260,7 @@ export class RoomView extends React.Component { case Action.FocusAComposer: { dis.dispatch({ ...(payload as FocusComposerPayload), - // re-dispatch to the correct composer + // re-dispatch to the correct composer (the send message will still be on screen even when editing a message) action: this.state.editState ? Action.FocusEditMessageComposer : Action.FocusSendMessageComposer, }); break; @@ -1454,7 +1447,7 @@ export class RoomView extends React.Component { private async loadMembersIfJoined(room: Room): Promise { // lazy load members if enabled if (this.context.client?.hasLazyLoadMembersEnabled()) { - if (room && room.getMyMembership() === "join") { + if (room && room.getMyMembership() === KnownMembership.Join) { try { await room.loadMembersIfNeeded(); if (!this.unmounted) { @@ -1588,7 +1581,8 @@ export class RoomView extends React.Component { if (room && this.context.client) { const me = this.context.client.getSafeUserId(); const canReact = - room.getMyMembership() === "join" && room.currentState.maySendEvent(EventType.Reaction, me); + room.getMyMembership() === KnownMembership.Join && + room.currentState.maySendEvent(EventType.Reaction, me); const canSendMessages = room.maySendMessage(); const canSelfRedact = room.currentState.maySendEvent(EventType.RoomRedaction, me); @@ -1622,10 +1616,10 @@ export class RoomView extends React.Component { private updateDMState(): void { const room = this.state.room; - if (room?.getMyMembership() !== "join") { + if (room?.getMyMembership() != KnownMembership.Join) { return; } - const dmInviter = room.getDMInviter(); + const dmInviter = room?.getDMInviter(); if (dmInviter) { Rooms.setDMRoom(room.client, room.roomId, dmInviter); } @@ -1662,7 +1656,8 @@ export class RoomView extends React.Component { action: Action.JoinRoom, roomId, opts: { inviteSignUrl: signUrl }, - metricsTrigger: this.state.room?.getMyMembership() === "invite" ? "Invite" : "RoomPreview", + metricsTrigger: + this.state.room?.getMyMembership() === KnownMembership.Invite ? "Invite" : "RoomPreview", canAskToJoin: this.state.canAskToJoin, }); } @@ -2183,7 +2178,7 @@ export class RoomView extends React.Component { const myMembership = this.state.room.getMyMembership(); if ( isVideoRoom(this.state.room) && - !(SettingsStore.getValue("feature_video_rooms") && myMembership === "join") + !(SettingsStore.getValue("feature_video_rooms") && myMembership === KnownMembership.Join) ) { return ( @@ -2200,7 +2195,7 @@ export class RoomView extends React.Component { } // SpaceRoomView handles invites itself - if (myMembership === "invite" && !this.state.room.isSpaceRoom()) { + if (myMembership === KnownMembership.Invite && !this.state.room.isSpaceRoom()) { if (this.state.joining || this.state.rejecting) { return ( @@ -2247,16 +2242,19 @@ export class RoomView extends React.Component { } } - if (this.state.canAskToJoin && ["knock", "leave"].includes(myMembership)) { + if ( + this.state.canAskToJoin && + ([KnownMembership.Knock, KnownMembership.Leave] as Array).includes(myMembership) + ) { return (
{ statusBar = ( { ); } else if (showRoomUpgradeBar) { aux = ; - } else if (myMembership !== "join") { + } else if (myMembership !== KnownMembership.Join) { // We do have a room object for this room, but we're not currently in it. // We may have a 3rd party invite to it. let inviterName: string | undefined; @@ -2406,7 +2404,7 @@ export class RoomView extends React.Component { let messageComposer; const showComposer = // joined and not showing search results - myMembership === "join" && !this.state.search; + myMembership === KnownMembership.Join && !this.state.search; if (showComposer) { messageComposer = ( { const myMember = this.state.room!.getMember(this.context.client!.getSafeUserId()); const showForgetButton = - !this.context.client.isGuest() && (["leave", "ban"].includes(myMembership) || myMember?.isKicked()); + !this.context.client.isGuest() && + (([KnownMembership.Leave, KnownMembership.Ban] as Array).includes(myMembership) || + myMember?.isKicked()); return ( @@ -2640,7 +2640,7 @@ export class RoomView extends React.Component { room={this.state.room} searchInfo={this.state.search} oobData={this.props.oobData} - inRoom={myMembership === "join"} + inRoom={myMembership === KnownMembership.Join} onSearchClick={onSearchClick} onInviteClick={onInviteClick} onForgetClick={showForgetButton ? onForgetClick : null} diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceHierarchy.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceHierarchy.tsx index feeacb4581..41c2bd139e 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceHierarchy.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceHierarchy.tsx @@ -41,11 +41,13 @@ import { HistoryVisibility, HierarchyRelation, HierarchyRoom, + JoinRule, } from "matrix-js-sdk/src/matrix"; import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy"; import classNames from "classnames"; import { sortBy, uniqBy } from "lodash"; import { logger } from "matrix-js-sdk/src/logger"; +import { KnownMembership, SpaceChildEventContent } from "matrix-js-sdk/src/types"; import defaultDispatcher from "../../dispatcher/dispatcher"; import { _t } from "../../languageHandler"; @@ -112,7 +114,7 @@ const Tile: React.FC = ({ const cli = useContext(MatrixClientContext); const joinedRoom = useTypedEventEmitterState(cli, ClientEvent.Room, () => { const cliRoom = cli?.getRoom(room.room_id); - return cliRoom?.getMyMembership() === "join" ? cliRoom : undefined; + return cliRoom?.getMyMembership() === KnownMembership.Join ? cliRoom : undefined; }); const joinedRoomName = useTypedEventEmitterState(joinedRoom, RoomEvent.Name, (room) => room?.name); const name = @@ -135,11 +137,12 @@ const Tile: React.FC = ({ setBusy(true); ev.preventDefault(); ev.stopPropagation(); - onJoinRoomClick() - .then(() => awaitRoomDownSync(cli, room.room_id)) - .finally(() => { - setBusy(false); - }); + try { + await onJoinRoomClick(); + await awaitRoomDownSync(cli, room.room_id); + } finally { + setBusy(false); + } }; let button: ReactElement; @@ -156,7 +159,9 @@ const Tile: React.FC = ({ ); - } else if (joinedRoom) { + } else if (joinedRoom || room.join_rule === JoinRule.Knock) { + // If the room is knockable, show the "View" button even if we are not a member; that + // allows us to reuse the "request to join" UX in RoomView. button = ( ({ @@ -726,7 +732,7 @@ const ManageButtons: React.FC = ({ hierarchy, selected, set const existingContent = hierarchy.getRelation(parentId, childId)?.content; if (!existingContent || existingContent.suggested === suggested) continue; - const content = { + const content: SpaceChildEventContent = { ...existingContent, suggested: !selectionAllSuggested, }; @@ -828,7 +834,7 @@ const SpaceHierarchy: React.FC = ({ space, initialText = "", showRoom, a content = ; } else { const hasPermissions = - space?.getMyMembership() === "join" && + space?.getMyMembership() === KnownMembership.Join && space.currentState.maySendStateEvent(EventType.SpaceChild, cli.getSafeUserId()); const root = hierarchy.roomMap.get(space.roomId); @@ -846,7 +852,7 @@ const SpaceHierarchy: React.FC = ({ space, initialText = "", showRoom, a onViewRoomClick={(roomId, roomType) => showRoom(cli, hierarchy, roomId, roomType)} onJoinRoomClick={async (roomId, parents) => { for (const parent of parents) { - if (cli.getRoom(parent)?.getMyMembership() !== "join") { + if (cli.getRoom(parent)?.getMyMembership() !== KnownMembership.Join) { await joinRoom(cli, hierarchy, parent); } } diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceRoomView.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceRoomView.tsx index dc79a25489..edc857edaf 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceRoomView.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/SpaceRoomView.tsx @@ -15,6 +15,7 @@ limitations under the License. */ import { EventType, RoomType, JoinRule, Preset, Room, RoomEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import React, { useCallback, useContext, useRef, useState } from "react"; @@ -237,7 +238,7 @@ const SpaceLanding: React.FC<{ space: Room }> = ({ space }) => { } const hasAddRoomPermissions = - myMembership === "join" && space.currentState.maySendStateEvent(EventType.SpaceChild, userId); + myMembership === KnownMembership.Join && space.currentState.maySendStateEvent(EventType.SpaceChild, userId); let addRoomButton; if (hasAddRoomPermissions) { @@ -678,7 +679,7 @@ export default class SpaceRoomView extends React.PureComponent { private renderBody(): JSX.Element { switch (this.state.phase) { case Phase.Landing: - if (this.state.myMembership === "join") { + if (this.state.myMembership === KnownMembership.Join) { return ; } else { return ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/ThreadPanel.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/ThreadPanel.tsx index d43b4e25d1..d1e8360174 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/ThreadPanel.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/ThreadPanel.tsx @@ -17,14 +17,17 @@ limitations under the License. import { Optional } from "matrix-events-sdk"; import React, { useContext, useEffect, useRef, useState } from "react"; import { EventTimelineSet, Room, Thread } from "matrix-js-sdk/src/matrix"; +import { IconButton, Tooltip } from "@vector-im/compound-web"; +import { logger } from "matrix-js-sdk/src/logger"; +import { Icon as MarkAllThreadsReadIcon } from "../../../res/img/element-icons/check-all.svg"; import BaseCard from "../views/right_panel/BaseCard"; import ResizeNotifier from "../../utils/ResizeNotifier"; -import MatrixClientContext from "../../contexts/MatrixClientContext"; +import MatrixClientContext, { useMatrixClientContext } from "../../contexts/MatrixClientContext"; import { _t } from "../../languageHandler"; import { ContextMenuButton } from "../../accessibility/context_menu/ContextMenuButton"; import ContextMenu, { ChevronFace, MenuItemRadio, useContextMenu } from "./ContextMenu"; -import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext"; +import RoomContext, { TimelineRenderingType, useRoomContext } from "../../contexts/RoomContext"; import TimelinePanel from "./TimelinePanel"; import { Layout } from "../../settings/enums/Layout"; import { RoomPermalinkCreator } from "../../utils/permalinks/Permalinks"; @@ -33,6 +36,10 @@ import PosthogTrackers from "../../PosthogTrackers"; import { ButtonEvent } from "../views/elements/AccessibleButton"; import Spinner from "../views/elements/Spinner"; import Heading from "../views/typography/Heading"; +import { clearRoomNotification } from "../../utils/notifications"; +import { useDispatcher } from "../../hooks/useDispatcher"; +import dis from "../../dispatcher/dispatcher"; +import { Action } from "../../dispatcher/actions"; interface IProps { roomId: string; @@ -71,6 +78,8 @@ export const ThreadPanelHeader: React.FC<{ setFilterOption: (filterOption: ThreadFilterType) => void; empty: boolean; }> = ({ filterOption, setFilterOption, empty }) => { + const mxClient = useMatrixClientContext(); + const roomContext = useRoomContext(); const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); const options: readonly ThreadPanelHeaderOption[] = [ { @@ -109,6 +118,26 @@ export const ThreadPanelHeader: React.FC<{ {contextMenuOptions} ) : null; + + const onMarkAllThreadsReadClick = React.useCallback( + (e) => { + PosthogTrackers.trackInteraction("WebThreadsMarkAllReadButton", e); + if (!roomContext.room) { + logger.error("No room in context to mark all threads read"); + return; + } + // This actually clears all room notifications by sending an unthreaded read receipt. + // We'd have to loop over all unread threads (pagninating back to find any we don't + // know about yet) and send threaded receipts for all of them... or implement a + // specific API for it. In practice, the user will have to be viewing the room to + // see this button, so will have marked the room itself read anyway. + clearRoomNotification(roomContext.room, mxClient).catch((e) => { + logger.error("Failed to mark all threads read", e); + }); + }, + [roomContext.room, mxClient], + ); + return (
@@ -116,6 +145,16 @@ export const ThreadPanelHeader: React.FC<{ {!empty && ( <> + + + + + +
= ({ roomId, onClose, permalinkCreator }) => const roomContext = useContext(RoomContext); const timelinePanel = useRef(null); const card = useRef(null); + const closeButonRef = useRef(null); const [filterOption, setFilterOption] = useState(ThreadFilterType.All); const [room, setRoom] = useState(null); @@ -219,6 +259,14 @@ const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => } }, [timelineSet, timelinePanel]); + useDispatcher(dis, (payload) => { + // This actually foucses the close button on the threads panel, as its the only interactive element, + // but at least it puts the user in the right area of the app. + if (payload.action === Action.FocusThreadsPanel) { + closeButonRef.current?.focus(); + } + }); + return ( = ({ roomId, onClose, permalinkCreator }) => onClose={onClose} withoutScrollContainer={true} ref={card} + closeButtonRef={closeButonRef} > {card.current && } {timelineSet ? ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/TimelinePanel.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/TimelinePanel.tsx index 7d1ce90762..ba3c4d203b 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/TimelinePanel.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/TimelinePanel.tsx @@ -39,6 +39,7 @@ import { ThreadEvent, ReceiptType, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership, Membership } from "matrix-js-sdk/src/types"; import { debounce, findLastIndex, throttle } from "lodash"; import { logger } from "matrix-js-sdk/src/logger"; @@ -1045,7 +1046,7 @@ class TimelinePanel extends React.Component { } if ( - !(await client.doesServerSupportUnstableFeature("org.matrix.msc2285.stable")) || + !(await client.doesServerSupportUnstableFeature("org.matrix.msc2285.stable")) && !(await client.isVersionSupported("v1.4")) ) { logger.warn( @@ -1824,7 +1825,7 @@ class TimelinePanel extends React.Component { // that the event belongs to, and traversing the timeline looking for // that event, while keeping track of the user's membership let i = events.length - 1; - let userMembership = "leave"; + let userMembership: Membership = KnownMembership.Leave; for (; i >= 0; i--) { const timeline = this.props.timelineSet.getTimelineForEvent(events[i].getId()!); if (!timeline) { @@ -1837,14 +1838,15 @@ class TimelinePanel extends React.Component { continue; } - userMembership = timeline.getState(EventTimeline.FORWARDS)?.getMember(userId)?.membership ?? "leave"; + userMembership = + timeline.getState(EventTimeline.FORWARDS)?.getMember(userId)?.membership ?? KnownMembership.Leave; const timelineEvents = timeline.getEvents(); for (let j = timelineEvents.length - 1; j >= 0; j--) { const event = timelineEvents[j]; if (event.getId() === events[i].getId()) { break; } else if (event.getStateKey() === userId && event.getType() === EventType.RoomMember) { - userMembership = event.getPrevContent().membership || "leave"; + userMembership = event.getPrevContent().membership || KnownMembership.Leave; } } break; @@ -1855,8 +1857,11 @@ class TimelinePanel extends React.Component { for (; i >= 0; i--) { const event = events[i]; if (event.getStateKey() === userId && event.getType() === EventType.RoomMember) { - userMembership = event.getPrevContent().membership || "leave"; - } else if (userMembership === "leave" && (event.isDecryptionFailure() || event.isBeingDecrypted())) { + userMembership = event.getPrevContent().membership || KnownMembership.Leave; + } else if ( + userMembership === KnownMembership.Leave && + (event.isDecryptionFailure() || event.isBeingDecrypted()) + ) { // reached an undecryptable message when the user wasn't in the room -- don't try to load any more // Note: for now, we assume that events that are being decrypted are // not decryptable - we will be called once more when it is decrypted. diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/auth/Registration.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/auth/Registration.tsx index 2bb38d6ef3..4c3ddb2f00 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/auth/Registration.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/auth/Registration.tsx @@ -18,7 +18,7 @@ import { AuthType, createClient, IAuthData, - IAuthDict, + AuthDict, IInputs, MatrixError, IRegisterRequestParams, @@ -499,7 +499,7 @@ export default class Registration extends React.Component { }); }; - private makeRegisterRequest = (auth: IAuthDict | null): Promise => { + private makeRegisterRequest = (auth: AuthDict | null): Promise => { if (!this.state.matrixClient) throw new Error("Matrix client has not yet been loaded"); const registerParams: IRegisterRequestParams = { diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/auth/SetupEncryptionBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/auth/SetupEncryptionBody.tsx index f3dcbb081d..d9cbfa3022 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/auth/SetupEncryptionBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/auth/SetupEncryptionBody.tsx @@ -15,10 +15,10 @@ limitations under the License. */ import React from "react"; -import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api"; import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; import { VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; +import { SecretStorageKeyDescription } from "matrix-js-sdk/src/secret-storage"; import { _t } from "../../../languageHandler"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; @@ -33,7 +33,7 @@ import { Action } from "matrix-react-sdk/src/dispatcher/actions"; import { UserTab } from "matrix-react-sdk/src/components/views/dialogs/UserTab"; import { OpenToTabPayload } from "matrix-react-sdk/src/dispatcher/payloads/OpenToTabPayload"; -function keyHasPassphrase(keyInfo: ISecretStorageKeyInfo): boolean { +function keyHasPassphrase(keyInfo: SecretStorageKeyDescription): boolean { return Boolean(keyInfo.passphrase && keyInfo.passphrase.salt && keyInfo.passphrase.iterations); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/structures/grouper/CreationGrouper.tsx b/linked-dependencies/matrix-react-sdk/src/components/structures/grouper/CreationGrouper.tsx index 0ceb6f5857..fa91a1bd90 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/structures/grouper/CreationGrouper.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/structures/grouper/CreationGrouper.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { ReactNode } from "react"; import { EventType, M_BEACON_INFO, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { BaseGrouper } from "./BaseGrouper"; import MessagePanel, { WrappedEvent } from "../MessagePanel"; @@ -48,7 +49,8 @@ export class CreationGrouper extends BaseGrouper { const eventType = event.getType(); if ( eventType === EventType.RoomMember && - (event.getStateKey() !== createEvent.getSender() || event.getContent()["membership"] !== "join") + (event.getStateKey() !== createEvent.getSender() || + event.getContent()["membership"] !== KnownMembership.Join) ) { return false; } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/auth/InteractiveAuthEntryComponents.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/auth/InteractiveAuthEntryComponents.tsx index 0a7ed19b2a..e8969f12ad 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/auth/InteractiveAuthEntryComponents.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/auth/InteractiveAuthEntryComponents.tsx @@ -16,7 +16,7 @@ limitations under the License. import classNames from "classnames"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; -import { AuthType, IAuthDict, IInputs, IStageStatus } from "matrix-js-sdk/src/interactive-auth"; +import { AuthType, AuthDict, IInputs, IStageStatus } from "matrix-js-sdk/src/interactive-auth"; import { logger } from "matrix-js-sdk/src/logger"; import React, { ChangeEvent, createRef, FormEvent, Fragment } from "react"; @@ -89,7 +89,7 @@ interface IAuthEntryProps { // Is the auth logic currently waiting for something to happen? busy?: boolean; onPhaseChange: (phase: number) => void; - submitAuthDict: (auth: IAuthDict) => void; + submitAuthDict: (auth: AuthDict) => void; requestEmailToken?: () => Promise; fail: (error: Error) => void; clientSecret: string; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/auth/LoginWithQRFlow.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/auth/LoginWithQRFlow.tsx index 526496246a..05c8d95c42 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/auth/LoginWithQRFlow.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/auth/LoginWithQRFlow.tsx @@ -16,16 +16,15 @@ limitations under the License. import React from "react"; import { RendezvousFailureReason } from "matrix-js-sdk/src/rendezvous"; +import { Icon as ChevronLeftIcon } from "@vector-im/compound-design-tokens/icons/chevron-left.svg"; import { _t } from "../../../languageHandler"; import AccessibleButton from "../elements/AccessibleButton"; import QRCode from "../elements/QRCode"; import Spinner from "../elements/Spinner"; -import { Icon as BackButtonIcon } from "../../../../res/img/element-icons/back.svg"; -import { Icon as DevicesIcon } from "../../../../res/img/element-icons/devices.svg"; -import { Icon as WarningBadge } from "../../../../res/img/element-icons/warning-badge.svg"; import { Icon as InfoIcon } from "../../../../res/img/element-icons/i.svg"; import { Click, FailureReason, LoginWithQRFailureReason, Phase } from "./LoginWithQR"; +import SdkConfig from "../../../SdkConfig"; interface IProps { phase: Phase; @@ -70,8 +69,6 @@ export default class LoginWithQRFlow extends React.Component { }; public render(): React.ReactNode { - let title = ""; - let titleIcon: JSX.Element | undefined; let main: JSX.Element | undefined; let buttons: JSX.Element | undefined; let backButton = true; @@ -115,9 +112,7 @@ export default class LoginWithQRFlow extends React.Component { cancellationMessage = _t("auth|qr_code_login|error_request_cancelled"); break; } - title = _t("timeline|m.call.invite|failed_connection"); centreTitle = true; - titleIcon = ; backButton = false; main =

{cancellationMessage}

; buttons = ( @@ -134,8 +129,6 @@ export default class LoginWithQRFlow extends React.Component { ); break; case Phase.Connected: - title = _t("auth|qr_code_login|devices_connected"); - titleIcon = ; backButton = false; main = ( <> @@ -170,7 +163,6 @@ export default class LoginWithQRFlow extends React.Component { ); break; case Phase.ShowingQR: - title = _t("settings|sessions|sign_in_with_qr"); if (this.props.code) { const code = (
@@ -182,17 +174,22 @@ export default class LoginWithQRFlow extends React.Component { ); main = ( <> -

{_t("auth|qr_code_login|scan_code_instruction")}

+

{_t("auth|qr_code_login|scan_code_instruction")}

+ {code}
    -
  1. {_t("auth|qr_code_login|start_at_sign_in_screen")}
  2. +
  3. + {_t("auth|qr_code_login|open_element_other_device", { + brand: SdkConfig.get().brand, + })} +
  4. {_t("auth|qr_code_login|select_qr_code", { - scanQRCode: _t("auth|qr_code_login|scan_qr_code"), + scanQRCode: {_t("auth|qr_code_login|scan_qr_code")}, })}
  5. -
  6. {_t("auth|qr_code_login|review_and_approve")}
  7. +
  8. {_t("auth|qr_code_login|point_the_camera")}
  9. +
  10. {_t("auth|qr_code_login|follow_remaining_instructions")}
- {code} ); } else { @@ -212,7 +209,6 @@ export default class LoginWithQRFlow extends React.Component { buttons = this.cancelButton(); break; case Phase.Verifying: - title = _t("common|success"); centreTitle = true; main = this.simpleSpinner(_t("auth|qr_code_login|completing_setup")); break; @@ -222,19 +218,20 @@ export default class LoginWithQRFlow extends React.Component {
{backButton ? ( - - - +
+ + + +
+ {_t("settings|sessions|title")} / {_t("settings|sessions|sign_in_with_qr")} +
+
) : null} -

- {titleIcon} - {title} -

{main}
{buttons}
diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/avatars/DecoratedRoomAvatar.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/avatars/DecoratedRoomAvatar.tsx index 750e495302..dd83d1e969 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/avatars/DecoratedRoomAvatar.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/avatars/DecoratedRoomAvatar.tsx @@ -39,7 +39,11 @@ interface IProps { room: Room; size: string; displayBadge?: boolean; - forceCount?: boolean; + /** + * If true, show nothing if the notification would only cause a dot to be shown rather than + * a badge. That is: only display badges and not dots. Default: false. + */ + hideIfDot?: boolean; oobData?: IOOBData; viewAvatarOnClick?: boolean; tooltipProps?: { @@ -211,14 +215,14 @@ export default class DecoratedRoomAvatar extends React.PureComponent ); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconMarker.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconMarker.tsx index 217be7351e..6ac29c8a24 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconMarker.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconMarker.tsx @@ -20,7 +20,7 @@ import { Beacon, BeaconEvent, LocationAssetType } from "matrix-js-sdk/src/matrix import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { useEventEmitterState } from "../../../hooks/useEventEmitter"; -import SmartMarker from "../location/SmartMarker"; +import { SmartMarker } from "../location"; interface Props { map: maplibregl.Map; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconViewDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconViewDialog.tsx index a5d79a472f..227ba221b7 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconViewDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/beacon/BeaconViewDialog.tsx @@ -36,7 +36,7 @@ import MapFallback from "../location/MapFallback"; import { MapError } from "../location/MapError"; import { LocationShareError } from "../../../utils/location"; -interface IProps { +export interface IProps { roomId: Room["roomId"]; matrixClient: MatrixClient; // open the map centered on this beacon's location diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/beacon/index.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/beacon/index.tsx new file mode 100644 index 0000000000..77119edbdd --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/components/views/beacon/index.tsx @@ -0,0 +1,31 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Exports beacon components which touch maplibre-gs wrapped in React Suspense to enable code splitting + +import React, { ComponentProps, lazy, Suspense } from "react"; + +import Spinner from "../elements/Spinner"; + +const BeaconViewDialogComponent = lazy(() => import("./BeaconViewDialog")); + +export function BeaconViewDialog(props: ComponentProps): JSX.Element { + return ( + }> + + + ); +} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/context_menus/RoomContextMenu.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/context_menus/RoomContextMenu.tsx index 7527ef4fee..3c77f32cb3 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/context_menus/RoomContextMenu.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/context_menus/RoomContextMenu.tsx @@ -15,7 +15,8 @@ limitations under the License. */ import React, { useContext } from "react"; -import { Room } from "matrix-js-sdk/src/matrix"; +import { Room, RoomMemberEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { IProps as IContextMenuProps } from "../../structures/ContextMenu"; import IconizedContextMenu, { @@ -116,9 +117,9 @@ const RoomContextMenu: React.FC = ({ room, onFinished, ...props }) => { const elementCallVideoRoomsEnabled = useFeatureEnabled("feature_element_call_video_rooms"); const isVideoRoom = videoRoomsEnabled && (room.isElementVideoRoom() || (elementCallVideoRoomsEnabled && room.isCallRoom())); - + const canInvite = useEventEmitterState(cli, RoomMemberEvent.PowerLevel, () => room.canInvite(cli.getUserId()!)); let inviteOption: JSX.Element | undefined; - if (room.canInvite(cli.getUserId()!) && !isDm && shouldShowComponent(UIComponent.InviteUsers)) { + if (canInvite && !isDm && shouldShowComponent(UIComponent.InviteUsers)) { const onInviteClick = (ev: ButtonEvent): void => { ev.preventDefault(); ev.stopPropagation(); @@ -144,7 +145,7 @@ const RoomContextMenu: React.FC = ({ room, onFinished, ...props }) => { let favouriteOption: JSX.Element | undefined; let lowPriorityOption: JSX.Element | undefined; let notificationOption: JSX.Element | undefined; - if (room.getMyMembership() === "join") { + if (room.getMyMembership() === KnownMembership.Join) { const isFavorite = roomTags.includes(DefaultTagID.Favourite); favouriteOption = ( void; + /** + * Called when the 'low priority' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ onPostLowPriorityClick?: (event: ButtonEvent) => void; + /** + * Called when the 'invite' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ onPostInviteClick?: (event: ButtonEvent) => void; + /** + * Called when the 'copy link' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ onPostCopyLinkClick?: (event: ButtonEvent) => void; + /** + * Called when the 'settings' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ onPostSettingsClick?: (event: ButtonEvent) => void; + /** + * Called when the 'forget room' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ onPostForgetClick?: (event: ButtonEvent) => void; + /** + * Called when the 'leave' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ onPostLeaveClick?: (event: ButtonEvent) => void; + /** + * Called when the 'mark as read' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ + onPostMarkAsReadClick?: (event: ButtonEvent) => void; + /** + * Called when the 'mark as unread' option is selected, after the menu has processed + * the mouse or keyboard event. + * @param event The event that caused the option to be selected. + */ + onPostMarkAsUnreadClick?: (event: ButtonEvent) => void; } /** @@ -67,6 +114,8 @@ export const RoomGeneralContextMenu: React.FC = ({ onPostSettingsClick, onPostLeaveClick, onPostForgetClick, + onPostMarkAsReadClick, + onPostMarkAsUnreadClick, ...props }) => { const cli = useContext(MatrixClientContext); @@ -213,18 +262,33 @@ export const RoomGeneralContextMenu: React.FC = ({ } const { level } = useUnreadNotifications(room); - const markAsReadOption: JSX.Element | null = - level > NotificationLevel.None ? ( - { - clearRoomNotification(room, cli); - onFinished?.(); - }} - active={false} - label={_t("room|context_menu|mark_read")} - iconClassName="mx_RoomGeneralContextMenu_iconMarkAsRead" - /> - ) : null; + const markAsReadOption: JSX.Element | null = (() => { + if (level > NotificationLevel.None) { + return ( + { + clearRoomNotification(room, cli); + onFinished?.(); + }, onPostMarkAsReadClick)} + label={_t("room|context_menu|mark_read")} + iconClassName="mx_RoomGeneralContextMenu_iconMarkAsRead" + /> + ); + } else if (!roomTags.includes(DefaultTagID.Archived)) { + return ( + { + setMarkedUnreadState(room, cli, true); + onFinished?.(); + }, onPostMarkAsUnreadClick)} + label={_t("room|context_menu|mark_unread")} + iconClassName="mx_RoomGeneralContextMenu_iconMarkAsUnread" + /> + ); + } else { + return null; + } + })(); const developerModeEnabled = useSettingValue("developerMode"); const developerToolsOption = developerModeEnabled ? ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/AddExistingToSpaceDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/AddExistingToSpaceDialog.tsx index 39a00f1034..3567dbecc7 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/AddExistingToSpaceDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/AddExistingToSpaceDialog.tsx @@ -17,6 +17,7 @@ limitations under the License. import React, { ReactElement, ReactNode, useContext, useMemo, useRef, useState } from "react"; import classNames from "classnames"; import { Room, EventType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { sleep } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; @@ -140,7 +141,9 @@ export const AddExistingToSpace: React.FC = ({ const msc3946ProcessDynamicPredecessor = useSettingValue("feature_dynamic_room_predecessors"); const visibleRooms = useMemo( () => - cli?.getVisibleRooms(msc3946ProcessDynamicPredecessor).filter((r) => r.getMyMembership() === "join") ?? [], + cli + ?.getVisibleRooms(msc3946ProcessDynamicPredecessor) + .filter((r) => r.getMyMembership() === KnownMembership.Join) ?? [], [cli, msc3946ProcessDynamicPredecessor], ); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/BaseDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/BaseDialog.tsx index 5e7c023e2d..1b160150f7 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/BaseDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/BaseDialog.tsx @@ -155,9 +155,6 @@ export default class BaseDialog extends React.Component { lockProps["aria-labelledby"] = "mx_BaseDialog_title"; } - const isHeaderWithCancelOnly = - !!cancelButton && !this.props.title && !this.props.headerButton && !this.props.headerImage; - return ( {this.props.screenName && } @@ -172,8 +169,6 @@ export default class BaseDialog extends React.Component {
{!!(this.props.title || headerImage) && ( @@ -188,8 +183,8 @@ export default class BaseDialog extends React.Component { )} {this.props.headerButton} - {cancelButton}
+ {cancelButton} {this.props.children}
diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/EndPollDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/EndPollDialog.tsx index cc68e80191..6d1abc4a33 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/EndPollDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/EndPollDialog.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { MatrixEvent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { MatrixEvent, MatrixClient, TimelineEvents } from "matrix-js-sdk/src/matrix"; import { PollEndEvent } from "matrix-js-sdk/src/extensible_events_v1/PollEndEvent"; import { _t } from "../../../languageHandler"; @@ -51,7 +51,11 @@ export default class EndPollDialog extends React.Component { const endEvent = PollEndEvent.from(this.props.event.getId()!, message).serialize(); - await this.props.matrixClient.sendEvent(this.props.event.getRoomId()!, endEvent.type, endEvent.content); + await this.props.matrixClient.sendEvent( + this.props.event.getRoomId()!, + endEvent.type as keyof TimelineEvents, + endEvent.content as TimelineEvents[keyof TimelineEvents], + ); } catch (e) { console.error("Failed to submit poll response event:", e); Modal.createDialog(ErrorDialog, { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ForwardDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ForwardDialog.tsx index a21acd7b71..d59e23fe4c 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ForwardDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ForwardDialog.tsx @@ -28,7 +28,9 @@ import { LocationAssetType, M_TIMESTAMP, M_BEACON, + TimelineEvents, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import dis from "../../../dispatcher/dispatcher"; @@ -57,6 +59,15 @@ import { isLocationEvent } from "../../../utils/EventUtils"; import { isSelfLocation, locationEventGeoUri } from "../../../utils/location"; import { RoomContextDetails } from "../rooms/RoomContextDetails"; import { filterBoolean } from "../../../utils/arrays"; +import { + IState, + RovingTabIndexContext, + RovingTabIndexProvider, + Type, + useRovingTabIndex, +} from "../../../accessibility/RovingTabIndex"; +import { getKeyBindingsManager } from "../../../KeyBindingsManager"; +import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; const AVATAR_SIZE = 30; @@ -70,10 +81,10 @@ interface IProps { onFinished(): void; } -interface IEntryProps { +interface IEntryProps { room: Room; - type: EventType | string; - content: IContent; + type: K; + content: TimelineEvents[K]; matrixClient: MatrixClient; onFinished(success: boolean): void; } @@ -85,8 +96,9 @@ enum SendState { Failed, } -const Entry: React.FC = ({ room, type, content, matrixClient: cli, onFinished }) => { +const Entry: React.FC> = ({ room, type, content, matrixClient: cli, onFinished }) => { const [sendState, setSendState] = useState(SendState.CanSend); + const [onFocus, isActive, ref] = useRovingTabIndex(); const jumpToRoom = (ev: ButtonEvent): void => { dis.dispatch({ @@ -134,16 +146,30 @@ const Entry: React.FC = ({ room, type, content, matrixClient: cli, icon = ; } + const id = `mx_ForwardDialog_entry_${room.roomId}`; return ( -
+
- - {room.name} + + + {room.name} + = ({ room, type, content, matrixClient: cli, disabled={disabled} title={title} alignment={Alignment.Top} + tabIndex={isActive ? 0 : -1} + id={`${id}_send`} >
{_t("forward|send_label")}
{icon} @@ -241,7 +269,7 @@ const ForwardDialog: React.FC = ({ matrixClient: cli, event, permalinkCr sortRooms( cli .getVisibleRooms(msc3946DynamicRoomPredecessors) - .filter((room) => room.getMyMembership() === "join" && !room.isSpaceRoom()), + .filter((room) => room.getMyMembership() === KnownMembership.Join && !room.isSpaceRoom()), ), [cli, msc3946DynamicRoomPredecessors], ); @@ -270,6 +298,26 @@ const ForwardDialog: React.FC = ({ matrixClient: cli, event, permalinkCr ); } + const onKeyDown = (ev: React.KeyboardEvent, state: IState): void => { + let handled = true; + + const action = getKeyBindingsManager().getAccessibilityAction(ev); + switch (action) { + case KeyBindingAction.Enter: { + state.activeRef?.current?.querySelector(".mx_ForwardList_sendButton")?.click(); + break; + } + + default: + handled = false; + } + + if (handled) { + ev.preventDefault(); + ev.stopPropagation(); + } + }; + return ( = ({ matrixClient: cli, event, permalinkCr />

-
- - - {rooms.length > 0 ? ( -
- - rooms - .slice(start, end) - .map((room) => ( - - )) - } - getChildCount={() => rooms.length} - /> -
- ) : ( - {_t("common|no_results")} - )} -
-
+ + {({ onKeyDownHandler }) => ( +
+ + {(context) => ( + { + setQuery(query); + setImmediate(() => { + const ref = context.state.refs[0]; + if (ref) { + context.dispatch({ + type: Type.SetFocus, + payload: { ref }, + }); + ref.current?.scrollIntoView?.({ + block: "nearest", + }); + } + }); + }} + autoFocus={true} + onKeyDown={onKeyDownHandler} + aria-activedescendant={context.state.activeRef?.current?.id} + aria-owns="mx_ForwardDialog_resultsList" + /> + )} + + + {rooms.length > 0 ? ( +
+ + rooms + .slice(start, end) + .map((room) => ( + + )) + } + getChildCount={() => rooms.length} + /> +
+ ) : ( + {_t("common|no_results")} + )} +
+
+ )} +
); }; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/IncomingSasDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/IncomingSasDialog.tsx index 9504370604..14db23e272 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/IncomingSasDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/IncomingSasDialog.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React, { ReactNode } from "react"; -import { GeneratedSas, ShowSasCallbacks, Verifier, VerifierEvent } from "matrix-js-sdk/src/crypto-api/verification"; +import { GeneratedSas, ShowSasCallbacks, Verifier, VerifierEvent } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InteractiveAuthDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InteractiveAuthDialog.tsx index f16da83cc0..c6e3dd2037 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InteractiveAuthDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InteractiveAuthDialog.tsx @@ -29,6 +29,7 @@ import InteractiveAuth, { } from "../../structures/InteractiveAuth"; import { ContinueKind, SSOAuthEntry } from "../auth/InteractiveAuthEntryComponents"; import BaseDialog from "./BaseDialog"; +import { Linkify } from "../../../Linkify"; type DialogAesthetics = Partial<{ [x in AuthType]: { @@ -168,7 +169,9 @@ export default class InteractiveAuthDialog extends React.Component -
{this.state.authError.message || this.state.authError.toString()}
+ +
{this.state.authError.message || this.state.authError.toString()}
+

{_t("action|dismiss")} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InviteDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InviteDialog.tsx index 08dbddc21d..2b3c7af8db 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InviteDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/InviteDialog.tsx @@ -17,6 +17,7 @@ limitations under the License. import React, { createRef, ReactNode, SyntheticEvent } from "react"; import classNames from "classnames"; import { RoomMember, Room, MatrixError, EventType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import { logger } from "matrix-js-sdk/src/logger"; import { uniqBy } from "lodash"; @@ -372,10 +373,10 @@ export default class InviteDialog extends React.PureComponent excludedIds.add(m.userId)); - room.getMembersWithMembership("join").forEach((m) => excludedIds.add(m.userId)); + room.getMembersWithMembership(KnownMembership.Invite).forEach((m) => excludedIds.add(m.userId)); + room.getMembersWithMembership(KnownMembership.Join).forEach((m) => excludedIds.add(m.userId)); // add banned users, so we don't try to invite them - room.getMembersWithMembership("ban").forEach((m) => excludedIds.add(m.userId)); + room.getMembersWithMembership(KnownMembership.Ban).forEach((m) => excludedIds.add(m.userId)); if (isFederated === false) { // exclude users from external servers const homeserver = props.roomId.split(":")[1]; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/LazyLoadingDisabledDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/LazyLoadingDisabledDialog.tsx deleted file mode 100644 index 1e90b91b45..0000000000 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/LazyLoadingDisabledDialog.tsx +++ /dev/null @@ -1,55 +0,0 @@ -/* -Copyright 2018 New Vector Ltd -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from "react"; - -import QuestionDialog from "./QuestionDialog"; -import { _t } from "../../../languageHandler"; -import SdkConfig from "../../../SdkConfig"; - -interface IProps { - host: string; - onFinished(): void; -} - -const LazyLoadingDisabledDialog: React.FC = (props) => { - const brand = SdkConfig.get().brand; - const description1 = _t("lazy_loading|disabled_description1", { - brand, - host: props.host, - }); - const description2 = _t("lazy_loading|disabled_description2", { - brand, - }); - - return ( - -

{description1}

-

{description2}

-
- } - button={_t("lazy_loading|disabled_action")} - onFinished={props.onFinished} - /> - ); -}; - -export default LazyLoadingDisabledDialog; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/LazyLoadingResyncDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/LazyLoadingResyncDialog.tsx deleted file mode 100644 index 54779bda4c..0000000000 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/LazyLoadingResyncDialog.tsx +++ /dev/null @@ -1,43 +0,0 @@ -/* -Copyright 2018 New Vector Ltd -Copyright 2020 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -import React from "react"; - -import QuestionDialog from "./QuestionDialog"; -import { _t } from "../../../languageHandler"; -import SdkConfig from "../../../SdkConfig"; - -interface IProps { - onFinished(): void; -} - -const LazyLoadingResyncDialog: React.FC = (props) => { - const brand = SdkConfig.get().brand; - const description = _t("lazy_loading|resync_description", { brand }); - - return ( - {description}
} - button={_t("action|ok")} - onFinished={props.onFinished} - /> - ); -}; - -export default LazyLoadingResyncDialog; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx index 0799ff88f1..9bc28ab4a0 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ManageRestrictedJoinRuleDialog.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { useMemo, useState } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import BaseDialog from "./BaseDialog"; @@ -102,7 +103,7 @@ const ManageRestrictedJoinRuleDialog: React.FC = ({ room, selected = [], if (!room) { return { roomId, name: roomId } as Room; } - if (room.getMyMembership() !== "join" || !room.isSpaceRoom()) { + if (room.getMyMembership() !== KnownMembership.Join || !room.isSpaceRoom()) { return room; } }), diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ReportEventDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ReportEventDialog.tsx index 52859c55f6..0e0b231b3f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ReportEventDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ReportEventDialog.tsx @@ -32,6 +32,12 @@ import Field from "../elements/Field"; import Spinner from "../elements/Spinner"; import LabelledCheckbox from "../elements/LabelledCheckbox"; +declare module "matrix-js-sdk/src/types" { + interface TimelineEvents { + [ABUSE_EVENT_TYPE]: AbuseEventContent; + } +} + interface IProps { mxEvent: MatrixEvent; onFinished(report?: boolean): void; @@ -56,7 +62,16 @@ const MODERATED_BY_STATE_EVENT_TYPE = [ */ ]; -const ABUSE_EVENT_TYPE = "org.matrix.msc3215.abuse.report"; +export const ABUSE_EVENT_TYPE = "org.matrix.msc3215.abuse.report"; + +interface AbuseEventContent { + event_id: string; + room_id: string; + moderated_by_id: string; + nature?: ExtendedNature; + reporter: string; + comment: string; +} // Standard abuse natures. enum Nature { @@ -250,13 +265,13 @@ export default class ReportEventDialog extends React.Component { } await client.sendEvent(dmRoomId, ABUSE_EVENT_TYPE, { - event_id: ev.getId(), - room_id: ev.getRoomId(), + event_id: ev.getId()!, + room_id: ev.getRoomId()!, moderated_by_id: this.moderation.moderationRoomId, nature, - reporter: client.getUserId(), + reporter: client.getUserId()!, comment: this.state.reason.trim(), - }); + } satisfies AbuseEventContent); } else { // Report to homeserver admin through the dedicated Matrix API. await client.reportEvent(ev.getRoomId()!, ev.getId()!, -100, this.state.reason.trim()); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ScrollableBaseModal.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ScrollableBaseModal.tsx index 8fa9fa3f64..a12632a05f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ScrollableBaseModal.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ScrollableBaseModal.tsx @@ -94,12 +94,12 @@ export default abstract class ScrollableBaseModal< >

{this.state.title}

-
+
{this.renderContent()}
diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ShareDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ShareDialog.tsx index aba35e70e2..9e6ee7fc8a 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ShareDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/ShareDialog.tsx @@ -62,11 +62,28 @@ const socials = [ ]; interface BaseProps { + /** + * A function that is called when the dialog is dismissed + */ onFinished(): void; + /** + * An optional string to use as the dialog title. + * If not provided, an appropriate title for the target type will be used. + */ + customTitle?: string; + /** + * An optional string to use as the dialog subtitle + */ + subtitle?: string; } interface Props extends BaseProps { - target: Room | User | RoomMember; + /** + * The target to link to. + * This can be a Room, User, RoomMember, or MatrixEvent or an already computed URL. + * A matrix.to link will be generated out of it if it's not already a url. + */ + target: Room | User | RoomMember | URL; permalinkCreator?: RoomPermalinkCreator; } @@ -109,7 +126,9 @@ export default class ShareDialog extends React.PureComponent 0) { @@ -146,9 +167,9 @@ export default class ShareDialog extends React.PureComponent + {this.props.subtitle &&

{this.props.subtitle}

}
matrixToUrl}> diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/UserSettingsDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/UserSettingsDialog.tsx index f0c9d1cd73..820617ae96 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/UserSettingsDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/UserSettingsDialog.tsx @@ -84,6 +84,16 @@ export default class UserSettingsDialog extends React.Component "UserSettingsGeneral", ), ); + tabs.push( + new Tab( + UserTab.SessionManager, + _td("settings|sessions|title"), + "mx_UserSettingsDialog_sessionsIcon", + , + // don't track with posthog while under construction + undefined, + ), + ); tabs.push( new Tab( UserTab.Appearance, @@ -151,16 +161,6 @@ export default class UserSettingsDialog extends React.Component "UserSettingsSecurityPrivacy", ), ); - tabs.push( - new Tab( - UserTab.SessionManager, - _td("settings|sessions|title"), - "mx_UserSettingsDialog_sessionsIcon", - , - // don't track with posthog while under construction - undefined, - ), - ); // Show the Labs tab if enabled or if there are any active betas if (showLabsFlags() || SettingsStore.getFeatureSettingNames().some((k) => SettingsStore.getBetaInfo(k))) { tabs.push( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/BaseTool.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/BaseTool.tsx index 49bcd76009..e5f93ead3f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/BaseTool.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/BaseTool.tsx @@ -60,7 +60,7 @@ const BaseTool: React.FC> = ({ let actionButton: ReactNode = null; if (message) { children = message; - } else if (onAction) { + } else if (onAction && actionLabel) { const onActionClick = (): void => { onAction().then((msg) => { if (typeof msg === "string") { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/Event.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/Event.tsx index 4b85dbe3f6..e1e0e469a3 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/Event.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/Event.tsx @@ -16,7 +16,7 @@ limitations under the License. */ import React, { ChangeEvent, ReactNode, useContext, useMemo, useRef, useState } from "react"; -import { IContent, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { IContent, MatrixEvent, TimelineEvents } from "matrix-js-sdk/src/matrix"; import { _t, _td, TranslationKey } from "../../../../languageHandler"; import Field from "../../elements/Field"; @@ -32,7 +32,7 @@ export const stringify = (object: object): string => { interface IEventEditorProps extends Pick { fieldDefs: IFieldDef[]; // immutable defaultContent?: string; - onSend(fields: string[], content?: IContent): Promise; + onSend(fields: string[], content: IContent): Promise; } interface IFieldDef { @@ -180,8 +180,8 @@ export const TimelineEventEditor: React.FC = ({ mxEvent, onBack }) const fields = useMemo(() => [eventTypeField(mxEvent?.getType())], [mxEvent]); - const onSend = ([eventType]: string[], content?: IContent): Promise => { - return cli.sendEvent(context.room.roomId, eventType, content || {}); + const onSend = ([eventType]: string[], content: TimelineEvents[keyof TimelineEvents]): Promise => { + return cli.sendEvent(context.room.roomId, eventType as keyof TimelineEvents, content); }; let defaultContent: string | undefined; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/RoomState.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/RoomState.tsx index ba8e3c75d9..51fdd1e830 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/RoomState.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/RoomState.tsx @@ -38,7 +38,7 @@ export const StateEventEditor: React.FC = ({ mxEvent, onBack }) => ); const onSend = async ([eventType, stateKey]: string[], content: IContent): Promise => { - await cli.sendStateEvent(context.room.roomId, eventType, content, stateKey); + await cli.sendStateEvent(context.room.roomId, eventType as any, content, stateKey); }; const defaultContent = mxEvent ? stringify(mxEvent.getContent()) : undefined; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/ServersInRoom.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/ServersInRoom.tsx index 4096a22626..bf980163ea 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/ServersInRoom.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/ServersInRoom.tsx @@ -17,6 +17,7 @@ limitations under the License. import React, { useContext, useMemo } from "react"; import { EventType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import BaseTool, { DevtoolsContext, IDevtoolsProps } from "./BaseTool"; import { _t } from "../../../../languageHandler"; @@ -27,7 +28,7 @@ const ServersInRoom: React.FC = ({ onBack }) => { const servers = useMemo>(() => { const servers: Record = {}; context.room.currentState.getStateEvents(EventType.RoomMember).forEach((ev) => { - if (ev.getContent().membership !== "join") return; // only count joined users + if (ev.getContent().membership !== KnownMembership.Join) return; // only count joined users const server = ev.getSender()!.split(":")[1]; servers[server] = (servers[server] ?? 0) + 1; }); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/VerificationExplorer.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/VerificationExplorer.tsx index dd9a4b0ee2..aad806d27f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/VerificationExplorer.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/devtools/VerificationExplorer.tsx @@ -16,8 +16,11 @@ limitations under the License. */ import React, { useContext, useEffect, useState } from "react"; -import { VerificationRequest } from "matrix-js-sdk/src/crypto/verification/request/VerificationRequest"; -import { VerificationPhase as Phase, VerificationRequestEvent } from "matrix-js-sdk/src/crypto-api"; +import { + VerificationPhase as Phase, + VerificationRequest, + VerificationRequestEvent, +} from "matrix-js-sdk/src/crypto-api"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; import { useTypedEventEmitter, useTypedEventEmitterState } from "../../../../hooks/useEventEmitter"; @@ -67,13 +70,11 @@ const VerificationRequestExplorer: React.FC<{
{_t("devtools|phase")}
{PHASE_MAP[request.phase] ? _t(PHASE_MAP[request.phase]) : request.phase}
{_t("devtools|timeout")}
-
{Math.floor(timeout / 1000)}
+
{timeout === null ? _t("devtools|timeout_none") : Math.floor(timeout / 1000)}
{_t("devtools|methods")}
{request.methods && request.methods.join(", ")}
-
{_t("devtools|requester")}
-
{request.requestingUserId}
-
{_t("devtools|observe_only")}
-
{JSON.stringify(request.observeOnly)}
+
{_t("devtools|other_user")}
+
{request.otherUserId}
); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx index 9f398cb3ed..35ea46f045 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/AccessSecretStorageDialog.tsx @@ -17,8 +17,8 @@ limitations under the License. import { debounce } from "lodash"; import classNames from "classnames"; import React, { ChangeEvent, FormEvent } from "react"; -import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api"; import { logger } from "matrix-js-sdk/src/logger"; +import { SecretStorage } from "matrix-js-sdk/src/matrix"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import Field from "../../elements/Field"; @@ -42,7 +42,7 @@ const VALIDATION_THROTTLE_MS = 200; export type KeyParams = { passphrase?: string; recoveryKey?: string }; interface IProps { - keyInfo: ISecretStorageKeyInfo; + keyInfo: SecretStorage.SecretStorageKeyDescription; checkPrivateKey: (k: KeyParams) => Promise; onFinished(result?: false | KeyParams): void; } @@ -290,8 +290,8 @@ export default class AccessSecretStorageDialog extends React.PureComponent + const resetLine = ( + {_t("encryption|reset_all_button", undefined, { a: (sub) => ( ), })} -
+ ); let content; @@ -378,7 +378,7 @@ export default class AccessSecretStorageDialog extends React.PureComponent
@@ -458,11 +458,11 @@ export default class AccessSecretStorageDialog extends React.PureComponent
diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx index edc2befe11..c535245e61 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/security/RestoreKeyBackupDialog.tsx @@ -16,9 +16,8 @@ limitations under the License. */ import React, { ChangeEvent } from "react"; -import { MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix"; +import { MatrixClient, MatrixError, SecretStorage } from "matrix-js-sdk/src/matrix"; import { IKeyBackupInfo, IKeyBackupRestoreResult } from "matrix-js-sdk/src/crypto/keybackup"; -import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api"; import { logger } from "matrix-js-sdk/src/logger"; import { MatrixClientPeg } from "../../../../MatrixClientPeg"; @@ -53,7 +52,7 @@ interface IProps { interface IState { backupInfo: IKeyBackupInfo | null; - backupKeyStored: Record | null; + backupKeyStored: Record | null; loading: boolean; loadError: boolean | null; restoreError: unknown | null; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/spotlight/SpotlightDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/spotlight/SpotlightDialog.tsx index 04df85e79f..ee42a59221 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/spotlight/SpotlightDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/dialogs/spotlight/SpotlightDialog.tsx @@ -26,6 +26,7 @@ import { HierarchyRoom, JoinRule, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { normalize } from "matrix-js-sdk/src/utils"; import React, { ChangeEvent, RefObject, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react"; import sanitizeHtml from "sanitize-html"; @@ -244,7 +245,7 @@ const findVisibleRooms = (cli: MatrixClient, msc3946ProcessDynamicPredecessor: b if (isLocalRoom(room)) return false; // TODO we may want to put invites in their own list - return room.getMyMembership() === "join" || room.getMyMembership() == "invite"; + return room.getMyMembership() === KnownMembership.Join || room.getMyMembership() == KnownMembership.Invite; }); }; @@ -675,7 +676,7 @@ const SpotlightDialog: React.FC = ({ initialText = "", initialFilter = n // world readable, a modal will appear asking you to register first. If // it is readable, the preview appears as normal. const showViewButton = - clientRoom?.getMyMembership() === "join" || + clientRoom?.getMyMembership() === KnownMembership.Join || (result.publicRoom.world_readable && !canAskToJoin(joinRule)) || cli.isGuest(); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/elements/AppTile.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/elements/AppTile.tsx index 74317041bd..7a1b641791 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/elements/AppTile.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/elements/AppTile.tsx @@ -21,6 +21,7 @@ import React, { ContextType, createRef, CSSProperties, MutableRefObject, ReactNo import classNames from "classnames"; import { IWidget, MatrixCapabilities } from "matrix-widget-api"; import { Room, RoomEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { ApprovalOpts, WidgetLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/WidgetLifecycle"; @@ -217,7 +218,10 @@ export default class AppTile extends React.Component { } private onMyMembership = (room: Room, membership: string): void => { - if ((membership === "leave" || membership === "ban") && room.roomId === this.props.room?.roomId) { + if ( + (membership === KnownMembership.Leave || membership === KnownMembership.Ban) && + room.roomId === this.props.room?.roomId + ) { this.onUserLeftRoom(); } }; @@ -249,8 +253,9 @@ export default class AppTile extends React.Component { private getNewState(newProps: IProps): IState { return { initialising: true, // True while we are mangling the widget URL - // True while the iframe content is loading - loading: this.props.waitForIframeLoad && !PersistedElement.isMounted(this.persistKey), + // Don't show loading at all if the widget is ready once the IFrame is loaded (waitForIframeLoad = true). + // We only need the loading screen if the widget sends a contentLoaded event (waitForIframeLoad = false). + loading: !this.props.waitForIframeLoad && !PersistedElement.isMounted(this.persistKey), // Assume that widget has permission to load if we are the user who // added it to the room, or if explicitly granted by the user hasPermissionToLoad: this.hasPermissionToLoad(newProps), @@ -312,7 +317,6 @@ export default class AppTile extends React.Component { if (this.props.room) { this.context.on(RoomEvent.MyMembership, this.onMyMembership); } - this.allowedWidgetsWatchRef = SettingsStore.watchSetting("allowedWidgets", null, this.onAllowedWidgetsChange); // Widget action listeners this.dispatcherRef = dis.register(this.onAction); @@ -352,7 +356,7 @@ export default class AppTile extends React.Component { } private setupSgListeners(): void { - this.sgWidget?.on("preparing", this.onWidgetPreparing); + this.sgWidget?.on("ready", this.onWidgetReady); this.sgWidget?.on("error:preparing", this.updateRequiresClient); // emits when the capabilities have been set up or changed this.sgWidget?.on("capabilitiesNotified", this.updateRequiresClient); @@ -360,7 +364,7 @@ export default class AppTile extends React.Component { private stopSgListeners(): void { if (!this.sgWidget) return; - this.sgWidget.off("preparing", this.onWidgetPreparing); + this.sgWidget?.off("ready", this.onWidgetReady); this.sgWidget.off("error:preparing", this.updateRequiresClient); this.sgWidget.off("capabilitiesNotified", this.updateRequiresClient); } @@ -446,8 +450,7 @@ export default class AppTile extends React.Component { this.sgWidget?.stopMessaging({ forceDestroy: true }); } - - private onWidgetPreparing = (): void => { + private onWidgetReady = (): void => { this.setState({ loading: false }); }; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/elements/EventListSummary.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/elements/EventListSummary.tsx index 4d9bbe35c9..a1270427cc 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/elements/EventListSummary.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/elements/EventListSummary.tsx @@ -18,6 +18,7 @@ limitations under the License. import React, { ComponentProps, ReactNode } from "react"; import { MatrixEvent, RoomMember, EventType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import { formatList } from "../../../utils/FormattingUtils"; @@ -416,12 +417,12 @@ export default class EventListSummary extends React.Component< case EventType.RoomMember: switch (e.mxEvent.getContent().membership) { - case "invite": + case KnownMembership.Invite: return TransitionType.Invited; - case "ban": + case KnownMembership.Ban: return TransitionType.Banned; - case "join": - if (e.mxEvent.getPrevContent().membership === "join") { + case KnownMembership.Join: + if (e.mxEvent.getPrevContent().membership === KnownMembership.Join) { if (e.mxEvent.getContent().displayname !== e.mxEvent.getPrevContent().displayname) { return TransitionType.ChangedName; } else if (e.mxEvent.getContent().avatar_url !== e.mxEvent.getPrevContent().avatar_url) { @@ -431,17 +432,17 @@ export default class EventListSummary extends React.Component< } else { return TransitionType.Joined; } - case "leave": + case KnownMembership.Leave: if (e.mxEvent.getSender() === e.mxEvent.getStateKey()) { - if (e.mxEvent.getPrevContent().membership === "invite") { + if (e.mxEvent.getPrevContent().membership === KnownMembership.Invite) { return TransitionType.InviteReject; } return TransitionType.Left; } switch (e.mxEvent.getPrevContent().membership) { - case "invite": + case KnownMembership.Invite: return TransitionType.InviteWithdrawal; - case "ban": + case KnownMembership.Ban: return TransitionType.Unbanned; // sender is not target and made the target leave, if not from invite/ban then this is a kick default: diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/elements/PollCreateDialog.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/elements/PollCreateDialog.tsx index 5049a3b016..0fd1b7c21e 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/elements/PollCreateDialog.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/elements/PollCreateDialog.tsx @@ -23,6 +23,7 @@ import { M_POLL_KIND_UNDISCLOSED, M_POLL_START, IPartialEvent, + TimelineEvents, } from "matrix-js-sdk/src/matrix"; import { PollStartEvent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent"; @@ -166,8 +167,8 @@ export default class PollCreateDialog extends ScrollableBaseModal { // The name to annotate the selector with label?: string; - onChange(value: number, powerLevelKey: K extends undefined ? void : K): void; + onChange(value: number, powerLevelKey: K extends undefined ? void : K): void | Promise; // Optional key to pass as the second argument to `onChange` powerLevelKey: K extends undefined ? void : K; @@ -60,6 +60,7 @@ export default class PowerSelector extends React.C maxValue: Infinity, usersDefault: 0, }; + private unmounted = false; public constructor(props: Props) { super(props); @@ -84,6 +85,10 @@ export default class PowerSelector extends React.C } } + public componentWillUnmount(): void { + this.unmounted = true; + } + private initStateFromProps(): void { // This needs to be done now because levelRoleMap has translated strings const levelRoleMap = Roles.levelRoleMap(this.props.usersDefault); @@ -106,14 +111,20 @@ export default class PowerSelector extends React.C }); } - private onSelectChange = (event: React.ChangeEvent): void => { + private onSelectChange = async (event: React.ChangeEvent): Promise => { const isCustom = event.target.value === CUSTOM_VALUE; if (isCustom) { this.setState({ custom: true }); } else { const powerLevel = parseInt(event.target.value); - this.props.onChange(powerLevel, this.props.powerLevelKey); this.setState({ selectValue: powerLevel }); + try { + await this.props.onChange(powerLevel, this.props.powerLevelKey); + } catch { + if (this.unmounted) return; + // If the request failed, roll back the state of the selector. + this.initStateFromProps(); + } } }; @@ -121,12 +132,18 @@ export default class PowerSelector extends React.C this.setState({ customValue: parseInt(event.target.value) }); }; - private onCustomBlur = (event: React.FocusEvent): void => { + private onCustomBlur = async (event: React.FocusEvent): Promise => { event.preventDefault(); event.stopPropagation(); if (Number.isFinite(this.state.customValue)) { - this.props.onChange(this.state.customValue, this.props.powerLevelKey); + try { + await this.props.onChange(this.state.customValue, this.props.powerLevelKey); + } catch { + if (this.unmounted) return; + // If the request failed, roll back the state of the selector. + this.initStateFromProps(); + } } else { this.initStateFromProps(); // reset, invalid input } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomFacePile.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomFacePile.tsx index 6ec333c4e5..0d1491edba 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomFacePile.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomFacePile.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { FC, HTMLAttributes, useContext } from "react"; import { Room, RoomMember } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { sortBy } from "lodash"; import { _t } from "../../../languageHandler"; @@ -38,7 +39,7 @@ interface IProps extends HTMLAttributes { const RoomFacePile: FC = ({ room, onlyKnownUsers = true, numShown = DEFAULT_NUM_FACES, ...props }) => { const cli = useContext(MatrixClientContext); - const isJoined = room.getMyMembership() === "join"; + const isJoined = room.getMyMembership() === KnownMembership.Join; let members = useRoomMembers(room); const count = members.length; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomTopic.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomTopic.tsx index 35eb72515f..fa9fc0fd34 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomTopic.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/elements/RoomTopic.tsx @@ -36,7 +36,7 @@ interface IProps extends React.HTMLProps { room: Room; } -export default function RoomTopic({ room, ...props }: IProps): JSX.Element { +export default function RoomTopic({ room, className, ...props }: IProps): JSX.Element { const client = useContext(MatrixClientContext); const ref = useRef(null); @@ -82,7 +82,8 @@ export default function RoomTopic({ room, ...props }: IProps): JSX.Element { ) { + onClick(e); modal.close(); }, }, @@ -110,15 +111,13 @@ export default function RoomTopic({ room, ...props }: IProps): JSX.Element { } }); - const className = classNames(props.className, "mx_RoomTopic"); - return ( void; - - // The current value of the slider - value: number; - - // The min and max of the slider - min: number; - max: number; - // The step size of the slider, can be a number or "any" - step: number | "any"; - - // A function for formatting the values - displayFunc: (value: number) => string; - - // Whether the slider is disabled - disabled: boolean; - - label: string; -} - -const THUMB_SIZE = 2.4; // em - -export default class Slider extends React.Component { - private get position(): number { - const { min, max, value } = this.props; - return Number(((value - min) * 100) / (max - min)); - } - - private onChange = (ev: ChangeEvent): void => { - this.props.onChange(parseInt(ev.target.value, 10)); - }; - - public render(): React.ReactNode { - let selection: JSX.Element | undefined; - - if (!this.props.disabled) { - const position = this.position; - selection = ( - - {this.props.value} - - ); - } - - return ( -
- - {selection} -
- ); - } -} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/elements/SyntaxHighlight.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/elements/SyntaxHighlight.tsx index 3262ce5d6c..caa7ceb51c 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/elements/SyntaxHighlight.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/elements/SyntaxHighlight.tsx @@ -16,22 +16,23 @@ limitations under the License. */ import React from "react"; -import hljs from "highlight.js"; -interface IProps { +import { useAsyncMemo } from "../../../hooks/useAsyncMemo"; + +interface Props { language?: string; children: string; } -export default class SyntaxHighlight extends React.PureComponent { - public render(): React.ReactNode { - const { children: content, language } = this.props; - const highlighted = language ? hljs.highlight(content, { language }) : hljs.highlightAuto(content); - - return ( -
-                
-            
- ); - } +export default function SyntaxHighlight({ children, language }: Props): JSX.Element { + const highlighted = useAsyncMemo(async () => { + const { default: highlight } = await import("highlight.js"); + return language ? highlight.highlight(children, { language }) : highlight.highlightAuto(children); + }, [language, children]); + + return ( +
+            {highlighted ?  : children}
+        
+ ); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/elements/TruncatedList.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/elements/TruncatedList.tsx index 074df5bfb2..4c6979832d 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/elements/TruncatedList.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/elements/TruncatedList.tsx @@ -36,6 +36,7 @@ interface IProps { // This will be inserted after the children. createOverflowElement: (overflowCount: number, totalCount: number) => React.ReactNode; children?: ReactNode; + id?: string; } export default class TruncatedList extends React.Component { @@ -86,7 +87,7 @@ export default class TruncatedList extends React.Component { const childNodes = this.getChildren(0, upperBound); return ( -
+
{childNodes} {overflowNode}
diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/emojipicker/ReactionPicker.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/emojipicker/ReactionPicker.tsx index a1c07b63d7..075a6e6cee 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/emojipicker/ReactionPicker.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/emojipicker/ReactionPicker.tsx @@ -108,7 +108,7 @@ class ReactionPicker extends React.Component { MatrixClientPeg.safeGet().sendEvent(this.props.mxEvent.getRoomId()!, EventType.Reaction, { "m.relates_to": { rel_type: RelationType.Annotation, - event_id: this.props.mxEvent.getId(), + event_id: this.props.mxEvent.getId()!, key: reaction, }, }); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/location/LocationButton.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/location/LocationButton.tsx index fe9cf056b4..aab595e1f9 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/location/LocationButton.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/location/LocationButton.tsx @@ -24,7 +24,7 @@ import { aboveLeftOf, useContextMenu, MenuProps } from "../../structures/Context import { OverflowMenuContext } from "../rooms/MessageComposerButtons"; import LocationShareMenu from "./LocationShareMenu"; -interface IProps { +export interface IProps { roomId: string; sender: RoomMember; menuPosition?: MenuProps; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/location/Map.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/location/Map.tsx index 8eda492b30..7d726da494 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/location/Map.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/location/Map.tsx @@ -139,7 +139,7 @@ const onGeolocateError = (e: GeolocationPositionError): void => { }); }; -interface MapProps { +export interface MapProps { id: string; interactive?: boolean; /** diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/location/SmartMarker.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/location/SmartMarker.tsx index f082bce8d8..27f6eb5d03 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/location/SmartMarker.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/location/SmartMarker.tsx @@ -18,7 +18,8 @@ import React, { ReactNode, useCallback, useEffect, useState } from "react"; import * as maplibregl from "maplibre-gl"; import { RoomMember } from "matrix-js-sdk/src/matrix"; -import { createMarker, parseGeoUri } from "../../../utils/location"; +import { parseGeoUri } from "../../../utils/location"; +import { createMarker } from "../../../utils/location/map"; import Marker from "./Marker"; const useMapMarker = ( @@ -66,7 +67,7 @@ const useMapMarker = ( }; }; -interface SmartMarkerProps { +export interface SmartMarkerProps { map: maplibregl.Map; geoUri: string; id?: string; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/location/index.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/location/index.tsx new file mode 100644 index 0000000000..3df2289d64 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/components/views/location/index.tsx @@ -0,0 +1,71 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Exports location components which touch maplibre-gs wrapped in React Suspense to enable code splitting + +import React, { ComponentProps, lazy, Suspense } from "react"; + +import Spinner from "../elements/Spinner"; + +const MapComponent = lazy(() => import("./Map")); + +export function Map(props: ComponentProps): JSX.Element { + return ( + }> + + + ); +} + +const LocationPickerComponent = lazy(() => import("./LocationPicker")); + +export function LocationPicker(props: ComponentProps): JSX.Element { + return ( + }> + + + ); +} + +const SmartMarkerComponent = lazy(() => import("./SmartMarker")); + +export function SmartMarker(props: ComponentProps): JSX.Element { + return ( + }> + + + ); +} + +const LocationButtonComponent = lazy(() => import("./LocationButton")); + +export function LocationButton(props: ComponentProps): JSX.Element { + return ( + }> + + + ); +} + +const LocationViewDialogComponent = lazy(() => import("./LocationViewDialog")); + +export function LocationViewDialog(props: ComponentProps): JSX.Element { + return ( + }> + + + ); +} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/location/shareLocation.ts b/linked-dependencies/matrix-react-sdk/src/components/views/location/shareLocation.ts index cf44a77c73..42a8e25c5b 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/location/shareLocation.ts +++ b/linked-dependencies/matrix-react-sdk/src/components/views/location/shareLocation.ts @@ -16,13 +16,13 @@ limitations under the License. import { MatrixClient, - IContent, IEventRelation, MatrixError, THREAD_RELATION_TYPE, ContentHelpers, LocationAssetType, } from "matrix-js-sdk/src/matrix"; +import { RoomMessageEventContent } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../languageHandler"; @@ -146,7 +146,7 @@ export const shareLocation = timestamp, undefined, assetType, - ) as IContent; + ) as RoomMessageEventContent; await doMaybeLocalRoomAction( roomId, (actualRoomId: string) => client.sendMessage(actualRoomId, threadId, content), diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MAudioBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MAudioBody.tsx index f3868f6b83..76c9634b6f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MAudioBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MAudioBody.tsx @@ -17,13 +17,14 @@ limitations under the License. import React from "react"; import { logger } from "matrix-js-sdk/src/logger"; import { IContent } from "matrix-js-sdk/src/matrix"; +import { MediaEventContent } from "matrix-js-sdk/src/types"; import { Playback } from "../../../audio/Playback"; import InlineSpinner from "../elements/InlineSpinner"; import { _t } from "../../../languageHandler"; import AudioPlayer from "../audio_messages/AudioPlayer"; -import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; // :TCHAP: content-scanner import MFileBody from "../../../../../../src/tchap/components/views/messages/OriginalFileBody"; // :TCHAP: content-scanner +// import MFileBody from "./MFileBody";// :TCHAP: content-scanner import { IBodyProps } from "./IBodyProps"; import { PlaybackManager } from "../../../audio/PlaybackManager"; import { isVoiceMessage } from "../../../utils/EventUtils"; @@ -67,7 +68,7 @@ export default class MAudioBody extends React.PureComponent // We should have a buffer to work with now: let's set it up // Note: we don't actually need a waveform to render an audio event, but voice messages do. - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent(); const waveform = content?.["org.matrix.msc1767.audio"]?.waveform?.map((p: number) => p / 1024); // We should have a buffer to work with now: let's set it up diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MBeaconBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MBeaconBody.tsx index d5a8609376..16f85559d3 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MBeaconBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MBeaconBody.tsx @@ -38,12 +38,11 @@ import { isSelfLocation, LocationShareError } from "../../../utils/location"; import { BeaconDisplayStatus, getBeaconDisplayStatus } from "../beacon/displayStatus"; import BeaconStatus from "../beacon/BeaconStatus"; import OwnBeaconStatus from "../beacon/OwnBeaconStatus"; -import Map from "../location/Map"; +import { Map, SmartMarker } from "../location"; import { MapError } from "../location/MapError"; import MapFallback from "../location/MapFallback"; -import SmartMarker from "../location/SmartMarker"; import { GetRelationsForEvent } from "../rooms/EventTile"; -import BeaconViewDialog from "../beacon/BeaconViewDialog"; +import { BeaconViewDialog } from "../beacon"; import { IBodyProps } from "./IBodyProps"; const useBeaconState = ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MFileBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MFileBody.tsx index ab0c1f505e..12d4c80416 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MFileBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MFileBody.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { AllHTMLAttributes, createRef } from "react"; import { logger } from "matrix-js-sdk/src/logger"; +import { MediaEventContent } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import Modal from "../../../Modal"; @@ -23,7 +24,6 @@ import AccessibleButton from "../elements/AccessibleButton"; import { mediaFromContent } from "../../../customisations/Media"; import ErrorDialog from "../dialogs/ErrorDialog"; import { fileSize, presentableTextForFile } from "../../../utils/FileUtils"; -import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; import { IBodyProps } from "./IBodyProps"; import { FileDownloader } from "../../../utils/FileDownloader"; import TextWithTooltip from "../elements/TextWithTooltip"; @@ -128,8 +128,8 @@ export default class MFileBody extends React.Component { const media = mediaFromContent(this.props.mxEvent.getContent()); return media.srcHttp; } - private get content(): IMediaEventContent { - return this.props.mxEvent.getContent(); + private get content(): MediaEventContent { + return this.props.mxEvent.getContent(); } private get fileName(): string { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageBody.tsx index bbcea7c63e..54c7c5f40b 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageBody.tsx @@ -21,6 +21,7 @@ import classNames from "classnames"; import { CSSTransition, SwitchTransition } from "react-transition-group"; import { logger } from "matrix-js-sdk/src/logger"; import { ClientEvent, ClientEventHandlerMap } from "matrix-js-sdk/src/matrix"; +import { ImageContent } from "matrix-js-sdk/src/types"; import { Tooltip } from "@vector-im/compound-web"; import MFileBody from "../../../../../../src/tchap/components/views/messages/OriginalFileBody"; // :TCHAP: content-scanner @@ -30,7 +31,6 @@ import SettingsStore from "../../../settings/SettingsStore"; import Spinner from "../elements/Spinner"; import { Media, mediaFromContent } from "../../../customisations/Media"; import { BLURHASH_FIELD, createThumbnail } from "../../../utils/image-media"; -import { ImageContent } from "../../../customisations/models/IMediaEventContent"; import ImageView from "../elements/ImageView"; import { IBodyProps } from "./IBodyProps"; import { ImageSize, suggestedSize as suggestedImageSize } from "../../../settings/enums/ImageSize"; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageReplyBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageReplyBody.tsx index c24f3d854b..eb9cff6611 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageReplyBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MImageReplyBody.tsx @@ -15,9 +15,10 @@ limitations under the License. */ import React from "react"; +import { ImageContent } from "matrix-js-sdk/src/types"; import MImageBody from "../../../../../../src/tchap/components/views/messages/OriginalImageBody"; // :TCHAP: content-scanner -import { ImageContent } from "../../../customisations/models/IMediaEventContent"; // :TCHAP: content-scanner +// import MImageBody from "./MImageBody"; // :TCHAP: content-scanner const FORCED_IMAGE_HEIGHT = 44; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MLocationBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MLocationBody.tsx index 8b2dc2e95d..29c1c97e1a 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MLocationBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MLocationBody.tsx @@ -29,9 +29,7 @@ import { import MatrixClientContext from "../../../contexts/MatrixClientContext"; import TooltipTarget from "../elements/TooltipTarget"; import { Alignment } from "../elements/Tooltip"; -import LocationViewDialog from "../location/LocationViewDialog"; -import Map from "../location/Map"; -import SmartMarker from "../location/SmartMarker"; +import { SmartMarker, Map, LocationViewDialog } from "../location"; import { IBodyProps } from "./IBodyProps"; import { createReconnectedListener } from "../../../utils/connection"; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MPollBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MPollBody.tsx index fcf92c7f62..d777ed9d77 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MPollBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MPollBody.tsx @@ -25,6 +25,7 @@ import { M_POLL_KIND_DISCLOSED, M_POLL_RESPONSE, M_POLL_START, + TimelineEvents, } from "matrix-js-sdk/src/matrix"; import { RelatedRelations } from "matrix-js-sdk/src/models/related-relations"; import { PollStartEvent, PollAnswerSubevent } from "matrix-js-sdk/src/extensible_events_v1/PollStartEvent"; @@ -225,14 +226,20 @@ export default class MPollBody extends React.Component { const response = PollResponseEvent.from([answerId], this.props.mxEvent.getId()!).serialize(); - this.context.sendEvent(this.props.mxEvent.getRoomId()!, response.type, response.content).catch((e: any) => { - console.error("Failed to submit poll response event:", e); - - Modal.createDialog(ErrorDialog, { - title: _t("poll|error_voting_title"), - description: _t("poll|error_voting_description"), + this.context + .sendEvent( + this.props.mxEvent.getRoomId()!, + response.type as keyof TimelineEvents, + response.content as TimelineEvents[keyof TimelineEvents], + ) + .catch((e: any) => { + console.error("Failed to submit poll response event:", e); + + Modal.createDialog(ErrorDialog, { + title: _t("poll|error_voting_title"), + description: _t("poll|error_voting_description"), + }); }); - }); this.setState({ selected: answerId }); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MStickerBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MStickerBody.tsx index c3f1e797cf..dfe9d336c9 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MStickerBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MStickerBody.tsx @@ -16,10 +16,10 @@ limitations under the License. import React, { ComponentProps, ReactNode } from "react"; import { Tooltip } from "@vector-im/compound-web"; +import { MediaEventContent } from "matrix-js-sdk/src/types"; import MImageBody from "../../../../../../src/tchap/components/views/messages/OriginalImageBody"; // :TCHAP: content-scanner import { BLURHASH_FIELD } from "../../../utils/image-media"; -import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; // :TCHAP: content-scanner export default class MStickerBody extends MImageBody { // Mostly empty to prevent default behaviour of MImageBody @@ -80,7 +80,7 @@ export default class MStickerBody extends MImageBody { return null; } - protected getBanner(content: IMediaEventContent): ReactNode { + protected getBanner(content: MediaEventContent): ReactNode { return null; // we don't need a banner, we have a tooltip } } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MVideoBody.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MVideoBody.tsx index cedfef9844..84aa08162a 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/MVideoBody.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/MVideoBody.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { ReactNode } from "react"; import { decode } from "blurhash"; +import { MediaEventContent } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../languageHandler"; @@ -23,7 +24,6 @@ import SettingsStore from "../../../settings/SettingsStore"; import InlineSpinner from "../elements/InlineSpinner"; import { mediaFromContent } from "../../../customisations/Media"; import { BLURHASH_FIELD } from "../../../utils/image-media"; -import { IMediaEventContent } from "../../../customisations/models/IMediaEventContent"; import { IBodyProps } from "./IBodyProps"; import MFileBody from "../../../../../../src/tchap/components/views/messages/OriginalFileBody"; // :TCHAP: content-scanner import { ImageSize, suggestedSize as suggestedVideoSize } from "../../../settings/enums/ImageSize"; @@ -62,7 +62,7 @@ export default class MVideoBody extends React.PureComponent } private getContentUrl(): string | undefined { - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent(); // During export, the content url will point to the MSC, which will later point to a local url if (this.props.forExport) return content.file?.url ?? content.url; const media = mediaFromContent(content); @@ -82,7 +82,7 @@ export default class MVideoBody extends React.PureComponent // there's no need of thumbnail when the content is local if (this.props.forExport) return null; - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent(); const media = mediaFromContent(content); if (media.isEncrypted && this.state.decryptedThumbnailUrl) { @@ -121,7 +121,7 @@ export default class MVideoBody extends React.PureComponent posterLoading: true, }); - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent(); const media = mediaFromContent(content); if (media.hasThumbnail) { const image = new Image(); @@ -157,7 +157,7 @@ export default class MVideoBody extends React.PureComponent this.props.onHeightChanged?.(); } else { logger.log("NOT preloading video"); - const content = this.props.mxEvent.getContent(); + const content = this.props.mxEvent.getContent(); let mimetype = content?.info?.mimetype; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/messages/ReactionsRowButton.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/messages/ReactionsRowButton.tsx index 99a1a6088b..2737212d33 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/messages/ReactionsRowButton.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/messages/ReactionsRowButton.tsx @@ -16,7 +16,7 @@ limitations under the License. import React from "react"; import classNames from "classnames"; -import { MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { EventType, MatrixEvent, RelationType } from "matrix-js-sdk/src/matrix"; import { mediaFromMxc } from "../../../customisations/Media"; import { _t } from "../../../languageHandler"; @@ -26,6 +26,7 @@ import ReactionsRowButtonTooltip from "./ReactionsRowButtonTooltip"; import AccessibleButton from "../elements/AccessibleButton"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { REACTION_SHORTCODE_KEY } from "./ReactionsRow"; + export interface IProps { // The event we're displaying reactions for mxEvent: MatrixEvent; @@ -62,10 +63,10 @@ export default class ReactionsRowButton extends React.PureComponent { pre.append(document.createElement("span")); } - private highlightCode(code: HTMLElement): void { + private async highlightCode(code: HTMLElement): Promise { + const { default: highlight } = await import("highlight.js"); + if (code.textContent && code.textContent.length > MAX_HIGHLIGHT_LENGTH) { console.log( "Code block is bigger than highlight limit (" + diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/BaseCard.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/BaseCard.tsx index 580db4621a..2afae0bc28 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/BaseCard.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/BaseCard.tsx @@ -35,6 +35,8 @@ interface IProps { onKeyDown?(ev: KeyboardEvent): void; cardState?: any; ref?: Ref; + // Ref for the 'close' button the the card + closeButtonRef?: Ref; children: ReactNode; } @@ -54,7 +56,21 @@ export const Group: React.FC = ({ className, title, children }) => }; const BaseCard: React.FC = forwardRef( - ({ closeLabel, onClose, onBack, className, header, footer, withoutScrollContainer, children, onKeyDown }, ref) => { + ( + { + closeLabel, + onClose, + onBack, + className, + header, + footer, + withoutScrollContainer, + children, + onKeyDown, + closeButtonRef, + }, + ref, + ) => { let backButton; const cardHistory = RightPanelStore.instance.roomPhaseHistory; if (cardHistory.length > 1) { @@ -75,6 +91,7 @@ const BaseCard: React.FC = forwardRef( className="mx_BaseCard_close" onClick={onClose} title={closeLabel || _t("action|close")} + ref={closeButtonRef} /> ); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/RoomSummaryCard.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/RoomSummaryCard.tsx index 739f9d5132..72cab396c0 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/RoomSummaryCard.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/RoomSummaryCard.tsx @@ -32,7 +32,7 @@ import { Icon as LockIcon } from "@vector-im/compound-design-tokens/icons/lock-s import { Icon as LockOffIcon } from "@vector-im/compound-design-tokens/icons/lock-off.svg"; import { Icon as PublicIcon } from "@vector-im/compound-design-tokens/icons/public.svg"; import { Icon as ErrorIcon } from "@vector-im/compound-design-tokens/icons/error.svg"; -import { EventType, JoinRule, Room } from "matrix-js-sdk/src/matrix"; +import { EventType, JoinRule, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import { useIsEncrypted } from "../../../hooks/useIsEncrypted"; @@ -402,6 +402,7 @@ const RoomSummaryCard: React.FC = ({ room, permalinkCreator, onClose, on const roomTags = useEventEmitterState(RoomListStore.instance, LISTS_UPDATE_EVENT, () => RoomListStore.instance.getTagsForRoom(room), ); + const canInviteToState = useEventEmitterState(room, RoomStateEvent.Update, () => canInviteTo(room)); const isFavorite = roomTags.includes(DefaultTagID.Favourite); return ( @@ -448,7 +449,7 @@ const RoomSummaryCard: React.FC = ({ room, permalinkCreator, onClose, on inviteToRoom(room)} /> diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/TimelineCard.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/TimelineCard.tsx index 7e3ce09e50..7dfcd63307 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/TimelineCard.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/TimelineCard.tsx @@ -23,6 +23,7 @@ import { EventTimelineSet, Thread, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import BaseCard from "./BaseCard"; import ResizeNotifier from "../../../utils/ResizeNotifier"; @@ -217,7 +218,7 @@ export default class TimelineCard extends React.Component { const isUploading = ContentMessages.sharedInstance().getCurrentUploads(this.props.composerRelation).length > 0; const myMembership = this.props.room.getMyMembership(); - const showComposer = myMembership === "join"; + const showComposer = myMembership === KnownMembership.Join; return ( device.deviceId !== dehydratedDeviceId); + dehydratedDeviceInExpandSection = true; + } expandSectionDevices = devices; expandCountCaption = _t("user_info|count_of_sessions", { count: devices.length }); expandHideCaption = _t("user_info|hide_sessions"); @@ -346,6 +371,9 @@ function DevicesSection({ ); }), ); + if (dehydratedDeviceInExpandSection) { + deviceList.push(
{_t("user_info|dehydrated_device_enabled")}
); + } } return ( @@ -473,7 +501,7 @@ export const UserOptionsSection: React.FC<{ if ( member instanceof RoomMember && canInvite && - (member?.membership ?? "leave") === "leave" && + (member?.membership ?? KnownMembership.Leave) === KnownMembership.Leave && shouldShowComponent(UIComponent.InviteUsers) ) { const roomId = member && member.roomId ? member.roomId : SdkContextClass.instance.roomViewStore.getRoomId(); @@ -638,7 +666,7 @@ export const RoomKickButton = ({ const cli = useContext(MatrixClientContext); // check if user can be kicked/disinvited - if (member.membership !== "invite" && member.membership !== "join") return <>; + if (member.membership !== KnownMembership.Invite && member.membership !== KnownMembership.Join) return <>; const onKick = async (): Promise => { if (isUpdating) return; // only allow one operation at a time @@ -647,17 +675,17 @@ export const RoomKickButton = ({ const commonProps = { member, action: room.isSpaceRoom() - ? member.membership === "invite" + ? member.membership === KnownMembership.Invite ? _t("user_info|disinvite_button_space") : _t("user_info|kick_button_space") - : member.membership === "invite" + : member.membership === KnownMembership.Invite ? _t("user_info|disinvite_button_room") : _t("user_info|kick_button_room"), title: - member.membership === "invite" + member.membership === KnownMembership.Invite ? _t("user_info|disinvite_button_room_name", { roomName: room.name }) : _t("user_info|kick_button_room_name", { roomName: room.name }), - askReason: member.membership === "join", + askReason: member.membership === KnownMembership.Join, danger: true, }; @@ -718,10 +746,10 @@ export const RoomKickButton = ({ }; const kickLabel = room.isSpaceRoom() - ? member.membership === "invite" + ? member.membership === KnownMembership.Invite ? _t("user_info|disinvite_button_space") : _t("user_info|kick_button_space") - : member.membership === "invite" + : member.membership === KnownMembership.Invite ? _t("user_info|disinvite_button_room") : _t("user_info|kick_button_room"); @@ -771,7 +799,7 @@ export const BanToggleButton = ({ }: Omit): JSX.Element => { const cli = useContext(MatrixClientContext); - const isBanned = member.membership === "ban"; + const isBanned = member.membership === KnownMembership.Ban; const onBanOrUnban = async (): Promise => { if (isUpdating) return; // only allow one operation at a time startUpdating(); @@ -808,7 +836,7 @@ export const BanToggleButton = ({ return ( !!myMember && !!theirMember && - theirMember.membership === "ban" && + theirMember.membership === KnownMembership.Ban && myMember.powerLevel > theirMember.powerLevel && child.currentState.hasSufficientPowerLevelFor("ban", myMember.powerLevel) ); @@ -820,7 +848,7 @@ export const BanToggleButton = ({ return ( !!myMember && !!theirMember && - theirMember.membership !== "ban" && + theirMember.membership !== KnownMembership.Ban && myMember.powerLevel > theirMember.powerLevel && child.currentState.hasSufficientPowerLevelFor("ban", myMember.powerLevel) ); @@ -903,7 +931,7 @@ const MuteToggleButton: React.FC = ({ const cli = useContext(MatrixClientContext); // Don't show the mute/unmute option if the user is not in the room - if (member.membership !== "join") return null; + if (member.membership !== KnownMembership.Join) return null; const muted = isMuted(member, powerLevels); const onMuteToggle = async (): Promise => { @@ -931,7 +959,7 @@ const MuteToggleButton: React.FC = ({ return; } - cli.setPowerLevel(roomId, target, level, powerLevelEvent) + cli.setPowerLevel(roomId, target, level) .then( () => { // NO-OP; rely on the m.room.member event coming down else we could @@ -1158,13 +1186,8 @@ export const PowerLevelEditor: React.FC<{ async (powerLevel: number) => { setSelectedPowerLevel(powerLevel); - const applyPowerChange = ( - roomId: string, - target: string, - powerLevel: number, - powerLevelEvent: MatrixEvent, - ): Promise => { - return cli.setPowerLevel(roomId, target, powerLevel, powerLevelEvent).then( + const applyPowerChange = (roomId: string, target: string, powerLevel: number): Promise => { + return cli.setPowerLevel(roomId, target, powerLevel).then( function () { // NO-OP; rely on the m.room.member event coming down else we could // get out of sync if we force setState here! @@ -1212,7 +1235,7 @@ export const PowerLevelEditor: React.FC<{ } } - await applyPowerChange(roomId, target, powerLevel, powerLevelEvent); + await applyPowerChange(roomId, target, powerLevel); }, [user.roomId, user.userId, cli, room], ); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/VerificationPanel.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/VerificationPanel.tsx index 97eb681392..4189ee190f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/VerificationPanel.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/right_panel/VerificationPanel.tsx @@ -15,16 +15,17 @@ limitations under the License. */ import React from "react"; -import { verificationMethods } from "matrix-js-sdk/src/crypto"; -import { SCAN_QR_CODE_METHOD } from "matrix-js-sdk/src/crypto/verification/QRCode"; import { + ShowQrCodeCallbacks, + ShowSasCallbacks, VerificationPhase as Phase, VerificationRequest, VerificationRequestEvent, + VerifierEvent, } from "matrix-js-sdk/src/crypto-api"; -import { RoomMember, Device, User } from "matrix-js-sdk/src/matrix"; +import { Device, RoomMember, User } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; -import { ShowQrCodeCallbacks, ShowSasCallbacks, VerifierEvent } from "matrix-js-sdk/src/crypto-api/verification"; +import { VerificationMethod } from "matrix-js-sdk/src/types"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import VerificationQRCode from "../elements/crypto/VerificationQRCode"; @@ -85,8 +86,8 @@ export default class VerificationPanel extends React.PureComponent => { this.setState({ emojiButtonClicked: true }); - await this.props.request.startVerification(verificationMethods.SAS); + await this.props.request.startVerification(VerificationMethod.Sas); }; private onSasMatchesClick = (): void => { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/room_settings/AliasSettings.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/room_settings/AliasSettings.tsx index 7b1bc1be28..3b2f294e5c 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/room_settings/AliasSettings.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/room_settings/AliasSettings.tsx @@ -15,8 +15,9 @@ limitations under the License. */ import React, { ChangeEvent, ContextType, createRef, SyntheticEvent } from "react"; -import { IContent, MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; +import { MatrixEvent, EventType } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; +import { RoomCanonicalAliasEventContent } from "matrix-js-sdk/src/types"; import EditableItemList from "../elements/EditableItemList"; import { _t } from "../../../languageHandler"; @@ -169,7 +170,7 @@ export default class AliasSettings extends React.Component { updatingCanonicalAlias: true, }); - const eventContent: IContent = { + const eventContent: RoomCanonicalAliasEventContent = { alt_aliases: this.state.altAliases, }; @@ -197,7 +198,7 @@ export default class AliasSettings extends React.Component { updatingCanonicalAlias: true, }); - const eventContent: IContent = {}; + const eventContent: RoomCanonicalAliasEventContent = {}; if (this.state.canonicalAlias) { eventContent["alias"] = this.state.canonicalAlias; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/EditMessageComposer.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/EditMessageComposer.tsx index 2839732c13..fabca13a1c 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/EditMessageComposer.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/EditMessageComposer.tsx @@ -16,9 +16,10 @@ limitations under the License. import React, { createRef, KeyboardEvent } from "react"; import classNames from "classnames"; -import { EventStatus, IContent, MatrixEvent, Room, MsgType } from "matrix-js-sdk/src/matrix"; +import { EventStatus, MatrixEvent, Room, MsgType } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { Composer as ComposerEvent } from "@matrix-org/analytics-events/types/typescript/Composer"; +import { ReplacementEvent, RoomMessageEventContent, RoomMessageTextEventContent } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import dis from "../../../dispatcher/dispatcher"; @@ -70,7 +71,11 @@ function getTextReplyFallback(mxEvent: MatrixEvent): string { } // exported for tests -export function createEditContent(model: EditorModel, editedEvent: MatrixEvent, replyToEvent?: MatrixEvent): IContent { +export function createEditContent( + model: EditorModel, + editedEvent: MatrixEvent, + replyToEvent?: MatrixEvent, +): RoomMessageEventContent { const isEmote = containsEmote(model); if (isEmote) { model = stripEmoteCommand(model); @@ -86,11 +91,11 @@ export function createEditContent(model: EditorModel, editedEvent: MatrixEvent, const body = textSerialize(model); - const newContent: IContent = { + const newContent: RoomMessageEventContent = { msgtype: isEmote ? MsgType.Emote : MsgType.Text, body: body, }; - const contentBody: IContent = { + const contentBody: RoomMessageTextEventContent & Omit, "m.relates_to"> = { "msgtype": newContent.msgtype, "body": `${plainPrefix} * ${body}`, "m.new_content": newContent, @@ -111,7 +116,7 @@ export function createEditContent(model: EditorModel, editedEvent: MatrixEvent, attachMentions(editedEvent.sender!.userId, contentBody, model, replyToEvent, editedEvent.getContent()); attachRelation(contentBody, { rel_type: "m.replace", event_id: editedEvent.getId() }); - return contentBody; + return contentBody as RoomMessageEventContent; } interface IEditMessageComposerProps extends MatrixClientProps { @@ -142,7 +147,7 @@ class EditMessageComposer extends React.Component(); if ( oldContent["msgtype"] === newContent["msgtype"] && oldContent["body"] === newContent["body"] && - oldContent["format"] === newContent["format"] && - oldContent["formatted_body"] === newContent["formatted_body"] + (oldContent as RoomMessageTextEventContent)["format"] === + (newContent as RoomMessageTextEventContent)["format"] && + (oldContent as RoomMessageTextEventContent)["formatted_body"] === + (newContent as RoomMessageTextEventContent)["formatted_body"] ) { return false; } @@ -318,7 +325,7 @@ class EditMessageComposer extends React.Component
{isRenderingNotification && room ? ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/ExtraTile.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/ExtraTile.tsx index 157bfc4d56..3bb3a21525 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/ExtraTile.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/ExtraTile.tsx @@ -52,7 +52,7 @@ export default function ExtraTile({ let badge: JSX.Element | null = null; if (notificationState) { - badge = ; + badge = ; } let name = displayName; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MemberList.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MemberList.tsx index ec5a1af3f0..5126425ac5 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MemberList.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MemberList.tsx @@ -31,6 +31,7 @@ import { EventType, ClientEvent, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { throttle } from "lodash"; import { Button, Tooltip } from "@vector-im/compound-web"; import { Icon as UserAddIcon } from "@vector-im/compound-design-tokens/icons/user-add-solid.svg"; @@ -172,7 +173,11 @@ export default class MemberList extends React.Component { }; private onMyMembership = (room: Room, membership: string, oldMembership?: string): void => { - if (room.roomId === this.props.roomId && membership === "join" && oldMembership !== "join") { + if ( + room.roomId === this.props.roomId && + membership === KnownMembership.Join && + oldMembership !== KnownMembership.Join + ) { // we just joined the room, load the member list this.updateListNow(true); } @@ -364,7 +369,7 @@ export default class MemberList extends React.Component { const room = cli.getRoom(this.props.roomId); let inviteButton: JSX.Element | undefined; - if (room?.getMyMembership() === "join" && shouldShowComponent(UIComponent.InviteUsers)) { + if (room?.getMyMembership() === KnownMembership.Join && shouldShowComponent(UIComponent.InviteUsers)) { const inviteButtonText = room.isSpaceRoom() ? _t("space|invite_this_space") : _t("room|invite_this_room"); const button = ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MessageComposerButtons.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MessageComposerButtons.tsx index d9d364a211..7f23efbce2 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MessageComposerButtons.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/MessageComposerButtons.tsx @@ -24,7 +24,7 @@ import { CollapsibleButton } from "./CollapsibleButton"; import { MenuProps } from "../../structures/ContextMenu"; import dis from "../../../dispatcher/dispatcher"; import ErrorDialog from "../dialogs/ErrorDialog"; -import LocationButton from "../location/LocationButton"; +import { LocationButton } from "../location"; import Modal from "../../../Modal"; import PollCreateDialog from "../elements/PollCreateDialog"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NewRoomIntro.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NewRoomIntro.tsx index 4cc9028d48..70ea6c23a2 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NewRoomIntro.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NewRoomIntro.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { useContext } from "react"; import { EventType, Room, User, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; import RoomContext from "../../../contexts/RoomContext"; @@ -112,7 +113,7 @@ const NewRoomIntro: React.FC = () => { ); } else { - const inRoom = room && room.getMyMembership() === "join"; + const inRoom = room && room.getMyMembership() === KnownMembership.Join; const topic = room.currentState.getStateEvents(EventType.RoomTopic, "")?.getContent()?.topic; const canAddTopic = inRoom && room.currentState.maySendStateEvent(EventType.RoomTopic, cli.getSafeUserId()); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge.tsx index d152ab6a62..20ee53d95d 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge.tsx @@ -28,10 +28,10 @@ interface IProps { notification: NotificationState; /** - * If true, the badge will show a count if at all possible. This is typically - * used to override the user's preference for things like room sublists. + * If true, show nothing if the notification would only cause a dot to be shown rather than + * a badge. That is: only display badges and not dots. Default: false. */ - forceCount?: boolean; + hideIfDot?: boolean; /** * The room ID, if any, the badge represents. @@ -48,7 +48,7 @@ interface IClickableProps extends IProps, React.InputHTMLAttributes { } interface IState { - showCounts: boolean; // whether to show counts. Independent of props.forceCount + showCounts: boolean; // whether to show counts. } export default class NotificationBadge extends React.PureComponent, IState> { @@ -97,11 +97,12 @@ export default class NotificationBadge extends React.PureComponent = { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx index 69f756b3b7..825192b82c 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/StatelessNotificationBadge.tsx @@ -28,7 +28,12 @@ interface Props { count: number; level: NotificationLevel; knocked?: boolean; - type?: "badge" | "dot"; + /** + * If true, where we would normally show a badge, we instead show a dot. No numeric count will + * be displayed (but may affect whether the the dot is displayed). See class doc + * for the difference between the two. + */ + forceDot?: boolean; } interface ClickableProps extends Props { @@ -39,8 +44,17 @@ interface ClickableProps extends Props { tabIndex?: number; } +/** + * A notification indicator that conveys what activity / notifications the user has in whatever + * context it is being used. + * + * Can either be a 'badge': a small circle with a number in it (the 'count'), or a 'dot': a smaller, empty circle. + * The two can be used to convey the same meaning but in different contexts, for example: for unread + * notifications in the room list, it may have a green badge with the number of unread notifications, + * but somewhere else it may just have a green dot as a more compact representation of the same information. + */ export const StatelessNotificationBadge = forwardRef>( - ({ symbol, count, level, knocked, type = "badge", ...props }, ref) => { + ({ symbol, count, level, knocked, forceDot = false, ...props }, ref) => { const hideBold = useSettingValue("feature_hidebold"); // Don't show a badge if we don't need to @@ -56,15 +70,29 @@ export const StatelessNotificationBadge = forwardRef= NotificationLevel.Highlight, - mx_NotificationBadge_dot: (isEmptyBadge && !knocked) || type === "dot", - mx_NotificationBadge_knocked: knocked, - mx_NotificationBadge_2char: type === "badge" && symbol && symbol.length > 0 && symbol.length < 3, - mx_NotificationBadge_3char: type === "badge" && symbol && symbol.length > 2, + "mx_NotificationBadge": true, + "mx_NotificationBadge_visible": isEmptyBadge || knocked ? true : hasUnreadCount, + "mx_NotificationBadge_level_notification": level == NotificationLevel.Notification, + "mx_NotificationBadge_level_highlight": level >= NotificationLevel.Highlight, + "mx_NotificationBadge_knocked": knocked, + + // Exactly one of mx_NotificationBadge_dot, mx_NotificationBadge_2char, mx_NotificationBadge_3char + "mx_NotificationBadge_dot": badgeType === "dot", + "mx_NotificationBadge_2char": badgeType === "badge_2char", + "mx_NotificationBadge_3char": badgeType === "badge_3char", + // Badges with text should always use light colors + "cpd-theme-light": badgeType !== "dot", }); if (props.onClick) { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx index 5864a63be0..c3c8cf7df8 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/NotificationBadge/UnreadNotificationBadge.tsx @@ -23,11 +23,15 @@ import { StatelessNotificationBadge } from "./StatelessNotificationBadge"; interface Props { room?: Room; threadId?: string; - type?: "badge" | "dot"; + /** + * If true, where we would normally show a badge, we instead show a dot. No numeric count will + * be displayed. + */ + forceDot?: boolean; } -export function UnreadNotificationBadge({ room, threadId, type }: Props): JSX.Element { +export function UnreadNotificationBadge({ room, threadId, forceDot }: Props): JSX.Element { const { symbol, count, level } = useUnreadNotifications(room, threadId); - return ; + return ; } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomBreadcrumbs.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomBreadcrumbs.tsx index eca8da4624..cd31dbd8e7 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomBreadcrumbs.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomBreadcrumbs.tsx @@ -61,7 +61,7 @@ const RoomBreadcrumbTile: React.FC<{ room: Room; onClick: (ev: ButtonEvent) => v room={room} size="32px" displayBadge={true} - forceCount={true} + hideIfDot={true} tooltipProps={{ tabIndex: isActive ? 0 : -1 }} /> diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomHeader.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomHeader.tsx index 6099fb73ad..ad3bbfe558 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomHeader.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomHeader.tsx @@ -54,6 +54,7 @@ import { VideoRoomChatButton } from "./RoomHeader/VideoRoomChatButton"; import { RoomKnocksBar } from "./RoomKnocksBar"; import { isVideoRoom } from "../../../utils/video-rooms"; import { notificationLevelToIndicator } from "../../../utils/notifications"; +import { CallGuestLinkButton } from "./RoomHeader/CallGuestLinkButton"; import TchapUIFeature from "../../../../../../src/tchap/util/TchapUIFeature"; // :TCHAP: customize-room-header-bar import TchapExternalRoomHeader from "../../../../../../src/tchap/components/views/rooms/TchapExternalRoomHeader"; // :TCHAP: customize-room-header-bar @@ -205,7 +206,10 @@ export default function RoomHeader({ const voiceCallButton = ( voiceCallClick(ev, callOptions[0])} > @@ -327,6 +331,7 @@ export default function RoomHeader({ ); })} + {isViewingCall && } {((isConnectedToCall && isViewingCall) || isVideoRoom(room)) && } {hasActiveCallSession && !isConnectedToCall && !isViewingCall ? ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomHeader/CallGuestLinkButton.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomHeader/CallGuestLinkButton.tsx new file mode 100644 index 0000000000..c5efe10e0f --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomHeader/CallGuestLinkButton.tsx @@ -0,0 +1,166 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +import { Icon as ExternalLinkIcon } from "@vector-im/compound-design-tokens/icons/link.svg"; +import { Button, IconButton, Tooltip } from "@vector-im/compound-web"; +import React, { useCallback } from "react"; +import { logger } from "matrix-js-sdk/src/logger"; +import { EventType, IJoinRuleEventContent, JoinRule, Room } from "matrix-js-sdk/src/matrix"; + +import Modal from "../../../../Modal"; +import ShareDialog from "../../dialogs/ShareDialog"; +import { _t } from "../../../../languageHandler"; +import SettingsStore from "../../../../settings/SettingsStore"; +import { calculateRoomVia } from "../../../../utils/permalinks/Permalinks"; +import BaseDialog from "../../dialogs/BaseDialog"; +import { useGuestAccessInformation } from "../../../../hooks/room/useGuestAccessInformation"; + +/** + * Display a button to open a dialog to share a link to the call using a element call guest spa url (`element_call:guest_spa_url` in the EW config). + * @param room + * @returns Nothing if there is not the option to share a link (No guest_spa_url is set) or a button to open a dialog to share the link. + */ +export const CallGuestLinkButton: React.FC<{ room: Room }> = ({ room }) => { + const { canInviteGuests, guestSpaUrl, isRoomJoinable, canInvite } = useGuestAccessInformation(room); + + const generateCallLink = useCallback(() => { + if (!isRoomJoinable()) throw new Error("Cannot create link for room that users can not join without invite."); + if (!guestSpaUrl) throw new Error("No guest SPA url for external links provided."); + const url = new URL(guestSpaUrl); + url.pathname = "/room/"; + // Set params for the sharable url + url.searchParams.set("roomId", room.roomId); + if (room.hasEncryptionStateEvent()) url.searchParams.set("perParticipantE2EE", "true"); + for (const server of calculateRoomVia(room)) { + url.searchParams.set("viaServers", server); + } + + // Move params into hash + url.hash = "/" + room.name + url.search; + url.search = ""; + + logger.info("Generated element call external url:", url); + return url; + }, [guestSpaUrl, isRoomJoinable, room]); + + const showLinkModal = useCallback(() => { + try { + // generateCallLink throws if the invite rules are not met + const target = generateCallLink(); + Modal.createDialog(ShareDialog, { + target, + customTitle: _t("share|share_call"), + subtitle: _t("share|share_call_subtitle"), + }); + } catch (e) { + logger.error("Could not generate call link.", e); + } + }, [generateCallLink]); + + const shareClick = useCallback(() => { + if (isRoomJoinable()) { + showLinkModal(); + } else { + // the room needs to be set to public or knock to generate a link + Modal.createDialog(JoinRuleDialog, { + room, + // If the user cannot invite the Knocking is not given as an option. + canInvite, + }).finished.then(() => { + if (isRoomJoinable()) showLinkModal(); + }); + } + }, [isRoomJoinable, showLinkModal, room, canInvite]); + + return ( + <> + {canInviteGuests && ( + + + + + + )} + + ); +}; + +/** + * A dialog to change the join rule of a room to public or knock. + * @param room The room to change the join rule of. + * @param onFinished Callback that is getting called if the dialog wants to close. + */ +export const JoinRuleDialog: React.FC<{ + onFinished(): void; + room: Room; + canInvite: boolean; +}> = ({ onFinished, room, canInvite }) => { + const askToJoinEnabled = SettingsStore.getValue("feature_ask_to_join"); + const [isUpdating, setIsUpdating] = React.useState(undefined); + const changeJoinRule = useCallback( + async (newRule: JoinRule) => { + if (isUpdating !== undefined) return; + setIsUpdating(newRule); + await room.client.sendStateEvent( + room.roomId, + EventType.RoomJoinRules, + { + join_rule: newRule, + } as IJoinRuleEventContent, + "", + ); + // Show the dialog for a bit to give the user feedback + setTimeout(() => onFinished(), 500); + }, + [isUpdating, onFinished, room.client, room.roomId], + ); + return ( + +

{_t("update_room_access_modal|description")}

+
+ {askToJoinEnabled && canInvite && ( + + )} + +
+

{_t("update_room_access_modal|dont_change_description")}

+
+ +
+
+ ); +}; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomInfoLine.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomInfoLine.tsx index cca5e2adaf..b443ecfada 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomInfoLine.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomInfoLine.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { FC } from "react"; import { Room, JoinRule, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import RightPanelStore from "../../../stores/right-panel/RightPanelStore"; @@ -33,7 +34,7 @@ interface IProps { const RoomInfoLine: FC = ({ room }) => { // summary will begin as undefined whilst loading and go null if it fails to load or we are not invited. const summary = useAsyncMemo(async (): Promise> | null> => { - if (room.getMyMembership() !== "invite") return null; + if (room.getMyMembership() !== KnownMembership.Invite) return null; try { return await room.client.getRoomSummary(room.roomId); } catch (e) { @@ -61,7 +62,7 @@ const RoomInfoLine: FC = ({ room }) => { } let members: JSX.Element | undefined; - if (membership === "invite" && summary) { + if (membership === KnownMembership.Invite && summary) { // Don't trust local state and instead use the summary API members = ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomKnocksBar.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomKnocksBar.tsx index edac6d47a8..9feb23a147 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomKnocksBar.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomKnocksBar.tsx @@ -15,6 +15,7 @@ limitations under the License. */ import { EventTimeline, JoinRule, MatrixError, Room, RoomStateEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import React, { ReactElement, ReactNode, useCallback, useState, VFC } from "react"; import { Icon as CheckIcon } from "../../../../res/img/feather-customised/check.svg"; @@ -35,7 +36,7 @@ export const RoomKnocksBar: VFC<{ room: Room }> = ({ room }) => { const knockMembers = useTypedEventEmitterState( room, RoomStateEvent.Update, - useCallback(() => room.getMembersWithMembership("knock"), [room]), + useCallback(() => room.getMembersWithMembership(KnownMembership.Knock), [room]), ); const knockMembersCount = knockMembers.length; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomList.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomList.tsx index 40fe10f2be..6ddc5d8fb8 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomList.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomList.tsx @@ -85,6 +85,7 @@ export const TAG_ORDER: TagID[] = [ DefaultTagID.ServerNotice, // :TCHAP: tchap-annonces DefaultTagID.DM, DefaultTagID.Untagged, + DefaultTagID.Conference, DefaultTagID.LowPriority, DefaultTagID.Suggested, // DefaultTagID.Archived isn't here any more: we don't show it at all. @@ -387,6 +388,11 @@ const TAG_AESTHETICS: TagAestheticsMap = { defaultHidden: false, AuxButtonComponent: DmAuxButton, }, + [DefaultTagID.Conference]: { + sectionLabel: _td("voip|metaspace_video_rooms|conference_room_section"), + isInvite: false, + defaultHidden: false, + }, [DefaultTagID.Untagged]: { sectionLabel: _td("common|rooms"), isInvite: false, @@ -594,6 +600,7 @@ export default class RoomList extends React.PureComponent { (this.props.activeSpace === MetaSpace.Favourites && orderedTagId !== DefaultTagID.Favourite) || (this.props.activeSpace === MetaSpace.People && orderedTagId !== DefaultTagID.DM) || (this.props.activeSpace === MetaSpace.Orphans && orderedTagId === DefaultTagID.DM) || + (this.props.activeSpace === MetaSpace.VideoRooms && orderedTagId === DefaultTagID.DM) || (!isMetaSpace(this.props.activeSpace) && orderedTagId === DefaultTagID.DM && !SettingsStore.getValue("Spaces.showPeopleInSpace", this.props.activeSpace)) diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewBar.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewBar.tsx index e3b06e5b9f..bbb3154f12 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewBar.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewBar.tsx @@ -24,6 +24,7 @@ import { JoinRule, MatrixError, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import classNames from "classnames"; import { RoomPreviewOpts, RoomViewLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle"; @@ -192,13 +193,13 @@ export default class RoomPreviewBar extends React.Component { if (myMember) { const previousMembership = myMember.events.member?.getPrevContent().membership; if (myMember.isKicked()) { - if (previousMembership === "knock") { + if (previousMembership === KnownMembership.Knock) { return MessageCase.RequestDenied; } else if (this.props.promptAskToJoin) { return MessageCase.PromptAskToJoin; } return MessageCase.Kicked; - } else if (myMember.membership === "ban") { + } else if (myMember.membership === KnownMembership.Ban) { return MessageCase.Banned; } } @@ -284,7 +285,7 @@ export default class RoomPreviewBar extends React.Component { return false; } const memberContent = myMember.events.member?.getContent(); - return memberContent?.membership === "invite" && memberContent.is_direct; + return memberContent?.membership === KnownMembership.Invite && memberContent.is_direct; } private makeScreenAfterLogin(): { screen: string; params: Record } { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewCard.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewCard.tsx index 91893847d0..ee31206c38 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewCard.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomPreviewCard.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { FC, useContext, useState } from "react"; import { Room, JoinRule } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { _t } from "../../../languageHandler"; import defaultDispatcher from "../../../dispatcher/dispatcher"; @@ -73,7 +74,7 @@ const RoomPreviewCard: FC = ({ room, onJoinButtonClicked, onRejectButton let inviterSection: JSX.Element | null = null; let joinButtons: JSX.Element; - if (myMembership === "join") { + if (myMembership === KnownMembership.Join) { joinButtons = ( = ({ room, onJoinButtonClicked, onRejectButton {_t("action|leave")} ); - } else if (myMembership === "invite") { + } else if (myMembership === KnownMembership.Invite) { const inviteSender = room.getMember(cli.getUserId()!)?.events.member?.getSender(); if (inviteSender) { @@ -178,7 +179,7 @@ const RoomPreviewCard: FC = ({ room, onJoinButtonClicked, onRejectButton }); } else if (isVideoRoom && !videoRoomsEnabled) { notice = - myMembership === "join" + myMembership === KnownMembership.Join ? _t("room|view_failed_enable_video_rooms") : _t("room|join_failed_enable_video_rooms"); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomSublist.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomSublist.tsx index 4e84bee0be..c8ad9d4aca 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomSublist.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/RoomSublist.tsx @@ -657,7 +657,7 @@ export default class RoomSublist extends React.Component { const badge = ( { private get showContextMenu(): boolean { return ( this.props.tag !== DefaultTagID.Invite && - this.props.room.getMyMembership() !== "knock" && + this.props.room.getMyMembership() !== KnownMembership.Knock && !isKnockDenied(this.props.room) && shouldShowComponent(UIComponent.RoomOptionsMenu) ); @@ -362,6 +363,12 @@ export class RoomTile extends React.PureComponent { onPostLeaveClick={(ev: ButtonEvent) => PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuLeaveItem", ev) } + onPostMarkAsReadClick={(ev: ButtonEvent) => + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuMarkRead", ev) + } + onPostMarkAsUnreadClick={(ev: ButtonEvent) => + PosthogTrackers.trackInteraction("WebRoomListRoomTileContextMenuMarkUnread", ev) + } /> )} @@ -387,7 +394,7 @@ export class RoomTile extends React.PureComponent { mx_RoomTile: true, mx_RoomTile_sticky: SettingsStore.getValue("feature_ask_to_join") && - (this.props.room.getMyMembership() === "knock" || isKnockDenied(this.props.room)), + (this.props.room.getMyMembership() === KnownMembership.Knock || isKnockDenied(this.props.room)), mx_RoomTile_selected: this.state.selected, mx_RoomTile_hasMenuOpen: !!(this.state.generalMenuPosition || this.state.notificationsMenuPosition), mx_RoomTile_minimized: this.props.isMinimized, @@ -402,11 +409,7 @@ export class RoomTile extends React.PureComponent { // aria-hidden because we summarise the unread count/highlight status in a manual aria-label below badge = ( ); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/SendMessageComposer.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/SendMessageComposer.tsx index b371d81b72..0ea0bdf94c 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/SendMessageComposer.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/SendMessageComposer.tsx @@ -30,6 +30,7 @@ import { import { DebouncedFunc, throttle } from "lodash"; import { logger } from "matrix-js-sdk/src/logger"; import { Composer as ComposerEvent } from "@matrix-org/analytics-events/types/typescript/Composer"; +import { RoomMessageEventContent } from "matrix-js-sdk/src/types"; import dis from "../../../dispatcher/dispatcher"; import EditorModel from "../../../editor/model"; @@ -183,7 +184,7 @@ export function createMessageContent( relation: IEventRelation | undefined, permalinkCreator?: RoomPermalinkCreator, includeReplyLegacyFallback = true, -): IContent { +): RoomMessageEventContent { const isEmote = containsEmote(model); if (isEmote) { model = stripEmoteCommand(model); @@ -195,7 +196,7 @@ export function createMessageContent( const body = textSerialize(model); - const content: IContent = { + const content: RoomMessageEventContent = { msgtype: isEmote ? MsgType.Emote : MsgType.Text, body: body, }; @@ -432,7 +433,7 @@ export class SendMessageComposer extends React.Component { MatrixClientPeg.safeGet() - .sendStateEvent(this.state.roomId, "m.room.third_party_invite", {}, this.state.stateKey) + .sendStateEvent(this.state.roomId, EventType.RoomThirdPartyInvite, {}, this.state.stateKey) .catch((err) => { logger.error(err); diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts index 58a4795c2a..6b056c9155 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/createMessageContent.ts @@ -16,6 +16,7 @@ limitations under the License. import { richToPlain, plainToRich } from "@matrix-org/matrix-wysiwyg"; import { IContent, IEventRelation, MatrixEvent, MsgType } from "matrix-js-sdk/src/matrix"; +import { ReplacementEvent, RoomMessageEventContent, RoomMessageTextEventContent } from "matrix-js-sdk/src/types"; import SettingsStore from "../../../../../settings/SettingsStore"; import { parsePermalink, RoomPermalinkCreator } from "../../../../../utils/permalinks/Permalinks"; @@ -76,7 +77,7 @@ export async function createMessageContent( includeReplyLegacyFallback = true, editedEvent, }: CreateMessageContentParams, -): Promise { +): Promise { const isEditing = isMatrixEvent(editedEvent); const isReply = isEditing ? Boolean(editedEvent.replyEventId) : isMatrixEvent(replyToEvent); const isReplyAndEditing = isEditing && isReply; @@ -100,10 +101,10 @@ export async function createMessageContent( const bodyPrefix = (isReplyAndEditing && getTextReplyFallback(editedEvent)) || ""; const formattedBodyPrefix = (isReplyAndEditing && getHtmlReplyFallback(editedEvent)) || ""; - const content: IContent = { + const content = { msgtype: isEmote ? MsgType.Emote : MsgType.Text, body: isEditing ? `${bodyPrefix} * ${body}` : body, - }; + } as RoomMessageTextEventContent & ReplacementEvent; // TODO markdown support diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/isContentModified.ts b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/isContentModified.ts index 0def386278..62af83b826 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/isContentModified.ts +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/isContentModified.ts @@ -14,18 +14,22 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { IContent } from "matrix-js-sdk/src/matrix"; +import { RoomMessageEventContent, RoomMessageTextEventContent } from "matrix-js-sdk/src/types"; import EditorStateTransfer from "../../../../../utils/EditorStateTransfer"; -export function isContentModified(newContent: IContent, editorStateTransfer: EditorStateTransfer): boolean { +export function isContentModified( + newContent: RoomMessageEventContent, + editorStateTransfer: EditorStateTransfer, +): boolean { // if nothing has changed then bail - const oldContent = editorStateTransfer.getEvent().getContent(); + const oldContent = editorStateTransfer.getEvent().getContent(); if ( oldContent["msgtype"] === newContent["msgtype"] && oldContent["body"] === newContent["body"] && - oldContent["format"] === newContent["format"] && - oldContent["formatted_body"] === newContent["formatted_body"] + (oldContent)["format"] === (newContent)["format"] && + (oldContent)["formatted_body"] === + (newContent)["formatted_body"] ) { return false; } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/message.ts b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/message.ts index a3c625048b..3122a9d2ef 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/message.ts +++ b/linked-dependencies/matrix-react-sdk/src/components/views/rooms/wysiwyg_composer/utils/message.ts @@ -16,13 +16,13 @@ limitations under the License. import { Composer as ComposerEvent } from "@matrix-org/analytics-events/types/typescript/Composer"; import { - IContent, IEventRelation, MatrixEvent, ISendEventResponse, MatrixClient, THREAD_RELATION_TYPE, } from "matrix-js-sdk/src/matrix"; +import { RoomMessageEventContent } from "matrix-js-sdk/src/types"; import { PosthogAnalytics } from "../../../../../PosthogAnalytics"; import SettingsStore from "../../../../../settings/SettingsStore"; @@ -82,7 +82,7 @@ export async function sendMessage( }*/ PosthogAnalytics.instance.trackEvent(posthogEvent); - let content: IContent | null = null; + let content: RoomMessageEventContent | null = null; // Slash command handling here approximates what can be found in SendMessageComposer.sendMessage() // but note that the /me and // special cases are handled by the call to createMessageContent @@ -145,7 +145,7 @@ export async function sendMessage( const prom = doMaybeLocalRoomAction( roomId, - (actualRoomId: string) => mxClient.sendMessage(actualRoomId, threadId, content as IContent), + (actualRoomId: string) => mxClient.sendMessage(actualRoomId, threadId, content!), mxClient, ); @@ -218,7 +218,7 @@ export async function editMessage( this.editorRef.current?.replaceEmoticon(position, REGEX_EMOTICON); }*/ const editContent = await createMessageContent(html, true, { editedEvent }); - const newContent = editContent["m.new_content"]; + const newContent = editContent["m.new_content"]!; const shouldSend = true; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/AddPrivilegedUsers.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/AddPrivilegedUsers.tsx index d8d2659371..5bcaecd469 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/AddPrivilegedUsers.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/AddPrivilegedUsers.tsx @@ -62,7 +62,7 @@ export const AddPrivilegedUsers: React.FC = ({ room, de } try { - await client.setPowerLevel(room.roomId, userIds, powerLevel, powerLevelEvent); + await client.setPowerLevel(room.roomId, userIds, powerLevel); setSelectedUsers([]); setPowerLevel(defaultUserLevel); } catch (error) { diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/Notifications.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/Notifications.tsx index ef3c4dc74a..693664339f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/Notifications.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/Notifications.tsx @@ -58,6 +58,7 @@ import { Caption } from "../typography/Caption"; import { SettingsSubsectionHeading } from "./shared/SettingsSubsectionHeading"; import SettingsSubsection from "./shared/SettingsSubsection"; import { doesRoomHaveUnreadMessages } from "../../../Unread"; +import SettingsFlag from "../elements/SettingsFlag"; import TchapUIFeature from "../../../../../../src/tchap/util/TchapUIFeature"; // :tchap: tchap-features-from-config @@ -202,6 +203,18 @@ const maximumVectorState = ( return vectorState; }; +const NotificationActivitySettings = (): JSX.Element => { + return ( +
+ + +
+ ); +}; + +/** + * The old, deprecated notifications tab view, only displayed if the user has the labs flag disabled. + */ export default class Notifications extends React.PureComponent { private settingWatchers: string[]; @@ -737,43 +750,10 @@ export default class Notifications extends React.PureComponent { } private renderCategory(category: RuleClass): ReactNode { - if (category !== RuleClass.VectorOther && this.isInhibited) { + if (this.isInhibited) { return null; // nothing to show for the section } - let clearNotifsButton: JSX.Element | undefined; - if ( - category === RuleClass.VectorOther && - MatrixClientPeg.safeGet() - .getRooms() - .some((r) => doesRoomHaveUnreadMessages(r, true)) - ) { - clearNotifsButton = ( - - {_t("notifications|mark_all_read")} - - ); - } - - if (category === RuleClass.VectorOther && this.isInhibited) { - // only render the utility buttons (if needed) - if (clearNotifsButton) { - return ( -
-
{_t("notifications|class_other")}
- {clearNotifsButton} -
- ); - } - return null; - } - let keywordComposer: JSX.Element | undefined; if (category === RuleClass.VectorMentions) { const tags = filterBoolean(this.state.vectorKeywordRuleInfo?.rules.map((r) => r.pattern) || []); @@ -848,7 +828,6 @@ export default class Notifications extends React.PureComponent { {VectorStateToLabel[VectorState.Loud]} {fieldsetRows}
- {clearNotifsButton} {keywordComposer}
); @@ -884,6 +863,25 @@ export default class Notifications extends React.PureComponent { return

{_t("settings|notifications|error_loading")}

; } + let clearNotifsButton: JSX.Element | undefined; + if ( + MatrixClientPeg.safeGet() + .getRooms() + .some((r) => doesRoomHaveUnreadMessages(r, true)) + ) { + clearNotifsButton = ( + + {_t("notifications|mark_all_read")} + + ); + } + return ( <> {this.renderTopSection()} @@ -891,6 +889,8 @@ export default class Notifications extends React.PureComponent { {this.renderCategory(RuleClass.VectorMentions)} {this.renderCategory(RuleClass.VectorOther)} {this.renderTargets()} + + {clearNotifsButton} ); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/PowerLevelSelector.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/PowerLevelSelector.tsx new file mode 100644 index 0000000000..5d823c885d --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/PowerLevelSelector.tsx @@ -0,0 +1,142 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import React, { useState, JSX, PropsWithChildren } from "react"; +import { Button } from "@vector-im/compound-web"; +import { compare } from "matrix-js-sdk/src/utils"; + +import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; +import PowerSelector from "../elements/PowerSelector"; +import { _t } from "../../../languageHandler"; +import SettingsFieldset from "./SettingsFieldset"; + +/** + * Display in a fieldset, the power level of the users and allow to change them. + * The apply button is disabled until the power level of an user is changed. + * If there is no user to display, the children is displayed instead. + */ +interface PowerLevelSelectorProps { + /** + * The power levels of the users + * The key is the user id and the value is the power level + */ + userLevels: Record; + /** + * Whether the user can change the power levels of other users + */ + canChangeLevels: boolean; + /** + * The current user power level + */ + currentUserLevel: number; + /** + * The callback when the apply button is clicked + * @param value - new power level for the user + * @param userId - the user id + */ + onClick: (value: number, userId: string) => void; + /** + * Filter the users to display + * @param user + */ + filter: (user: string) => boolean; + /** + * The title of the fieldset + */ + title: string; +} + +export function PowerLevelSelector({ + userLevels, + canChangeLevels, + currentUserLevel, + onClick, + filter, + title, + children, +}: PropsWithChildren): JSX.Element | null { + const matrixClient = useMatrixClientContext(); + const [currentPowerLevel, setCurrentPowerLevel] = useState<{ value: number; userId: string } | null>(null); + + // If the power level has changed, we need to enable the apply button + const powerLevelChanged = Boolean( + currentPowerLevel && currentPowerLevel.value !== userLevels[currentPowerLevel?.userId], + ); + + // We sort the users by power level, then we filter them + const users = Object.keys(userLevels) + .sort((userA, userB) => sortUser(userA, userB, userLevels)) + .filter(filter); + + // No user to display, we return the children into fragment to convert it to JSX.Element type + if (!users.length) return <>{children}; + + return ( + + {users.map((userId) => { + // We only want to display users with a valid power level aka an integer + if (!Number.isInteger(userLevels[userId])) return; + + const isMe = userId === matrixClient.getUserId(); + // If I can change levels, I can change the level of anyone with a lower level than mine + const canChange = canChangeLevels && (userLevels[userId] < currentUserLevel || isMe); + + // When the new power level is selected, the fields are rerendered and we need to keep the current value + const userLevel = currentPowerLevel?.userId === userId ? currentPowerLevel?.value : userLevels[userId]; + + return ( + setCurrentPowerLevel({ value, userId })} + /> + ); + })} + + + + ); +} + +/** + * Sort the users by power level, then by name + * @param userA + * @param userB + * @param userLevels + */ +function sortUser(userA: string, userB: string, userLevels: PowerLevelSelectorProps["userLevels"]): number { + const powerLevelDiff = userLevels[userA] - userLevels[userB]; + return powerLevelDiff !== 0 ? powerLevelDiff : compare(userA.toLocaleLowerCase(), userB.toLocaleLowerCase()); +} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/SetIdServer.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/SetIdServer.tsx index bdf4ee837e..bd75204e74 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/SetIdServer.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/SetIdServer.tsx @@ -137,7 +137,7 @@ export default class SetIdServer extends React.Component {
); } else if (this.state.error) { - return {this.state.error}; + return {this.state.error}; } else { return null; } @@ -226,7 +226,7 @@ export default class SetIdServer extends React.Component { title: _t("terms|identity_server_no_terms_title"), description: (
- {_t("identity_server|no_terms")} + {_t("identity_server|no_terms")}  {_t("terms|identity_server_no_terms_description_2")}
), diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/SpellCheckSettings.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/SpellCheckSettings.tsx index a7c9cd9e2d..58737773ea 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/SpellCheckSettings.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/SpellCheckSettings.tsx @@ -18,10 +18,14 @@ import React from "react"; import SpellCheckLanguagesDropdown from "../../../components/views/elements/SpellCheckLanguagesDropdown"; import AccessibleButton, { ButtonEvent } from "../../../components/views/elements/AccessibleButton"; -import { _t } from "../../../languageHandler"; +import { _t, getUserLanguage } from "../../../languageHandler"; interface ExistingSpellCheckLanguageIProps { language: string; + /** + * The label to render on the component. If not provided, the language code will be used. + */ + label?: string; onRemoved(language: string): void; } @@ -45,7 +49,9 @@ export class ExistingSpellCheckLanguage extends React.Component - {this.props.language} + + {this.props.label ?? this.props.language} + {_t("action|remove")} @@ -87,8 +93,9 @@ export default class SpellCheckLanguages extends React.Component { - return ; + return ; }); const addButton = ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/account/PhoneNumbers.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/account/PhoneNumbers.tsx index 27c2bdf104..b037643bc0 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/account/PhoneNumbers.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/account/PhoneNumbers.tsx @@ -16,7 +16,7 @@ limitations under the License. */ import React from "react"; -import { ThreepidMedium } from "matrix-js-sdk/src/matrix"; +import { IAuthData, ThreepidMedium } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { _t, UserFriendlyError } from "../../../../languageHandler"; @@ -216,7 +216,7 @@ export default class PhoneNumbers extends React.Component { const address = this.state.verifyMsisdn; this.state.addTask ?.haveMsisdnToken(token) - .then(([finished] = []) => { + .then(([finished]: [success?: boolean, result?: IAuthData | Error | null] = []) => { let newPhoneNumber = this.state.newPhoneNumber; if (finished !== false) { const msisdns = [...this.props.msisdns, { address, medium: ThreepidMedium.Phone }]; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/LoginWithQRSection.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/LoginWithQRSection.tsx index 036597cfe9..c85b80c3a7 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/LoginWithQRSection.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/LoginWithQRSection.tsx @@ -22,6 +22,7 @@ import { Capabilities, IClientWellKnown, } from "matrix-js-sdk/src/matrix"; +import { Icon as QrCodeIcon } from "@vector-im/compound-design-tokens/icons/qr-code.svg"; import { _t } from "../../../../languageHandler"; import AccessibleButton from "../../elements/AccessibleButton"; @@ -62,6 +63,7 @@ export default class LoginWithQRSection extends React.Component { {_t("settings|sessions|sign_in_with_qr_description")}

+ {_t("settings|sessions|sign_in_with_qr_button")}
diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/deleteDevices.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/deleteDevices.tsx index c07757f7a9..e42dbe10b9 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/deleteDevices.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/deleteDevices.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import { MatrixClient, MatrixError } from "matrix-js-sdk/src/matrix"; -import { IAuthDict, IAuthData } from "matrix-js-sdk/src/interactive-auth"; +import { AuthDict, IAuthData } from "matrix-js-sdk/src/interactive-auth"; import { _t } from "../../../../languageHandler"; import Modal from "../../../../Modal"; @@ -25,7 +25,7 @@ import InteractiveAuthDialog from "../../dialogs/InteractiveAuthDialog"; const makeDeleteRequest = (matrixClient: MatrixClient, deviceIds: string[]) => - async (auth: IAuthDict | null): Promise => { + async (auth: AuthDict | null): Promise => { return matrixClient.deleteMultipleDevices(deviceIds, auth ?? undefined); }; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/useOwnDevices.ts b/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/useOwnDevices.ts index c735b2cbce..f0cec2777a 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/useOwnDevices.ts +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/devices/useOwnDevices.ts @@ -77,6 +77,7 @@ export enum OwnDevicesError { } export type DevicesState = { devices: DevicesDictionary; + dehydratedDeviceId?: string; pushers: IPusher[]; localNotificationSettings: Map; currentDeviceId: string; @@ -97,6 +98,7 @@ export const useOwnDevices = (): DevicesState => { const userId = matrixClient.getSafeUserId(); const [devices, setDevices] = useState({}); + const [dehydratedDeviceId, setDehydratedDeviceId] = useState(undefined); const [pushers, setPushers] = useState([]); const [localNotificationSettings, setLocalNotificationSettings] = useState< DevicesState["localNotificationSettings"] @@ -131,6 +133,21 @@ export const useOwnDevices = (): DevicesState => { }); setLocalNotificationSettings(notificationSettings); + const ownUserId = matrixClient.getUserId()!; + const userDevices = (await matrixClient.getCrypto()?.getUserDeviceInfo([ownUserId]))?.get(ownUserId); + const dehydratedDeviceIds: string[] = []; + for (const device of userDevices?.values() ?? []) { + if (device.dehydrated) { + dehydratedDeviceIds.push(device.deviceId); + } + } + // If the user has exactly one device marked as dehydrated, we consider + // that as the dehydrated device, and hide it as a normal device (but + // indicate that the user is using a dehydrated device). If the user has + // more than one, that is anomalous, and we show all the devices so that + // nothing is hidden. + setDehydratedDeviceId(dehydratedDeviceIds.length == 1 ? dehydratedDeviceIds[0] : undefined); + setIsLoadingDeviceList(false); } catch (error) { if ((error as MatrixError).httpStatus == 404) { @@ -228,6 +245,7 @@ export const useOwnDevices = (): DevicesState => { return { devices, + dehydratedDeviceId, pushers, localNotificationSettings, currentDeviceId, diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/notifications/NotificationSettings2.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/notifications/NotificationSettings2.tsx index bdc021e486..a15fdd1d8b 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/notifications/NotificationSettings2.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/notifications/NotificationSettings2.tsx @@ -41,6 +41,7 @@ import { SettingsBanner } from "../shared/SettingsBanner"; import { SettingsSection } from "../shared/SettingsSection"; import SettingsSubsection from "../shared/SettingsSubsection"; import { NotificationPusherSettings } from "./NotificationPusherSettings"; +import SettingsFlag from "../../elements/SettingsFlag"; enum NotificationDefaultLevels { AllMessages = "all_messages", @@ -71,6 +72,9 @@ function useHasUnreadNotifications(): boolean { return cli.getRooms().some((room) => room.getUnreadNotificationCount() > 0); } +/** + * The new notification settings tab view, only displayed if the user has Features.NotificationSettings2 enabled + */ export default function NotificationSettings2(): JSX.Element { const cli = useMatrixClientContext(); @@ -352,6 +356,9 @@ export default function NotificationSettings2(): JSX.Element { label={_t("notifications|keyword")} placeholder={_t("notifications|keyword_new")} /> + + + diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx index b35914a467..828056dfec 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/GeneralRoomSettingsTab.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { ContextType } from "react"; import { Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { _t } from "../../../../../languageHandler"; import RoomProfileSettings from "../../../room_settings/RoomProfileSettings"; @@ -73,7 +74,7 @@ export default class GeneralRoomSettingsTab extends React.Component diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx index 418addfaf9..22c2bc471f 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/PeopleRoomSettingsTab.tsx @@ -15,6 +15,7 @@ limitations under the License. */ import { EventTimeline, MatrixError, Room, RoomMember, RoomStateEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import React, { useCallback, useState, VFC } from "react"; import { Icon as CheckIcon } from "../../../../../../res/img/feather-customised/check.svg"; @@ -145,7 +146,7 @@ export const PeopleRoomSettingsTab: VFC<{ room: Room }> = ({ room }) => { const knockMembers = useTypedEventEmitterState( room, RoomStateEvent.Update, - useCallback(() => room.getMembersWithMembership("knock"), [room]), + useCallback(() => room.getMembersWithMembership(KnownMembership.Knock), [room]), ); return ( diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx index 7bce2ccb17..2197cad3df 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/room/RolesRoomSettingsTab.tsx @@ -18,7 +18,7 @@ import React from "react"; import { EventType, RoomMember, RoomState, RoomStateEvent, Room, IContent } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { throttle, get } from "lodash"; -import { compare } from "matrix-js-sdk/src/utils"; +import { KnownMembership, RoomPowerLevelsEventContent } from "matrix-js-sdk/src/types"; import { _t, _td, TranslationKey } from "../../../../../languageHandler"; import AccessibleButton from "../../../elements/AccessibleButton"; @@ -34,6 +34,7 @@ import { AddPrivilegedUsers } from "../../AddPrivilegedUsers"; import SettingsTab from "../SettingsTab"; import { SettingsSection } from "../../shared/SettingsSection"; import MatrixClientContext from "../../../../../contexts/MatrixClientContext"; +import { PowerLevelSelector } from "../../PowerLevelSelector"; interface IEventShowOpts { isState?: boolean; @@ -174,11 +175,11 @@ export default class RolesRoomSettingsTab extends React.Component { } } - private onPowerLevelsChanged = (value: number, powerLevelKey: string): void => { + private onPowerLevelsChanged = async (value: number, powerLevelKey: string): Promise => { const client = this.context; const room = this.props.room; const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, ""); - let plContent = plEvent?.getContent() ?? {}; + let plContent = plEvent?.getContent() ?? {}; // Clone the power levels just in case plContent = Object.assign({}, plContent); @@ -192,7 +193,7 @@ export default class RolesRoomSettingsTab extends React.Component { } else { const keyPath = powerLevelKey.split("."); let parentObj: IContent = {}; - let currentObj = plContent; + let currentObj: IContent = plContent; for (const key of keyPath) { if (!currentObj[key]) { currentObj[key] = {}; @@ -203,21 +204,26 @@ export default class RolesRoomSettingsTab extends React.Component { parentObj[keyPath[keyPath.length - 1]] = value; } - client.sendStateEvent(this.props.room.roomId, EventType.RoomPowerLevels, plContent).catch((e) => { + try { + await client.sendStateEvent(this.props.room.roomId, EventType.RoomPowerLevels, plContent); + } catch (e) { logger.error(e); Modal.createDialog(ErrorDialog, { title: _t("room_settings|permissions|error_changing_pl_reqs_title"), description: _t("room_settings|permissions|error_changing_pl_reqs_description"), }); - }); + + // Rethrow so that the PowerSelector can roll back + throw e; + } }; - private onUserPowerLevelChanged = (value: number, powerLevelKey: string): void => { + private onUserPowerLevelChanged = async (value: number, powerLevelKey: string): Promise => { const client = this.context; const room = this.props.room; const plEvent = room.currentState.getStateEvents(EventType.RoomPowerLevels, ""); - let plContent = plEvent?.getContent() ?? {}; + let plContent = plEvent?.getContent() ?? {}; // Clone the power levels just in case plContent = Object.assign({}, plContent); @@ -226,14 +232,16 @@ export default class RolesRoomSettingsTab extends React.Component { if (!plContent["users"]) plContent["users"] = {}; plContent["users"][powerLevelKey] = value; - client.sendStateEvent(this.props.room.roomId, EventType.RoomPowerLevels, plContent).catch((e) => { + try { + await client.sendStateEvent(this.props.room.roomId, EventType.RoomPowerLevels, plContent); + } catch (e) { logger.error(e); Modal.createDialog(ErrorDialog, { title: _t("room_settings|permissions|error_changing_pl_title"), description: _t("room_settings|permissions|error_changing_pl_description"), }); - }); + } }; public render(): React.ReactNode { @@ -342,68 +350,32 @@ export default class RolesRoomSettingsTab extends React.Component { let privilegedUsersSection =
{_t("room_settings|permissions|no_privileged_users")}
; let mutedUsersSection; if (Object.keys(userLevels).length) { - const privilegedUsers: JSX.Element[] = []; - const mutedUsers: JSX.Element[] = []; - - Object.keys(userLevels).forEach((user) => { - if (!Number.isInteger(userLevels[user])) return; - const isMe = user === client.getUserId(); - const canChange = canChangeLevels && (userLevels[user] < currentUserLevel || isMe); - if (userLevels[user] > defaultUserLevel) { - // privileged - privilegedUsers.push( - , - ); - } else if (userLevels[user] < defaultUserLevel) { - // muted - mutedUsers.push( - , - ); - } - }); + privilegedUsersSection = ( + userLevels[user] > defaultUserLevel} + > +
{_t("room_settings|permissions|no_privileged_users")}
+
+ ); - // comparator for sorting PL users lexicographically on PL descending, MXID ascending. (case-insensitive) - const comparator = (a: JSX.Element, b: JSX.Element): number => { - const aKey = a.key as string; - const bKey = b.key as string; - const plDiff = userLevels[bKey] - userLevels[aKey]; - return plDiff !== 0 ? plDiff : compare(aKey.toLocaleLowerCase(), bKey.toLocaleLowerCase()); - }; - - privilegedUsers.sort(comparator); - mutedUsers.sort(comparator); - - if (privilegedUsers.length) { - privilegedUsersSection = ( - - {privilegedUsers} - - ); - } - if (mutedUsers.length) { - mutedUsersSection = ( - - {mutedUsers} - - ); - } + mutedUsersSection = ( + userLevels[user] < defaultUserLevel} + /> + ); } - const banned = room.getMembersWithMembership("ban"); + const banned = room.getMembersWithMembership(KnownMembership.Ban); let bannedUsersSection: JSX.Element | undefined; if (banned?.length) { const canBanUsers = currentUserLevel >= banLevel; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx index 0b34532218..7ec29d4366 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/MjolnirUserSettingsTab.tsx @@ -256,7 +256,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState> - {_t("labs_mjolnir|advanced_warning")} + {_t("labs_mjolnir|advanced_warning")}

{_t("labs_mjolnir|explainer_1", { brand }, { code: (s) => {s} })}

{_t("labs_mjolnir|explainer_2")}

@@ -289,7 +289,7 @@ export default class MjolnirUserSettingsTab extends React.Component<{}, IState> heading={_t("labs_mjolnir|lists_heading")} description={ <> - {_t("labs_mjolnir|lists_description_1")} + {_t("labs_mjolnir|lists_description_1")}   {_t("labs_mjolnir|lists_description_2")} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index bb477838be..47b046c5fb 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -17,6 +17,7 @@ limitations under the License. import React, { ReactNode } from "react"; import { sleep } from "matrix-js-sdk/src/utils"; import { Room, RoomEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership, Membership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../../../languageHandler"; @@ -41,6 +42,7 @@ import type { IServerVersions } from "matrix-js-sdk/src/matrix"; import SettingsTab from "../SettingsTab"; import { SettingsSection } from "../../shared/SettingsSection"; import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection"; +import { useOwnDevices } from "../../devices/useOwnDevices"; interface IIgnoredUserProps { userId: string; @@ -48,6 +50,23 @@ interface IIgnoredUserProps { inProgress: boolean; } +const DehydratedDeviceStatus: React.FC = () => { + const { dehydratedDeviceId } = useOwnDevices(); + + if (dehydratedDeviceId) { + return ( +
+
{_t("settings|security|dehydrated_device_enabled")}
+
+ {_t("settings|security|dehydrated_device_description")} +
+
+ ); + } else { + return null; + } +}; + export class IgnoredUser extends React.Component { private onUnignoreClicked = (): void => { this.props.onUnignored(this.props.userId); @@ -121,12 +140,12 @@ export default class SecurityUserSettingsTab extends React.Component { + private onMyMembership = (room: Room, membership: Membership): void => { if (room.isSpaceRoom()) { return; } - if (membership === "invite") { + if (membership === KnownMembership.Invite) { this.addInvitedRoom(room); } else if (this.state.invitedRoomIds.has(room.roomId)) { // The user isn't invited anymore @@ -167,7 +186,7 @@ export default class SecurityUserSettingsTab extends React.Component { - return r.hasMembershipState(MatrixClientPeg.safeGet().getUserId()!, "invite"); + return r.hasMembershipState(MatrixClientPeg.safeGet().getUserId()!, KnownMembership.Invite); }); }; @@ -285,6 +304,7 @@ export default class SecurityUserSettingsTab extends React.Component +
); */ diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SessionManagerTab.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SessionManagerTab.tsx index fc215f069a..61c8e85f8d 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SessionManagerTab.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SessionManagerTab.tsx @@ -150,6 +150,7 @@ const useSignOut = ( const SessionManagerTab: React.FC = () => { const { devices, + dehydratedDeviceId, pushers, localNotificationSettings, currentDeviceId, @@ -208,6 +209,9 @@ const SessionManagerTab: React.FC = () => { }; const { [currentDeviceId]: currentDevice, ...otherDevices } = devices; + if (dehydratedDeviceId && otherDevices[dehydratedDeviceId]?.isVerified) { + delete otherDevices[dehydratedDeviceId]; + } const otherSessionsCount = Object.keys(otherDevices).length; const shouldShowOtherSessions = otherSessionsCount > 0; diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SidebarUserSettingsTab.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SidebarUserSettingsTab.tsx index 27e75aca3e..a000e208eb 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SidebarUserSettingsTab.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/settings/tabs/user/SidebarUserSettingsTab.tsx @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ChangeEvent } from "react"; +import React, { ChangeEvent, useMemo } from "react"; +import { Icon as CameraCircle } from "@vector-im/compound-design-tokens/icons/video-call-solid.svg"; import { Icon as HomeIcon } from "../../../../../../res/img/element-icons/home.svg"; import { Icon as FavoriteIcon } from "../../../../../../res/img/element-icons/roomlist/favorite.svg"; @@ -30,6 +31,7 @@ import PosthogTrackers from "../../../../../PosthogTrackers"; import SettingsTab from "../SettingsTab"; import { SettingsSection } from "../../shared/SettingsSection"; import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection"; +import SdkConfig from "../../../../../SdkConfig"; type InteractionName = "WebSettingsSidebarTabSpacesCheckbox" | "WebQuickSettingsPinToSidebarCheckbox"; @@ -44,7 +46,14 @@ export const onMetaSpaceChangeFactory = PosthogTrackers.trackInteraction( interactionName, e, - [MetaSpace.Home, null, MetaSpace.Favourites, MetaSpace.People, MetaSpace.Orphans].indexOf(metaSpace), + [ + MetaSpace.Home, + null, + MetaSpace.Favourites, + MetaSpace.People, + MetaSpace.Orphans, + MetaSpace.VideoRooms, + ].indexOf(metaSpace), ); }; @@ -54,8 +63,15 @@ const SidebarUserSettingsTab: React.FC = () => { [MetaSpace.Favourites]: favouritesEnabled, [MetaSpace.People]: peopleEnabled, [MetaSpace.Orphans]: orphansEnabled, + [MetaSpace.VideoRooms]: videoRoomsEnabled, } = useSettingValue>("Spaces.enabledMetaSpaces"); const allRoomsInHome = useSettingValue("Spaces.allRoomsInHome"); + const guestSpaUrl = useMemo(() => { + return SdkConfig.get("element_call").guest_spa_url; + }, []); + const conferenceSubsectionText = + _t("settings|sidebar|metaspaces_video_rooms_description") + + (guestSpaUrl ? " " + _t("settings|sidebar|metaspaces_video_rooms_description_invite_extension") : ""); const onAllRoomsInHomeToggle = async (event: ChangeEvent): Promise => { await SettingsStore.setValue("Spaces.allRoomsInHome", null, SettingLevel.ACCOUNT, event.target.checked); @@ -140,6 +156,22 @@ const SidebarUserSettingsTab: React.FC = () => { {_t("settings|sidebar|metaspaces_orphans_description")} + {SettingsStore.getValue("feature_video_rooms") && ( + + + + {_t("settings|sidebar|metaspaces_video_rooms")} + + {conferenceSubsectionText} + + )} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/SpacePanel.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/SpacePanel.tsx index 5b1756244b..429a18e134 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/SpacePanel.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/SpacePanel.tsx @@ -209,6 +209,20 @@ const OrphansButton: React.FC = ({ selected, isPanelCollap ); }; +const VideoRoomsButton: React.FC = ({ selected, isPanelCollapsed }) => { + return ( + + ); +}; + const CreateSpaceButton: React.FC> = ({ isPanelCollapsed, setPanelCollapsed, @@ -263,6 +277,7 @@ const metaSpaceComponentMap: Record = { [MetaSpace.Favourites]: FavouritesButton, [MetaSpace.People]: PeopleButton, [MetaSpace.Orphans]: OrphansButton, + [MetaSpace.VideoRooms]: VideoRoomsButton, }; interface IInnerSpacePanelProps extends DroppableProvidedProps { @@ -279,10 +294,12 @@ const InnerSpacePanel = React.memo( const [invites, metaSpaces, actualSpaces, activeSpace] = useSpaces(); const activeSpaces = activeSpace ? [activeSpace] : []; - const metaSpacesSection = metaSpaces.map((key) => { - const Component = metaSpaceComponentMap[key]; - return ; - }); + const metaSpacesSection = metaSpaces + .filter((key) => !(key === MetaSpace.VideoRooms && !SettingsStore.getValue("feature_video_rooms"))) + .map((key) => { + const Component = metaSpaceComponentMap[key]; + return ; + }); return ( ({ let notifBadge; if (spaceKey && notificationState) { let ariaLabel = _t("a11y_jump_first_unread_room"); - if (space?.getMyMembership() === "invite") { + if (space?.getMyMembership() === KnownMembership.Invite) { ariaLabel = _t("a11y|jump_first_invite"); } @@ -113,7 +114,6 @@ export const SpaceButton = ({
{ hasSubSpaces: this.state.childSpaces?.length, }); - const isInvite = space.getMyMembership() === "invite"; + const isInvite = space.getMyMembership() === KnownMembership.Invite; const notificationState = isInvite ? StaticNotificationState.forSymbol("!", NotificationLevel.Highlight) @@ -379,7 +379,9 @@ export class SpaceItem extends React.PureComponent { isNarrow={isPanelCollapsed} size={isNested ? "24px" : "32px"} onKeyDown={this.onKeyDown} - ContextMenuComponent={this.props.space.getMyMembership() === "join" ? SpaceContextMenu : undefined} + ContextMenuComponent={ + this.props.space.getMyMembership() === KnownMembership.Join ? SpaceContextMenu : undefined + } > {toggleCollapseButton} diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentre.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentre.tsx index f6374ef32a..8b0b470f12 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentre.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentre.tsx @@ -32,6 +32,11 @@ import { useUnreadThreadRooms } from "./useUnreadThreadRooms"; import { StatelessNotificationBadge } from "../../rooms/NotificationBadge/StatelessNotificationBadge"; import { NotificationLevel } from "../../../../stores/notifications/NotificationLevel"; import PosthogTrackers from "../../../../PosthogTrackers"; +import { getKeyBindingsManager } from "../../../../KeyBindingsManager"; +import { KeyBindingAction } from "../../../../accessibility/KeyboardShortcuts"; +import { ReleaseAnnouncement } from "../../../structures/ReleaseAnnouncement"; +import { useIsReleaseAnnouncementOpen } from "../../../../hooks/useIsReleaseAnnouncementOpen"; +import { useSettingValue } from "../../../../hooks/useSettings"; interface ThreadsActivityCentreProps { /** @@ -47,43 +52,76 @@ interface ThreadsActivityCentreProps { export function ThreadsActivityCentre({ displayButtonLabel }: ThreadsActivityCentreProps): JSX.Element { const [open, setOpen] = useState(false); const roomsAndNotifications = useUnreadThreadRooms(open); + const isReleaseAnnouncementOpen = useIsReleaseAnnouncementOpen("threadsActivityCentre"); + const settingTACOnlyNotifs = useSettingValue("Notifications.tac_only_notifications"); + + const emptyCaption = settingTACOnlyNotifs + ? _t("threads_activity_centre|no_rooms_with_threads_notifs") + : _t("threads_activity_centre|no_rooms_with_unread_threads"); return ( - { - // Track only when the Threads Activity Centre is opened - if (newOpen) PosthogTrackers.trackInteraction("WebThreadsActivityCentreButton"); +
{ + // Do nothing if the TAC is closed + if (!open) return; + + const action = getKeyBindingsManager().getNavigationAction(evt); - setOpen(newOpen); + // Block spotlight opening + if (action === KeyBindingAction.FilterRooms) { + evt.stopPropagation(); + } }} - side="right" - title={_t("threads_activity_centre|header")} - trigger={ - - } > - {/* Make the content of the pop-up scrollable */} -
- {roomsAndNotifications.rooms.map(({ room, notificationLevel }) => ( - setOpen(false)} + {isReleaseAnnouncementOpen ? ( + + - ))} - {roomsAndNotifications.rooms.length === 0 && ( -
- {_t("threads_activity_centre|no_rooms_with_unreads_threads")} + + ) : ( + { + // Track only when the Threads Activity Centre is opened + if (newOpen) PosthogTrackers.trackInteraction("WebThreadsActivityCentreButton"); + + setOpen(newOpen); + }} + side="right" + title={_t("threads_activity_centre|header")} + trigger={ + + } + > + {/* Make the content of the pop-up scrollable */} +
+ {roomsAndNotifications.rooms.map(({ room, notificationLevel }) => ( + setOpen(false)} + /> + ))} + {roomsAndNotifications.rooms.length === 0 && ( +
{emptyCaption}
+ )}
- )} -
-
+ + )} +
); } @@ -105,10 +143,10 @@ interface ThreadsActivityRow { /** * Display a room with unread threads. */ -function ThreadsActivityRow({ room, onClick, notificationLevel }: ThreadsActivityRow): JSX.Element { +function ThreadsActivityCentreRow({ room, onClick, notificationLevel }: ThreadsActivityRow): JSX.Element { return ( { onClick(); @@ -125,12 +163,13 @@ function ThreadsActivityRow({ room, onClick, notificationLevel }: ThreadsActivit show_room_tile: true, // make sure the room is visible in the list room_id: room.roomId, metricsTrigger: "WebThreadsActivityCentre", + focusNext: "threadsPanel", }); }} label={room.name} Icon={} > - + ); } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentreButton.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentreButton.tsx index 3f85de38fa..c2e35de7aa 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentreButton.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/ThreadsActivityCentreButton.tsx @@ -27,7 +27,7 @@ import { notificationLevelToIndicator } from "../../../../utils/notifications"; interface ThreadsActivityCentreButtonProps extends ComponentProps { /** - * Display the `Treads` label next to the icon. + * Display the `Threads` label next to the icon. */ displayLabel?: boolean; /** diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/useUnreadThreadRooms.ts b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/useUnreadThreadRooms.ts index 115b208560..725fcfd5be 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/useUnreadThreadRooms.ts +++ b/linked-dependencies/matrix-react-sdk/src/components/views/spaces/threads-activity-centre/useUnreadThreadRooms.ts @@ -43,13 +43,14 @@ type Result = { */ export function useUnreadThreadRooms(forceComputation: boolean): Result { const msc3946ProcessDynamicPredecessor = useSettingValue("feature_dynamic_room_predecessors"); + const settingTACOnlyNotifs = useSettingValue("Notifications.tac_only_notifications"); const mxClient = useMatrixClientContext(); const [result, setResult] = useState({ greatestNotificationLevel: NotificationLevel.None, rooms: [] }); const doUpdate = useCallback(() => { - setResult(computeUnreadThreadRooms(mxClient, msc3946ProcessDynamicPredecessor)); - }, [mxClient, msc3946ProcessDynamicPredecessor]); + setResult(computeUnreadThreadRooms(mxClient, msc3946ProcessDynamicPredecessor, settingTACOnlyNotifs)); + }, [mxClient, msc3946ProcessDynamicPredecessor, settingTACOnlyNotifs]); // The exhautive deps lint rule can't compute dependencies here since it's not a plain inline func. // We make this as simple as possible so its only dep is doUpdate itself. @@ -83,22 +84,26 @@ export function useUnreadThreadRooms(forceComputation: boolean): Result { * @param mxClient - MatrixClient * @param msc3946ProcessDynamicPredecessor */ -function computeUnreadThreadRooms(mxClient: MatrixClient, msc3946ProcessDynamicPredecessor: boolean): Result { +function computeUnreadThreadRooms( + mxClient: MatrixClient, + msc3946ProcessDynamicPredecessor: boolean, + settingTACOnlyNotifs: boolean, +): Result { // Only count visible rooms to not torment the user with notification counts in rooms they can't see. // This will include highlights from the previous version of the room internally const visibleRooms = mxClient.getVisibleRooms(msc3946ProcessDynamicPredecessor); let greatestNotificationLevel = NotificationLevel.None; - const rooms = []; + const rooms: Result["rooms"] = []; for (const room of visibleRooms) { // We only care about rooms with unread threads if (VisibilityProvider.instance.isRoomVisible(room) && doesRoomHaveUnreadThreads(room)) { - // Get the greatest notification level of all rooms + // Get the greatest notification level of all threads const notificationLevel = getThreadNotificationLevel(room); // If the room has an activity notification or less, we ignore it - if (notificationLevel <= NotificationLevel.Activity) { + if (settingTACOnlyNotifs && notificationLevel <= NotificationLevel.Activity) { continue; } @@ -110,20 +115,35 @@ function computeUnreadThreadRooms(mxClient: MatrixClient, msc3946ProcessDynamicP } } - const sortedRooms = rooms.sort((a, b) => sortRoom(a.notificationLevel, b.notificationLevel)); + const sortedRooms = rooms.sort((a, b) => sortRoom(a, b)); return { greatestNotificationLevel, rooms: sortedRooms }; } +/** + * Store the room and its thread notification level + */ +type RoomData = Result["rooms"][0]; + /** * Sort notification level by the most important notification level to the least important * Highlight > Notification > Activity - * @param notificationLevelA - notification level of room A - * @param notificationLevelB - notification level of room B + * If the notification level is the same, we sort by the most recent thread + * @param roomDataA - room and notification level of room A + * @param roomDataB - room and notification level of room B * @returns {number} */ -function sortRoom(notificationLevelA: NotificationLevel, notificationLevelB: NotificationLevel): number { +function sortRoom(roomDataA: RoomData, roomDataB: RoomData): number { + const { notificationLevel: notificationLevelA, room: roomA } = roomDataA; + const { notificationLevel: notificationLevelB, room: roomB } = roomDataB; + + const timestampA = roomA.getLastThread()?.events.at(-1)?.getTs(); + const timestampB = roomB.getLastThread()?.events.at(-1)?.getTs(); + // NotificationLevel is a numeric enum, so we can compare them directly if (notificationLevelA > notificationLevelB) return -1; else if (notificationLevelB > notificationLevelA) return 1; - else return 0; + // Display most recent first + else if (!timestampA) return 1; + else if (!timestampB) return -1; + else return timestampB - timestampA; } diff --git a/linked-dependencies/matrix-react-sdk/src/components/views/verification/VerificationShowSas.tsx b/linked-dependencies/matrix-react-sdk/src/components/views/verification/VerificationShowSas.tsx index 42cb772159..de091091ab 100644 --- a/linked-dependencies/matrix-react-sdk/src/components/views/verification/VerificationShowSas.tsx +++ b/linked-dependencies/matrix-react-sdk/src/components/views/verification/VerificationShowSas.tsx @@ -16,7 +16,7 @@ limitations under the License. import React from "react"; import { Device } from "matrix-js-sdk/src/matrix"; -import { GeneratedSas, EmojiMapping } from "matrix-js-sdk/src/crypto-api/verification"; +import { GeneratedSas, EmojiMapping } from "matrix-js-sdk/src/crypto-api"; import SasEmoji from "@matrix-org/spec/sas-emoji.json"; import { _t, getNormalizedLanguageKeys, getUserLanguage } from "../../../languageHandler"; diff --git a/linked-dependencies/matrix-react-sdk/src/contexts/LocalDeviceVerificationStateContext.ts b/linked-dependencies/matrix-react-sdk/src/contexts/LocalDeviceVerificationStateContext.ts new file mode 100644 index 0000000000..4f0d7fe502 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/contexts/LocalDeviceVerificationStateContext.ts @@ -0,0 +1,27 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { createContext } from "react"; + +/** + * React context whose value is whether the local device has been verified. + * + * (Specifically, this is true if we have done enough verification to confirm that the published public cross-signing + * keys are genuine -- which normally means that we or another device will have published a signature of this device.) + * + * This context is available to all components under {@link LoggedInView}, via {@link MatrixClientContextProvider}. + */ +export const LocalDeviceVerificationStateContext = createContext(false); diff --git a/linked-dependencies/matrix-react-sdk/src/createRoom.ts b/linked-dependencies/matrix-react-sdk/src/createRoom.ts index 579eeab7f3..93ef63383f 100644 --- a/linked-dependencies/matrix-react-sdk/src/createRoom.ts +++ b/linked-dependencies/matrix-react-sdk/src/createRoom.ts @@ -347,15 +347,13 @@ export default async function createRoom(client: MatrixClient, opts: IOpts): Pro await JitsiCall.create(await room); // Reset our power level back to admin so that the widget becomes immutable - const plEvent = (await room).currentState.getStateEvents(EventType.RoomPowerLevels, ""); - await client.setPowerLevel(roomId, client.getUserId()!, 100, plEvent); + await client.setPowerLevel(roomId, client.getUserId()!, 100); } else if (opts.roomType === RoomType.UnstableCall) { // Set up this video room with an Element call await ElementCall.create(await room); // Reset our power level back to admin so that the call becomes immutable - const plEvent = (await room).currentState.getStateEvents(EventType.RoomPowerLevels, ""); - await client.setPowerLevel(roomId, client.getUserId()!, 100, plEvent); + await client.setPowerLevel(roomId, client.getUserId()!, 100); } }) .then( diff --git a/linked-dependencies/matrix-react-sdk/src/customisations/Media.ts b/linked-dependencies/matrix-react-sdk/src/customisations/Media.ts index 05f91325dd..25e8489658 100644 --- a/linked-dependencies/matrix-react-sdk/src/customisations/Media.ts +++ b/linked-dependencies/matrix-react-sdk/src/customisations/Media.ts @@ -15,10 +15,11 @@ */ import { MatrixClient, ResizeMethod } from "matrix-js-sdk/src/matrix"; +import { MediaEventContent } from "matrix-js-sdk/src/types"; import { Optional } from "matrix-events-sdk"; import { MatrixClientPeg } from "../MatrixClientPeg"; -import { IMediaEventContent, IPreparedMedia, prepEventContentAsMedia } from "./models/IMediaEventContent"; +import { IPreparedMedia, prepEventContentAsMedia } from "./models/IMediaEventContent"; import { UserFriendlyError } from "../languageHandler"; // Populate this class with the details of your customisations when copying it. @@ -154,11 +155,11 @@ export class Media { /** * Creates a media object from event content. - * @param {IMediaEventContent} content The event content. + * @param {MediaEventContent} content The event content. * @param {MatrixClient} client? Optional client to use. * @returns {Media} The media object. */ -export function mediaFromContent(content: Partial, client?: MatrixClient): Media { +export function mediaFromContent(content: Partial, client?: MatrixClient): Media { return new Media(prepEventContentAsMedia(content), client); } diff --git a/linked-dependencies/matrix-react-sdk/src/customisations/models/IMediaEventContent.ts b/linked-dependencies/matrix-react-sdk/src/customisations/models/IMediaEventContent.ts index 81714000d9..ad305239b1 100644 --- a/linked-dependencies/matrix-react-sdk/src/customisations/models/IMediaEventContent.ts +++ b/linked-dependencies/matrix-react-sdk/src/customisations/models/IMediaEventContent.ts @@ -14,220 +14,7 @@ * limitations under the License. */ -// TODO: These types should be elsewhere. - -import { MsgType } from "matrix-js-sdk/src/matrix"; - -import { BLURHASH_FIELD } from "../../utils/image-media"; - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#extensions-to-mroommessage-msgtypes - */ -export interface EncryptedFile { - /** - * The URL to the file. - */ - url: string; - /** - * A JSON Web Key object. - */ - key: { - alg: string; - key_ops: string[]; // eslint-disable-line camelcase - kty: string; - k: string; - ext: boolean; - }; - /** - * The 128-bit unique counter block used by AES-CTR, encoded as unpadded base64. - */ - iv: string; - /** - * A map from an algorithm name to a hash of the ciphertext, encoded as unpadded base64. - * Clients should support the SHA-256 hash, which uses the key sha256. - */ - hashes: { [alg: string]: string }; - /** - * Version of the encrypted attachment's protocol. Must be v2. - */ - v: string; -} - -interface ThumbnailInfo { - /** - * The mimetype of the image, e.g. image/jpeg. - */ - mimetype?: string; - /** - * The intended display width of the image in pixels. - * This may differ from the intrinsic dimensions of the image file. - */ - w?: number; - /** - * The intended display height of the image in pixels. - * This may differ from the intrinsic dimensions of the image file. - */ - h?: number; - /** - * Size of the image in bytes. - */ - size?: number; -} - -interface BaseInfo { - mimetype?: string; - size?: number; -} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#mfile - */ -export interface FileInfo extends BaseInfo { - /** - * @see https://github.com/matrix-org/matrix-spec-proposals/pull/2448 - */ - [BLURHASH_FIELD]?: string; - /** - * Information on the encrypted thumbnail file, as specified in End-to-end encryption. - * Only present if the thumbnail is encrypted. - * @see https://spec.matrix.org/v1.7/client-server-api/#sending-encrypted-attachments - */ - thumbnail_file?: EncryptedFile; - /** - * Metadata about the image referred to in thumbnail_url. - */ - thumbnail_info?: ThumbnailInfo; - /** - * The URL to the thumbnail of the file. Only present if the thumbnail is unencrypted. - */ - thumbnail_url?: string; -} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#mimage - * - */ -export interface ImageInfo extends FileInfo, ThumbnailInfo {} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#mimage - */ -export interface AudioInfo extends BaseInfo { - /** - * The duration of the audio in milliseconds. - */ - duration?: number; -} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#mvideo - */ -export interface VideoInfo extends AudioInfo, ImageInfo { - /** - * The duration of the video in milliseconds. - */ - duration?: number; -} - -export type IMediaEventInfo = FileInfo | ImageInfo | AudioInfo | VideoInfo; - -interface BaseContent { - /** - * Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption. - * @see https://spec.matrix.org/v1.7/client-server-api/#sending-encrypted-attachments - */ - file?: EncryptedFile; - /** - * Required if the file is unencrypted. The URL (typically mxc:// URI) to the file. - */ - url?: string; -} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#mfile - */ -export interface FileContent extends BaseContent { - /** - * A human-readable description of the file. - * This is recommended to be the filename of the original upload. - */ - body: string; - /** - * The original filename of the uploaded file. - */ - filename?: string; - /** - * Information about the file referred to in url. - */ - info?: FileInfo; - /** - * One of: [m.file]. - */ - msgtype: MsgType.File; -} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#mimage - */ -export interface ImageContent extends BaseContent { - /** - * A textual representation of the image. - * This could be the alt text of the image, the filename of the image, - * or some kind of content description for accessibility e.g. ‘image attachment’. - */ - body: string; - /** - * Metadata about the image referred to in url. - */ - info?: ImageInfo; - /** - * One of: [m.image]. - */ - msgtype: MsgType.Image; -} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#maudio - */ -export interface AudioContent extends BaseContent { - /** - * A description of the audio e.g. ‘Bee Gees - Stayin’ Alive’, - * or some kind of content description for accessibility e.g. ‘audio attachment’. - */ - body: string; - /** - * Metadata for the audio clip referred to in url. - */ - info?: AudioInfo; - /** - * One of: [m.audio]. - */ - msgtype: MsgType.Audio; -} - -/** - * @see https://spec.matrix.org/v1.7/client-server-api/#mvideo - */ -export interface VideoContent extends BaseContent { - /** - * A description of the video e.g. ‘Gangnam style’, - * or some kind of content description for accessibility e.g. ‘video attachment’. - */ - body: string; - /** - * Metadata about the video clip referred to in url. - */ - info?: VideoInfo; - /** - * One of: [m.video]. - */ - msgtype: MsgType.Video; -} - -/** - * Type representing media event contents for `m.room.message` events listed in the Matrix specification - */ -export type IMediaEventContent = FileContent | ImageContent | AudioContent | VideoContent; +import { EncryptedFile, MediaEventContent } from "matrix-js-sdk/src/types"; export interface IPreparedMedia extends IMediaObject { thumbnail?: IMediaObject; @@ -241,11 +28,11 @@ export interface IMediaObject { /** * Parses an event content body into a prepared media object. This prepared media object * can be used with other functions to manipulate the media. - * @param {IMediaEventContent} content Unredacted media event content. See interface. + * @param {MediaEventContent} content Unredacted media event content. See interface. * @returns {IPreparedMedia} A prepared media object. * @throws Throws if the given content cannot be packaged into a prepared media object. */ -export function prepEventContentAsMedia(content: Partial): IPreparedMedia { +export function prepEventContentAsMedia(content: Partial): IPreparedMedia { let thumbnail: IMediaObject | undefined; if (typeof content?.info === "object" && "thumbnail_url" in content.info && content.info.thumbnail_url) { thumbnail = { diff --git a/linked-dependencies/matrix-react-sdk/src/dispatcher/actions.ts b/linked-dependencies/matrix-react-sdk/src/dispatcher/actions.ts index f774508f54..e577daa884 100644 --- a/linked-dependencies/matrix-react-sdk/src/dispatcher/actions.ts +++ b/linked-dependencies/matrix-react-sdk/src/dispatcher/actions.ts @@ -91,6 +91,11 @@ export enum Action { */ FocusAComposer = "focus_a_composer", + /** + * Focuses the threads panel. + */ + FocusThreadsPanel = "focus_threads_panel", + /** * Opens the user menu (previously known as the top left menu). No additional payload information required. */ diff --git a/linked-dependencies/matrix-react-sdk/src/dispatcher/payloads/ViewRoomPayload.ts b/linked-dependencies/matrix-react-sdk/src/dispatcher/payloads/ViewRoomPayload.ts index 69ae5910ee..b8211128e5 100644 --- a/linked-dependencies/matrix-react-sdk/src/dispatcher/payloads/ViewRoomPayload.ts +++ b/linked-dependencies/matrix-react-sdk/src/dispatcher/payloads/ViewRoomPayload.ts @@ -24,6 +24,8 @@ import { IOpts } from "../../createRoom"; import { JoinRoomPayload } from "./JoinRoomPayload"; import { AtLeastOne } from "../../@types/common"; +export type FocusNextType = "composer" | "threadsPanel" | undefined; + /* eslint-disable camelcase */ interface BaseViewRoomPayload extends Pick { action: Action.ViewRoom; @@ -61,5 +63,6 @@ export type ViewRoomPayload = BaseViewRoomPayload & // the number of API calls required. room_id?: string; room_alias?: string; + focusNext: FocusNextType; // wat to focus after room switch. Defaults to 'composer' if undefined. }>; /* eslint-enable camelcase */ diff --git a/linked-dependencies/matrix-react-sdk/src/editor/commands.tsx b/linked-dependencies/matrix-react-sdk/src/editor/commands.tsx index 52ab881693..27f64f32be 100644 --- a/linked-dependencies/matrix-react-sdk/src/editor/commands.tsx +++ b/linked-dependencies/matrix-react-sdk/src/editor/commands.tsx @@ -16,7 +16,8 @@ limitations under the License. import React from "react"; import { logger } from "matrix-js-sdk/src/logger"; -import { IContent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { MatrixClient } from "matrix-js-sdk/src/matrix"; +import { RoomMessageEventContent } from "matrix-js-sdk/src/types"; import EditorModel from "./model"; import { Type } from "./parts"; @@ -63,9 +64,9 @@ export async function runSlashCommand( args: string | undefined, roomId: string, threadId: string | null, -): Promise<[content: IContent | null, success: boolean]> { +): Promise<[content: RoomMessageEventContent | null, success: boolean]> { const result = cmd.run(matrixClient, roomId, threadId, args); - let messageContent: IContent | null = null; + let messageContent: RoomMessageEventContent | null = null; let error: any = result.error; if (result.promise) { try { diff --git a/linked-dependencies/matrix-react-sdk/src/hooks/room/useGuestAccessInformation.ts b/linked-dependencies/matrix-react-sdk/src/hooks/room/useGuestAccessInformation.ts new file mode 100644 index 0000000000..38b83700bc --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/hooks/room/useGuestAccessInformation.ts @@ -0,0 +1,61 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { useMemo } from "react"; +import { EventType, JoinRule, Room } from "matrix-js-sdk/src/matrix"; + +import SdkConfig from "../../SdkConfig"; +import { useRoomState } from "../useRoomState"; + +interface GuestAccessInformation { + canInviteGuests: boolean; + guestSpaUrl?: string; + isRoomJoinable: () => boolean; + canInvite: boolean; +} + +/** + * Helper to retrieve the guest access related information for a room. + * @param room + * @returns The GuestAccessInformation which helps decide what options the user should be given. + */ +export const useGuestAccessInformation = (room: Room): GuestAccessInformation => { + const guestSpaUrl = useMemo(() => { + return SdkConfig.get("element_call").guest_spa_url; + }, []); + + // We use the direct function only in functions triggered by user interaction to avoid computation on every render. + const { joinRule, canInvite, canChangeJoinRule } = useRoomState(room, (roomState) => ({ + joinRule: room.getJoinRule(), + canInvite: room.canInvite(room.myUserId), + canChangeJoinRule: roomState.maySendStateEvent(EventType.RoomJoinRules, room.myUserId), + })); + const isRoomJoinable = useMemo( + () => joinRule === JoinRule.Public || (joinRule === JoinRule.Knock && canInvite), + [canInvite, joinRule], + ); + const canInviteGuests = useMemo( + () => (canChangeJoinRule || isRoomJoinable) && guestSpaUrl !== undefined, + [canChangeJoinRule, isRoomJoinable, guestSpaUrl], + ); + + const isRoomJoinableFunction = (): boolean => { + const join = room.getJoinRule(); + return join === JoinRule.Public || (join === JoinRule.Knock && room.canInvite(room.myUserId)); + }; + + return { canInviteGuests, guestSpaUrl, isRoomJoinable: isRoomJoinableFunction, canInvite }; +}; diff --git a/linked-dependencies/matrix-react-sdk/src/hooks/room/useRoomCall.ts b/linked-dependencies/matrix-react-sdk/src/hooks/room/useRoomCall.ts index fb1024b5d9..32662542ec 100644 --- a/linked-dependencies/matrix-react-sdk/src/hooks/room/useRoomCall.ts +++ b/linked-dependencies/matrix-react-sdk/src/hooks/room/useRoomCall.ts @@ -26,7 +26,7 @@ import { useWidgets } from "../../components/views/right_panel/RoomSummaryCard"; import { WidgetType } from "../../widgets/WidgetType"; import { useCall, useConnectionState, useParticipantCount } from "../useCall"; import { useRoomMemberCount } from "../useRoomMembers"; -import { Call, ConnectionState, ElementCall } from "../../models/Call"; +import { ConnectionState, ElementCall } from "../../models/Call"; import { placeCall } from "../../utils/room/placeCall"; import { Container, WidgetLayoutStore } from "../../stores/widgets/WidgetLayoutStore"; import { useRoomState } from "../useRoomState"; @@ -39,6 +39,8 @@ import defaultDispatcher from "../../dispatcher/dispatcher"; import { ViewRoomPayload } from "../../dispatcher/payloads/ViewRoomPayload"; import { Action } from "../../dispatcher/actions"; import { CallStore, CallStoreEvent } from "../../stores/CallStore"; +import { isVideoRoom } from "../../utils/video-rooms"; +import { useGuestAccessInformation } from "./useGuestAccessInformation"; export enum PlatformCallType { ElementCall, @@ -82,6 +84,7 @@ export const useRoomCall = ( hasActiveCallSession: boolean; callOptions: PlatformCallType[]; } => { + // settings const groupCallsEnabled = useFeatureEnabled("feature_group_calls"); const useElementCallExclusively = useMemo(() => { return SdkConfig.get("element_call").use_exclusively; @@ -92,21 +95,25 @@ export const useRoomCall = ( LegacyCallHandlerEvent.CallsChanged, () => LegacyCallHandler.instance.getCallForRoom(room.roomId) !== null, ); - + // settings const widgets = useWidgets(room); const jitsiWidget = useMemo(() => widgets.find((widget) => WidgetType.JITSI.matches(widget.type)), [widgets]); const hasJitsiWidget = !!jitsiWidget; const managedHybridWidget = useMemo(() => widgets.find(isManagedHybridWidget), [widgets]); const hasManagedHybridWidget = !!managedHybridWidget; + // group call const groupCall = useCall(room.roomId); const isConnectedToCall = useConnectionState(groupCall) === ConnectionState.Connected; const hasGroupCall = groupCall !== null; const hasActiveCallSession = useParticipantCount(groupCall) > 0; - const isViewingCall = useEventEmitterState(SdkContextClass.instance.roomViewStore, UPDATE_EVENT, () => - SdkContextClass.instance.roomViewStore.isViewingCall(), + const isViewingCall = useEventEmitterState( + SdkContextClass.instance.roomViewStore, + UPDATE_EVENT, + () => SdkContextClass.instance.roomViewStore.isViewingCall() || isVideoRoom(room), ); + // room const memberCount = useRoomMemberCount(room); const [mayEditWidgets, mayCreateElementCalls] = useRoomState(room, () => [ @@ -131,7 +138,7 @@ export const useRoomCall = ( return [PlatformCallType.ElementCall]; } if (hasGroupCall && WidgetType.CALL.matches(groupCall.widget.type)) { - // only allow joining joining the ongoing Element call if there is one. + // only allow joining the ongoing Element call if there is one. return [PlatformCallType.ElementCall]; } } @@ -164,15 +171,16 @@ export const useRoomCall = ( useEffect(() => { updateWidgetState(); }, [room, jitsiWidget, groupCall, updateWidgetState]); - const [activeCalls, setActiveCalls] = useState(Array.from(CallStore.instance.activeCalls)); - useEventEmitter(CallStore.instance, CallStoreEvent.ActiveCalls, () => { - setActiveCalls(Array.from(CallStore.instance.activeCalls)); - }); const [canPinWidget, setCanPinWidget] = useState(false); const [widgetPinned, setWidgetPinned] = useState(false); // We only want to prompt to pin the widget if it's not element call based. const isECWidget = WidgetType.CALL.matches(widget?.type ?? ""); const promptPinWidget = !isECWidget && canPinWidget && !widgetPinned; + const activeCalls = useEventEmitterState(CallStore.instance, CallStoreEvent.ActiveCalls, () => + Array.from(CallStore.instance.activeCalls), + ); + const { canInviteGuests } = useGuestAccessInformation(room); + const state = useMemo((): State => { if (activeCalls.find((call) => call.roomId != room.roomId)) { return State.Ongoing; @@ -183,8 +191,7 @@ export const useRoomCall = ( if (hasLegacyCall) { return State.Ongoing; } - - if (memberCount <= 1) { + if (memberCount <= 1 && !canInviteGuests) { return State.NoOneHere; } @@ -194,6 +201,7 @@ export const useRoomCall = ( return State.NoCall; }, [ activeCalls, + canInviteGuests, hasGroupCall, hasJitsiWidget, hasLegacyCall, diff --git a/linked-dependencies/matrix-react-sdk/src/hooks/useIsReleaseAnnouncementOpen.ts b/linked-dependencies/matrix-react-sdk/src/hooks/useIsReleaseAnnouncementOpen.ts new file mode 100644 index 0000000000..ab8bf07c5e --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/hooks/useIsReleaseAnnouncementOpen.ts @@ -0,0 +1,32 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import { useTypedEventEmitterState } from "./useEventEmitter"; +import { Feature, ReleaseAnnouncementStore } from "../stores/ReleaseAnnouncementStore"; + +/** + * Return true if the release announcement of the given feature is enabled + * @param feature + */ +export function useIsReleaseAnnouncementOpen(feature: Feature): boolean { + return useTypedEventEmitterState( + ReleaseAnnouncementStore.instance, + "releaseAnnouncementChanged", + () => ReleaseAnnouncementStore.instance.getReleaseAnnouncement() === feature, + ); +} diff --git a/linked-dependencies/matrix-react-sdk/src/hooks/useRoomMembers.ts b/linked-dependencies/matrix-react-sdk/src/hooks/useRoomMembers.ts index c0436562df..09c9773842 100644 --- a/linked-dependencies/matrix-react-sdk/src/hooks/useRoomMembers.ts +++ b/linked-dependencies/matrix-react-sdk/src/hooks/useRoomMembers.ts @@ -16,6 +16,7 @@ limitations under the License. import { useMemo, useState } from "react"; import { Room, RoomEvent, RoomMember, RoomStateEvent } from "matrix-js-sdk/src/matrix"; +import { Membership } from "matrix-js-sdk/src/types"; import { throttle } from "lodash"; import { useTypedEventEmitter } from "./useEventEmitter"; @@ -81,8 +82,8 @@ export const useRoomMemberCount = ( }; // Hook to simplify watching the local user's membership in a room -export const useMyRoomMembership = (room: Room): string => { - const [membership, setMembership] = useState(room.getMyMembership()); +export const useMyRoomMembership = (room: Room): Membership => { + const [membership, setMembership] = useState(room.getMyMembership()); useTypedEventEmitter(room, RoomEvent.MyMembership, () => { setMembership(room.getMyMembership()); }); diff --git a/linked-dependencies/matrix-react-sdk/src/hooks/useSpaceResults.ts b/linked-dependencies/matrix-react-sdk/src/hooks/useSpaceResults.ts index f21e071610..d2dde1315c 100644 --- a/linked-dependencies/matrix-react-sdk/src/hooks/useSpaceResults.ts +++ b/linked-dependencies/matrix-react-sdk/src/hooks/useSpaceResults.ts @@ -16,6 +16,7 @@ limitations under the License. import { useCallback, useEffect, useMemo, useState } from "react"; import { Room, RoomType, HierarchyRoom } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy"; import { normalize } from "matrix-js-sdk/src/utils"; @@ -57,7 +58,7 @@ export const useSpaceResults = (space: Room | undefined, query: string): [Hierar return rooms?.filter((r) => { return ( r.room_type !== RoomType.Space && - cli.getRoom(r.room_id)?.getMyMembership() !== "join" && + cli.getRoom(r.room_id)?.getMyMembership() !== KnownMembership.Join && (normalize(r.name || "").includes(normalizedQuery) || (r.canonical_alias || "").includes(lcQuery)) ); }); diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/cs.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/cs.json index bf905bdd0a..eacf7b6762 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/cs.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/cs.json @@ -249,7 +249,6 @@ "completing_setup": "Dokončování nastavení nového zařízení", "confirm_code_match": "Zkontrolujte, zda se níže uvedený kód shoduje s vaším dalším zařízením:", "connecting": "Připojování…", - "devices_connected": "Zařízení byla propojena", "error_device_already_signed_in": "Druhé zařízení je již přihlášeno.", "error_device_not_signed_in": "Druhé zařízení není přihlášeno.", "error_device_unsupported": "Propojení s tímto zařízením není podporováno.", @@ -260,12 +259,10 @@ "error_request_cancelled": "Požadavek byl zrušen.", "error_request_declined": "Požadavek byl na druhém zařízení odmítnut.", "error_unexpected": "Došlo k neočekávané chybě.", - "review_and_approve": "Zkontrolovat a schválit přihlášení", "scan_code_instruction": "Níže uvedený QR kód naskenujte pomocí přihlašovaného zařízení.", "scan_qr_code": "Skenovat QR kód", "select_qr_code": "Vybrat '%(scanQRCode)s'", "sign_in_new_device": "Přihlásit nové zařízení", - "start_at_sign_in_screen": "Začněte na přihlašovací obrazovce", "waiting_for_device": "Čekání na přihlášení zařízení" }, "register_action": "Vytvořit účet", @@ -742,7 +739,6 @@ "notification_state": "Stav oznámení je %(notificationState)s", "notifications_debug": "Ladění oznámení", "number_of_users": "Počet uživatelů", - "observe_only": "Pouze sledovat", "original_event_source": "Původní zdroj události", "phase": "Fáze", "phase_cancelled": "Zrušeno", @@ -750,7 +746,6 @@ "phase_requested": "Požadované", "phase_started": "Zahájeno", "phase_transaction": "Transakce", - "requester": "Žadatel", "room_encrypted": "Místnost je šifrovaná ✅", "room_id": "ID místnosti: %(roomId)s", "room_not_encrypted": "Místnost není šifrovaná 🚨", @@ -1512,14 +1507,6 @@ "view_rules": "Zobrazit pravidla" }, "language_dropdown_label": "Menu jazyků", - "lazy_loading": { - "disabled_action": "Smazat paměť a sesynchronizovat", - "disabled_description1": "Na adrese %(host)s už jste použili %(brand)s se zapnutou volbou načítání členů místností až při prvním zobrazení. V této verzi je načítání členů až při prvním zobrazení vypnuté. Protože je s tímto nastavením lokální vyrovnávací paměť nekompatibilní, %(brand)s potřebuje znovu synchronizovat údaje z vašeho účtu.", - "disabled_description2": "Je-li jiná verze programu %(brand)s stále otevřená na jiné kartě, tak ji prosím zavřete, neboť užívání programu %(brand)s stejným hostitelem se zpožděným nahráváním současně povoleným i zakázaným bude působit problémy.", - "disabled_title": "Nekompatibilní lokální vyrovnávací paměť", - "resync_description": "%(brand)s teď používá 3-5× méně paměti, protože si informace o ostatních uživatelích načítá až když je potřebuje. Prosím počkejte na dokončení synchronizace se serverem!", - "resync_title": "Aktualizujeme %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Jste zde jediná osoba. Pokud odejdete, nikdo se v budoucnu nebude moci připojit, včetně vás.", "leave_room_question": "Opravdu chcete opustit místnost '%(roomName)s'?", @@ -1893,6 +1880,7 @@ "forget": "Zapomenout místnost", "low_priority": "Nízká priorita", "mark_read": "Označit jako přečtené", + "mark_unread": "Označit jako nepřečtené", "mentions_only": "Pouze zmínky", "notifications_default": "Odpovídá výchozímu nastavení", "notifications_mute": "Ztlumit místnost", @@ -2899,6 +2887,9 @@ "link_title": "Odkaz na místnost", "permalink_message": "Odkaz na vybranou zprávu", "permalink_most_recent": "Odkaz na nejnovější zprávu", + "share_call": "Odkaz na pozvánku na konferenci", + "share_call_subtitle": "Odkaz pro externí uživatele, aby se připojili k hovoru bez Matrix účtu:", + "title_link": "Sdílet odkaz", "title_message": "Sdílet zprávu z místnosti", "title_room": "Sdílet místnost", "title_user": "Sdílet uživatele" @@ -3831,6 +3822,7 @@ "expand": "Návrat do hovoru", "failed_call_live_broadcast_description": "Nemůžete zahájit hovor, protože právě nahráváte živé vysílání. Ukončete prosím živé vysílání, abyste mohli zahájit hovor.", "failed_call_live_broadcast_title": "Nelze zahájit hovor", + "get_call_link": "Sdílet odkaz na hovor", "hangup": "Zavěsit", "hide_sidebar_button": "Skrýt postranní panel", "input_devices": "Vstupní zařízení", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/de_DE.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/de_DE.json index 7f4621290c..3fc5e49035 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/de_DE.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/de_DE.json @@ -1,5 +1,6 @@ { "a11y": { + "emoji_picker": "Emoji-Auswahl", "jump_first_invite": "Zur ersten Einladung springen.", "n_unread_messages": { "other": "%(count)s ungelesene Nachrichten.", @@ -244,7 +245,6 @@ "completing_setup": "Schließe Anmeldung deines neuen Gerätes ab", "confirm_code_match": "Überprüfe, dass der unten angezeigte Code mit deinem anderen Gerät übereinstimmt:", "connecting": "Verbinde …", - "devices_connected": "Geräte verbunden", "error_device_already_signed_in": "Das andere Gerät ist bereits angemeldet.", "error_device_not_signed_in": "Das andere Gerät ist nicht angemeldet.", "error_device_unsupported": "Die Verbindung mit diesem Gerät wird nicht unterstützt.", @@ -255,12 +255,10 @@ "error_request_cancelled": "Die Anfrage wurde abgebrochen.", "error_request_declined": "Die Anfrage wurde auf dem anderen Gerät abgelehnt.", "error_unexpected": "Ein unerwarteter Fehler ist aufgetreten.", - "review_and_approve": "Überprüfe und genehmige die Anmeldung", "scan_code_instruction": "Lese den folgenden QR-Code mit deinem nicht angemeldeten Gerät ein.", "scan_qr_code": "QR-Code einlesen", "select_qr_code": "Wähle „%(scanQRCode)s“", "sign_in_new_device": "Neues Gerät anmelden", - "start_at_sign_in_screen": "Beginne auf dem Anmeldebildschirm", "waiting_for_device": "Warte auf Anmeldung des Gerätes" }, "register_action": "Konto erstellen", @@ -736,7 +734,6 @@ "notification_state": "Benachrichtigungsstand ist %(notificationState)s", "notifications_debug": "Debug-Modus für Benachrichtigungen", "number_of_users": "Benutzeranzahl", - "observe_only": "Nur beobachten", "original_event_source": "Ursprüngliche Rohdaten", "phase": "Phase", "phase_cancelled": "Abgebrochen", @@ -744,7 +741,6 @@ "phase_requested": "Angefragt", "phase_started": "Gestartet", "phase_transaction": "Transaktion", - "requester": "Anforderer", "room_encrypted": "Raum ist verschlüsselt ✅", "room_id": "Raum-ID: %(roomId)s", "room_not_encrypted": "Raum ist nicht verschlüsselt 🚨", @@ -1007,7 +1003,7 @@ "verify_emoji_prompt": "Durch den Vergleich einzigartiger Emojis verifizieren.", "verify_emoji_prompt_qr": "Wenn du obigen Code nicht erfassen kannst, verifiziere stattdessen durch den Vergleich von Emojis.", "verify_later": "Später verifizieren", - "verify_reset_warning_1": "Das Zurücksetzen deiner Sicherheitsschlüssel kann nicht rückgängig gemacht werden. Nach dem Zurücksetzen wirst du alte Nachrichten nicht mehr lesen können un Freunde, die dich vorher verifiziert haben werden Sicherheitswarnungen bekommen, bis du dich erneut mit ihnen verifizierst.", + "verify_reset_warning_1": "Das Zurücksetzen deiner Sicherheitsschlüssel kann nicht rückgängig gemacht werden. Nach dem Zurücksetzen wirst du alte Nachrichten nicht mehr lesen können und Freunde, die dich vorher verifiziert haben werden Sicherheitswarnungen bekommen, bis du dich erneut mit ihnen verifizierst.", "verify_reset_warning_2": "Bitte fahre nur fort, wenn du sicher bist, dass du alle anderen Geräte und deinen Sicherheitsschlüssel verloren hast.", "verify_using_device": "Mit anderem Gerät verifizieren", "verify_using_key": "Mit Sicherheitsschlüssel verifizieren", @@ -1055,7 +1051,7 @@ "error_app_open_in_another_tab": "Wechsle zu einem anderen Tab um mit %(brand)s zu verbinden. Dieser Tab kann jetzt geschlossen werden.", "error_app_open_in_another_tab_title": "%(brand)s läuft bereits in einem anderen Tab.", "error_app_opened_in_another_window": "%(brand)s läuft bereit in einem anderen Fenster. Klicke \"%(label)s um %(brand)s hier zu nutzen und beende das andere Fenster.", - "error_database_closed_title": "Datenbank unerwartet geschlossen", + "error_database_closed_title": "%(brand)s funktioniert nicht mehr", "error_dialog": { "copy_room_link_failed": { "description": "Der Link zum Raum konnte nicht kopiert werden.", @@ -1359,7 +1355,7 @@ "send_sticker": "Sticker senden", "shift": "Umschalt", "space": "Leertaste", - "switch_to_space": "Mit Nummer zu Space springen", + "switch_to_space": "Mit Nummer zu Leerzeichen springen", "toggle_hidden_events": "Sichtbarkeit versteckter Ereignisse umschalten", "toggle_microphone_mute": "Mikrofon an-/ausschalten", "toggle_right_panel": "Rechtes Panel ein-/ausblenden", @@ -1405,6 +1401,7 @@ "group_rooms": "Räume", "group_spaces": "Räume", "group_themes": "Themen", + "group_threads": "Themen", "group_voip": "Anrufe", "group_widgets": "Widgets", "hidebold": "Benachrichtigungspunkt ausblenden (nur Zähler zeigen)", @@ -1493,14 +1490,6 @@ "view_rules": "Regeln öffnen" }, "language_dropdown_label": "Sprachauswahl", - "lazy_loading": { - "disabled_action": "Zwischenspeicher löschen und erneut synchronisieren", - "disabled_description1": "Du hast zuvor %(brand)s auf %(host)s ohne das verzögerte Laden von Mitgliedern genutzt. In dieser Version war das verzögerte Laden deaktiviert. Da die lokal zwischengespeicherten Daten zwischen diesen Einstellungen nicht kompatibel sind, muss %(brand)s dein Konto neu synchronisieren.", - "disabled_description2": "Wenn %(brand)s mit der alten Version in einem anderen Tab geöffnet ist, schließe dies bitte, da das parallele Nutzen von %(brand)s auf demselben Host mit aktivierten und deaktivierten verzögertem Laden, Probleme verursachen wird.", - "disabled_title": "Inkompatibler lokaler Zwischenspeicher", - "resync_description": "%(brand)s benutzt nun 3 bis 5 Mal weniger Arbeitsspeicher, indem Informationen über andere Nutzer erst bei Bedarf geladen werden. Bitte warte, während die Daten erneut mit dem Server abgeglichen werden!", - "resync_title": "Aktualisiere %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Du bist die einzige Person im Raum. Sobald du ihn verlässt, wird niemand mehr hineingelangen, auch du nicht.", "leave_room_question": "Bist du sicher, dass du den Raum „%(roomName)s“ verlassen möchtest?", @@ -2304,7 +2293,7 @@ "join_rule_upgrade_upgrading_room": "Raum wird aktualisiert", "public_without_alias_warning": "Um den Raum zu verlinken, füge bitte eine Adresse hinzu.", "publish_room": "Diesen Raum im Raumverzeichnis veröffentlichen.", - "publish_space": "Diesen Space im Raumerzeichnis veröffentlichen.", + "publish_space": "Diesen Space im Raumverzeichnis veröffentlichen.", "strict_encryption": "Niemals verschlüsselte Nachrichten von dieser Sitzung zu unverifizierten Sitzungen in diesem Raum senden", "title": "Sicherheit" }, @@ -3996,6 +3985,7 @@ "extendedRepeat": "Wiederholungen wie \"abcabcabc\" sind fast so schnell zu erraten wie \"abc\"", "keyPattern": "Kurze Tastaturmuster sind einfach zu erraten", "namesByThemselves": "Namen und Familiennamen alleine sind einfach zu erraten", + "pwned": "Dein Passwort wurde durch eine Datenleck im Internet offengelegt.", "recentYears": "Kürzlich vergangene Jahre sind einfach zu raten", "sequences": "Sequenzen wie \"abc\" oder \"6543\" sind leicht zu raten", "similarToCommon": "Dies ist ähnlich zu einem oft genutzten Passwort", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/el.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/el.json index baf8bd53d9..bd9f43db30 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/el.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/el.json @@ -606,7 +606,6 @@ "methods": "Μέθοδοι", "no_verification_requests_found": "Δεν βρέθηκαν αιτήματα επαλήθευσης", "number_of_users": "Αριθμός χρηστών", - "observe_only": "Παρατηρήστε μόνο", "original_event_source": "Αρχική πηγή συμβάντος", "phase": "Φάση", "phase_cancelled": "Ακυρώθηκαν", @@ -614,7 +613,6 @@ "phase_requested": "Απαιτείται", "phase_started": "Ξεκίνησαν", "phase_transaction": "Συναλλαγή", - "requester": "Aιτών", "room_id": "ID δωματίου: %(roomId)s", "save_setting_values": "Αποθήκευση τιμών ρύθμισης", "send_custom_account_data_event": "Αποστολή προσαρμοσμένου συμβάντος δεδομένων λογαριασμού", @@ -1215,14 +1213,6 @@ "view_rules": "Προβολή κανόνων" }, "language_dropdown_label": "Επιλογή Γλώσσας", - "lazy_loading": { - "disabled_action": "Εκκαθάριση προσωρινής μνήμης και επανασυγχρονισμός", - "disabled_description1": "Έχετε χρησιμοποιήσει στο παρελθόν %(brand)s στον %(host)s με ενεργοποιημένη την αργή φόρτωση μελών. Σε αυτήν την έκδοση η αργή φόρτωση είναι απενεργοποιημένη. Η τοπική κρυφή μνήμη δεν είναι συμβατή μεταξύ αυτών των δύο ρυθμίσεων και έτσι το %(brand)s πρέπει να συγχρονίσει ξανά τον λογαριασμό σας.", - "disabled_description2": "Εάν η άλλη έκδοση του %(brand)s εξακολουθεί να είναι ανοιχτή σε άλλη καρτέλα, κλείστε την, καθώς η χρήση του %(brand)s στον ίδιο κεντρικό υπολογιστή με ενεργοποιημένη και απενεργοποιημένη την αργή φόρτωση ταυτόχρονα , θα προκαλέσει προβλήματα.", - "disabled_title": "Μη συμβατή τοπική κρυφή μνήμη", - "resync_description": "Το %(brand)s χρησιμοποιεί πλέον 3-5 φορές λιγότερη μνήμη, φορτώνοντας πληροφορίες για άλλους χρήστες μόνο όταν χρειάζεται. Περιμένετε όσο γίνεται εκ νέου συγχρονισμός με τον διακομιστή!", - "resync_title": "Ενημέρωση %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Είστε το μόνο άτομο εδώ μέσα. Εάν φύγετε, κανείς δε θα μπορεί αργότερα να συμμετάσχει, συμπεριλαμβανομένου και εσάς.", "leave_room_question": "Είστε σίγουροι ότι θέλετε να αποχωρήσετε από το δωμάτιο '%(roomName)s';", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/en_EN.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/en_EN.json index c974dc5f8b..f0ee695d5e 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/en_EN.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/en_EN.json @@ -249,7 +249,6 @@ "completing_setup": "Completing set up of your new device", "confirm_code_match": "Check that the code below matches with your other device:", "connecting": "Connecting…", - "devices_connected": "Devices connected", "error_device_already_signed_in": "The other device is already signed in.", "error_device_not_signed_in": "The other device isn't signed in.", "error_device_unsupported": "Linking with this device is not supported.", @@ -260,12 +259,13 @@ "error_request_cancelled": "The request was cancelled.", "error_request_declined": "The request was declined on the other device.", "error_unexpected": "An unexpected error occurred.", - "review_and_approve": "Review and approve the sign in", - "scan_code_instruction": "Scan the QR code below with your device that's signed out.", + "follow_remaining_instructions": "Follow the remaining instructions to verify your other device", + "open_element_other_device": "Open %(brand)s on your other device", + "point_the_camera": "Point the camera at the QR code shown here", + "scan_code_instruction": "Scan the QR code with another device", "scan_qr_code": "Scan QR code", - "select_qr_code": "Select '%(scanQRCode)s'", + "select_qr_code": "Select \"%(scanQRCode)s\"", "sign_in_new_device": "Sign in new device", - "start_at_sign_in_screen": "Start at the sign in screen", "waiting_for_device": "Waiting for device to sign in" }, "register_action": "Create Account", @@ -742,15 +742,14 @@ "notification_state": "Notification state is %(notificationState)s", "notifications_debug": "Notifications debug", "number_of_users": "Number of users", - "observe_only": "Observe only", "original_event_source": "Original event source", + "other_user": "Other user", "phase": "Phase", "phase_cancelled": "Cancelled", "phase_ready": "Ready", "phase_requested": "Requested", "phase_started": "Started", "phase_transaction": "Transaction", - "requester": "Requester", "room_encrypted": "Room is encrypted ✅", "room_id": "Room ID: %(roomId)s", "room_not_encrypted": "Room is not encrypted 🚨", @@ -789,6 +788,7 @@ "thread_root_id": "Thread Root ID: %(threadRootId)s", "threads_timeline": "Threads timeline", "timeout": "Timeout", + "timeout_none": "None", "title": "Developer tools", "toggle_event": "toggle event", "toolbox": "Toolbox", @@ -1417,6 +1417,7 @@ "group_spaces": "Spaces", "group_themes": "Themes", "group_threads": "Threads", + "group_ui": "User interface", "group_voip": "Voice & Video", "group_widgets": "Widgets", "hidebold": "Hide notification dot (only display counters badges)", @@ -1440,6 +1441,7 @@ "oidc_native_flow": "OIDC native authentication", "oidc_native_flow_description": "⚠ WARNING: Experimental. Use OIDC native authentication when supported by the server.", "pinning": "Message Pinning", + "release_announcement": "Release announcement", "render_reaction_images": "Render custom images in reactions", "render_reaction_images_description": "Sometimes referred to as \"custom emojis\".", "report_to_moderators": "Report to moderators", @@ -1511,18 +1513,12 @@ "view_rules": "View rules" }, "language_dropdown_label": "Language Dropdown", - "lazy_loading": { - "disabled_action": "Clear cache and resync", - "disabled_description1": "You've previously used %(brand)s on %(host)s with lazy loading of members enabled. In this version lazy loading is disabled. As the local cache is not compatible between these two settings, %(brand)s needs to resync your account.", - "disabled_description2": "If the other version of %(brand)s is still open in another tab, please close it as using %(brand)s on the same host with both lazy loading enabled and disabled simultaneously will cause issues.", - "disabled_title": "Incompatible local cache", - "resync_description": "%(brand)s now uses 3-5x less memory, by only loading information about other users when needed. Please wait whilst we resynchronise with the server!", - "resync_title": "Updating %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "You are the only person here. If you leave, no one will be able to join in the future, including you.", "leave_room_question": "Are you sure you want to leave the room '%(roomName)s'?", "leave_space_question": "Are you sure you want to leave the space '%(spaceName)s'?", + "room_leave_admin_warning": "You're the only administrator in this room. If you leave, nobody will be able to change room settings or take other important actions.", + "room_leave_mod_warning": "You're the only moderator in this room. If you leave, nobody will be able to change room settings or take other important actions.", "room_rejoin_warning": "This room is not public. You will not be able to rejoin without an invite.", "space_rejoin_warning": "This space is not public. You will not be able to rejoin without an invite." }, @@ -1892,6 +1888,7 @@ "forget": "Forget Room", "low_priority": "Low Priority", "mark_read": "Mark as read", + "mark_unread": "Mark as unread", "mentions_only": "Mentions only", "notifications_default": "Match default setting", "notifications_mute": "Mute room", @@ -2687,6 +2684,8 @@ "cross_signing_self_signing_private_key": "Self signing private key:", "cross_signing_user_signing_private_key": "User signing private key:", "cryptography_section": "Cryptography", + "dehydrated_device_description": "The offline device feature allows you to receive encrypted messages even when you are not logged in to any devices", + "dehydrated_device_enabled": "Offline device enabled", "delete_backup": "Delete Backup", "delete_backup_confirm_description": "Are you sure? You will lose your encrypted messages if your keys are not backed up properly.", "e2ee_default_disabled_warning": "Your server admin has disabled end-to-end encryption by default in private rooms & Direct Messages.", @@ -2807,9 +2806,9 @@ "security_recommendations_description": "Improve your account security by following these recommendations.", "session_id": "Session ID", "show_details": "Show details", - "sign_in_with_qr": "Sign in with QR code", + "sign_in_with_qr": "Link new device", "sign_in_with_qr_button": "Show QR code", - "sign_in_with_qr_description": "You can use this device to sign in a new device with a QR code. You will need to scan the QR code shown on this device with your device that's signed out.", + "sign_in_with_qr_description": "Use a QR code to sign in to another device and set up secure messaging.", "sign_out": "Sign out of this session", "sign_out_all_other_sessions": "Sign out of all other sessions (%(otherSessionsCount)s)", "sign_out_confirm_description": { @@ -2849,6 +2848,7 @@ "show_redaction_placeholder": "Show a placeholder for removed messages", "show_stickers_button": "Show stickers button", "show_typing_notifications": "Show typing notifications", + "showbold": "Show all activity in the room list (dots or number of unread messages)", "sidebar": { "metaspaces_favourites_description": "Group all your favourite rooms and people in one place.", "metaspaces_home_all_rooms": "Show all rooms", @@ -2858,10 +2858,14 @@ "metaspaces_orphans_description": "Group all your rooms that aren't part of a space in one place.", "metaspaces_people_description": "Group all your people in one place.", "metaspaces_subsection": "Spaces to show", + "metaspaces_video_rooms": "Video rooms and conferences", + "metaspaces_video_rooms_description": "Group all private video rooms and conferences.", + "metaspaces_video_rooms_description_invite_extension": "In conferences you can invite people outside of matrix.", "spaces_explainer": "Spaces are ways to group rooms and people. Alongside the spaces you're in, you can use some pre-built ones too.", "title": "Sidebar" }, "start_automatically": "Start automatically after system login", + "tac_only_notifications": "Only show notifications in the thread activity centre", "use_12_hour_format": "Show timestamps in 12 hour format (e.g. 2:30pm)", "use_command_enter_send_message": "Use Command + Enter to send a message", "use_command_f_search": "Use Command + F to search timeline", @@ -2896,6 +2900,9 @@ "link_title": "Link to room", "permalink_message": "Link to selected message", "permalink_most_recent": "Link to most recent message", + "share_call": "Conference invite link", + "share_call_subtitle": "Link for external users to join the call without a matrix account:", + "title_link": "Share Link", "title_message": "Share Room Message", "title_room": "Share Room", "title_user": "Share User" @@ -3150,6 +3157,7 @@ "empty_heading": "Keep discussions organised with threads", "empty_tip": "Tip: Use “%(replyInThread)s” when hovering over a message.", "error_start_thread_existing_relation": "Can't create a thread from an event with an existing relation", + "mark_all_read": "Mark all as read", "my_threads": "My threads", "my_threads_description": "Shows all threads you've participated in", "open_thread": "Open thread", @@ -3159,7 +3167,10 @@ }, "threads_activity_centre": { "header": "Threads activity", - "no_rooms_with_unreads_threads": "You don't have rooms with unread threads yet." + "no_rooms_with_threads_notifs": "You don't have rooms with thread notifications yet.", + "no_rooms_with_unread_threads": "You don't have rooms with unread threads yet.", + "release_announcement_description": "Threads notifications have moved, find them here from now on.", + "release_announcement_header": "Threads Activity Centre" }, "time": { "about_day_ago": "about a day ago", @@ -3656,6 +3667,12 @@ "toast_title": "Update %(brand)s", "unavailable": "Unavailable" }, + "update_room_access_modal": { + "description": "To create a share link, you need to allow guests to join this room. This may make the room less secure. When you're done with the call, you can make the room private again.", + "dont_change_description": "Alternatively, you can hold the call in a separate room.", + "no_change": "I don't want to change the access level.", + "title": "Change the room access level" + }, "upload_failed_generic": "The file '%(fileName)s' failed to upload.", "upload_failed_size": "The file '%(fileName)s' exceeds this homeserver's size limit for uploads", "upload_failed_title": "Upload Failed", @@ -3691,6 +3708,7 @@ "deactivate_confirm_action": "Deactivate user", "deactivate_confirm_description": "Deactivating this user will log them out and prevent them from logging back in. Additionally, they will leave all the rooms they are in. This action cannot be reversed. Are you sure you want to deactivate this user?", "deactivate_confirm_title": "Deactivate user?", + "dehydrated_device_enabled": "Offline device enabled", "demote_button": "Demote", "demote_self_confirm_description_space": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the space it will be impossible to regain privileges.", "demote_self_confirm_room": "You will not be able to undo this change as you are demoting yourself, if you are the last privileged user in the room it will be impossible to regain privileges.", @@ -3828,6 +3846,7 @@ "expand": "Return to call", "failed_call_live_broadcast_description": "You can’t start a call as you are currently recording a live broadcast. Please end your live broadcast in order to start a call.", "failed_call_live_broadcast_title": "Can’t start a call", + "get_call_link": "Share call link", "hangup": "Hangup", "hide_sidebar_button": "Hide sidebar", "input_devices": "Input devices", @@ -3837,6 +3856,9 @@ "legacy_call": "Legacy Call", "maximise": "Fill screen", "maximise_call": "Maximise call", + "metaspace_video_rooms": { + "conference_room_section": "Conferences" + }, "minimise_call": "Minimise call", "misconfigured_server": "Call failed due to misconfigured server", "misconfigured_server_description": "Please ask the administrator of your homeserver (%(homeserverDomain)s) to configure a TURN server in order for calls to work reliably.", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/eo.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/eo.json index bb2560e3c4..7845e4bfb6 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/eo.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/eo.json @@ -1056,6 +1056,7 @@ "group_profile": "Profilo", "group_rooms": "Ĉambroj", "group_spaces": "Aroj", + "group_threads": "Fadenoj", "group_voip": "Voĉo kaj vido", "group_widgets": "Fenestraĵoj", "html_topic": "Montru HTML-prezenton de ĉambrotemoj", @@ -1108,14 +1109,6 @@ "view_rules": "Montri regulojn" }, "language_dropdown_label": "Lingva falmenuo", - "lazy_loading": { - "disabled_action": "Vakigi kaŝmemoron kaj respeguli", - "disabled_description1": "Vi antaŭe uzis %(brand)s-on je %(host)s kun ŝaltita malfrua enlegado de anoj. En ĉi tiu versio, malfrua enlegado estas malŝaltita. Ĉar la loka kaŝmemoro de ambaŭ versioj ne akordas, %(brand)s bezonas respeguli vian konton.", - "disabled_description2": "Se la alia versio de %(brand)s ankoraŭ estas malfermita en alia langeto, bonvolu tiun fermi, ĉar uzado de %(brand)s je la sama gastiganto, kun malfrua enlegado samtempe ŝaltita kaj malŝaltita, kaŭzos problemojn.", - "disabled_title": "Neakorda loka kaŝmemoro", - "resync_description": "%(brand)s nun uzas 3–5-oble malpli da memoro, ĉar ĝi enlegas informojn pri aliaj uzantoj nur tiam, kiam ĝi bezonas. Bonvolu atendi ĝis ni respegulos la servilon!", - "resync_title": "Ĝisdatigante %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Vi estas la nura persono tie ĉi. Se vi foriros, neniu alia plu povos aliĝi, inkluzive vin mem.", "leave_room_question": "Ĉu vi certe volas forlasi la ĉambron '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/es.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/es.json index 78ca3a655b..936ecebb6f 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/es.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/es.json @@ -233,7 +233,6 @@ "completing_setup": "Terminando de configurar tu nuevo dispositivo", "confirm_code_match": "Comprueba que el siguiente código también aparece en el otro dispositivo:", "connecting": "Conectando…", - "devices_connected": "Dispositivos conectados", "error_device_already_signed_in": "El otro dispositivo ya tiene una sesión iniciada.", "error_device_not_signed_in": "El otro dispositivo no tiene una sesión iniciada.", "error_homeserver_lacks_support": "Tu servidor base no es compatible con el inicio de sesión en otro dispositivo.", @@ -243,12 +242,10 @@ "error_request_cancelled": "La solicitud ha sido cancelada.", "error_request_declined": "El otro dispositivo ha rechazado la solicitud.", "error_unexpected": "Ha ocurrido un error inesperado.", - "review_and_approve": "Revisar y aprobar inicio de sesión", "scan_code_instruction": "Escanea el siguiente código QR con tu dispositivo.", "scan_qr_code": "Escanear código QR", "select_qr_code": "Selecciona «%(scanQRCode)s»", "sign_in_new_device": "Conectar nuevo dispositivo", - "start_at_sign_in_screen": "Ve a la pantalla de inicio de sesión", "waiting_for_device": "Esperando a que el dispositivo inicie sesión" }, "register_action": "Crear cuenta", @@ -692,7 +689,6 @@ "methods": "Métodos", "no_verification_requests_found": "Ninguna solicitud de verificación encontrada", "number_of_users": "Número de usuarios", - "observe_only": "Solo observar", "original_event_source": "Fuente original del evento", "phase": "Fase", "phase_cancelled": "Cancelado", @@ -700,7 +696,6 @@ "phase_requested": "Solicitado", "phase_started": "Empezado", "phase_transaction": "Transacción", - "requester": "Solicitante", "room_encrypted": "La sala está cifrada ✅", "room_id": "ID de la sala: %(roomId)s", "room_not_encrypted": "La sala no está cifrada 🚨", @@ -1383,14 +1378,6 @@ "view_rules": "Ver reglas" }, "language_dropdown_label": "Lista selección de idiomas", - "lazy_loading": { - "disabled_action": "Limpiar la caché y resincronizar", - "disabled_description1": "Has usado %(brand)s anteriormente en %(host)s con carga diferida de usuarios activada. En esta versión la carga diferida está desactivada. Como el caché local no es compatible entre estas dos configuraciones, %(brand)s tiene que resincronizar tu cuenta.", - "disabled_description2": "Si la otra versión de %(brand)s esta todavía abierta en otra pestaña, por favor, ciérrala, ya que usar %(brand)s en el mismo host con la opción de carga diferida activada y desactivada simultáneamente causará problemas.", - "disabled_title": "Caché local incompatible", - "resync_description": "%(brand)s ahora utiliza de 3 a 5 veces menos memoria, porque solo carga información sobre otros usuarios cuando es necesario. Por favor, ¡aguarda mientras volvemos a sincronizar con el servidor!", - "resync_title": "Actualizando %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Eres la única persona aquí. Si te vas, no podrá unirse nadie en el futuro, incluyéndote a ti.", "leave_room_question": "¿Salir de la sala «%(roomName)s»?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/et.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/et.json index 0aec099268..cdfe16cc66 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/et.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/et.json @@ -1,6 +1,8 @@ { "a11y": { + "emoji_picker": "Emojide valija", "jump_first_invite": "Siirdu esimese kutse juurde.", + "message_composer": "Sõnumikoostaja", "n_unread_messages": { "other": "%(count)s lugemata teadet.", "one": "1 lugemata teade." @@ -9,7 +11,10 @@ "one": "1 lugemata mainimine.", "other": "%(count)s lugemata sõnumit kaasa arvatud mainimised." }, + "recent_rooms": "Hiljuti kasutatud jututoad", "room_name": "Jututuba %(name)s", + "room_status_bar": "Jututoa olekuriba", + "seek_bar_label": "Heli kerimisriba", "unread_messages": "Lugemata sõnumid.", "user_menu": "Kasutajamenüü" }, @@ -30,7 +35,7 @@ "click": "Klõpsi", "click_to_copy": "Kopeerimiseks klõpsa", "close": "Sulge", - "collapse": "ahenda", + "collapse": "Ahenda", "complete": "Valmis", "confirm": "Kinnita", "continue": "Jätka", @@ -50,7 +55,7 @@ "enable": "Võta kasutusele", "enter_fullscreen": "Lülita täisekraanivaade sisse", "exit_fullscreeen": "Lülita täisekraanivaade välja", - "expand": "laienda", + "expand": "Laienda", "explore_public_rooms": "Sirvi avalikke jututubasid", "explore_rooms": "Tutvu jututubadega", "export": "Ekspordi", @@ -244,7 +249,6 @@ "completing_setup": "Lõpetame uue seadme seadistamise", "confirm_code_match": "Kontrolli, et järgnev kood klapib teises seadmes kuvatava koodiga:", "connecting": "Kõne on ühendamisel…", - "devices_connected": "Seadmed on ühendatud", "error_device_already_signed_in": "Teine seade on juba võrku loginud.", "error_device_not_signed_in": "Teine seade ei ole võrku loginud.", "error_device_unsupported": "Sidumine selle seadmega ei ole toetatud.", @@ -255,12 +259,10 @@ "error_request_cancelled": "Päring katkestati.", "error_request_declined": "Teine seade lükkas päringu tagasi.", "error_unexpected": "Tekkis teadmata viga.", - "review_and_approve": "Vaata üle ja kinnita sisselogimine Matrixi'i võrku", "scan_code_instruction": "Loe QR-koodi seadmega, kus sa oled Matrix'i võrgust välja loginud.", "scan_qr_code": "Loe QR-koodi", "select_qr_code": "Vali „%(scanQRCode)s“", "sign_in_new_device": "Logi sisse uus seade", - "start_at_sign_in_screen": "Alusta sisselogimisvaatest", "waiting_for_device": "Ootame, et teine seade logiks võrku" }, "register_action": "Loo konto", @@ -319,7 +321,7 @@ "set_email_prompt": "Kas sa soovid seadistada e-posti aadressi?", "sign_in_description": "Jätkamaks kasuta oma kontot.", "sign_in_instead": "Pigem logi sisse", - "sign_in_instead_prompt": "Pigem logi sisse", + "sign_in_instead_prompt": "Sul juba on kasutajakonto olemas?
Siis logi siin sisse", "sign_in_or_register": "Logi sisse või loo uus konto", "sign_in_or_register_description": "Jätkamaks kasuta oma kontot või loo uus konto.", "sign_in_prompt": "Sul on kasutajakonto olemas? Siis logi sisse", @@ -736,7 +738,6 @@ "notification_state": "Teavituste olek: %(notificationState)s", "notifications_debug": "Teavituste silumine", "number_of_users": "Kasutajate arv", - "observe_only": "Ainult vaatle", "original_event_source": "Sündmuse töötlemata lähtekood", "phase": "Faas", "phase_cancelled": "Katkestatud", @@ -744,7 +745,6 @@ "phase_requested": "Päring tehtud", "phase_started": "Alustatud", "phase_transaction": "Transaktsioon", - "requester": "Päringu tegija", "room_encrypted": "Jututuba on krüptitud ✅", "room_id": "Jututoa tunnus: %(roomId)s", "room_not_encrypted": "Jututuba on krüptimata 🚨", @@ -1052,9 +1052,13 @@ "unknown_error_code": "tundmatu veakood", "update_power_level": "Õiguste muutmine ei õnnestunud" }, - "error_app_open_in_another_tab": "%(brand)s on avatud teises vahekaardis.", + "error_app_open_in_another_tab": "%(brand)s'i kasutamiseks ava teine vahekaart. Selle vahekaardi võid kinni panna.", + "error_app_open_in_another_tab_title": "%(brand)s'i on kasutatav teisel vahekaardil", "error_app_opened_in_another_window": "%(brand)s on avatud teises aknas. Klõpsa \"%(label)s\", et kasutada siin %(brand)s ja katkestada teise akna ühendus.", - "error_database_closed_title": "Andmebaasiühendus sulgus ootamatult", + "error_database_closed_description": { + "for_desktop": "Andmekandja maht võib olla täis saanud. Palun tee ruumi juurde ja laadi leht uuesti." + }, + "error_database_closed_title": "%(brand)s lõpetas ootamatult töö", "error_dialog": { "copy_room_link_failed": { "description": "Jututoa lingi kopeerimine lõikelauale ei õnnestunud.", @@ -1299,6 +1303,7 @@ }, "keyboard": { "activate_button": "Aktiveeri valitud nupp", + "alt": "Alt", "autocomplete_cancel": "Lülita automaatne sõnalõpetus välja", "autocomplete_force": "Sunni lõpetama", "autocomplete_navigate_next": "Järgmine sisestussoovitus", @@ -1322,9 +1327,13 @@ "composer_toggle_link": "Lülita link sisse/välja", "composer_toggle_quote": "Lülita tsiteerimine sisse/välja", "composer_undo": "Võta muudatus tagasi", + "control": "Ctrl", "dismiss_read_marker_and_jump_bottom": "Ära arvesta loetud sõnumite järjehoidjat ning mine kõige lõppu", + "end": "End", + "enter": "Enter", + "escape": "Esc", "go_home_view": "Avalehele", - "home": "Avaleht", + "home": "Home", "jump_first_message": "Mine esimese sõnumi juurde", "jump_last_message": "Mine viimase sõnumi juurde", "jump_room_search": "Suundu jututoa otsingusse", @@ -1336,7 +1345,10 @@ "navigate_prev_message_edit": "Muutmiseks liigu eelmise sõnumi juurde", "next_room": "Järgmine otsevestlus või jututuba", "next_unread_room": "Järgmine lugemata otsevestlus või jututuba", + "number": "[number]", "open_user_settings": "Ava kasutaja seadistused", + "page_down": "Page Down", + "page_up": "Page Up", "prev_room": "Eelmine otsevestlus või jututuba", "prev_unread_room": "Eelmine lugemata otsevestlus või jututuba", "room_list_collapse_section": "Ahenda jututubade loendi valikut", @@ -1348,6 +1360,7 @@ "scroll_up_timeline": "Liigu ajajoonel üles", "search": "Otsing (peab olema lubatud)", "send_sticker": "Saada kleeps", + "shift": "Shift", "space": "Tühikuklahv", "switch_to_space": "Vaata kogukonnakeskust tema numbri alusel", "toggle_hidden_events": "Lülita peidetud sündmuste näitamine sisse/välja", @@ -1383,6 +1396,7 @@ "element_call_video_rooms": "Element Call videotoad", "experimental_description": "Soovid katsetada? Proovi meie uusimaid arendusmõtteid. Need funktsionaalsused pole üldsegi veel valmis, nad võivad toimida puudulikult, võivad muutuda või sootuks lõpetamata jääda. Lisateavet leiad siit.", "experimental_section": "Varased arendusjärgud", + "feature_disable_call_per_sender_encryption": "Lülita Element Call'i kasutamisel krüptimine kasutajakohaselt välja", "feature_wysiwyg_composer_description": "Sõnumite kirjutamisel kasuta Markdown'i asemel täisfunktsionaalset küljendust.", "group_calls": "Uus rühmakõnede lahendus", "group_developer": "Arendajad", @@ -1413,11 +1427,17 @@ "new_room_decoration_ui": "Uus jututoa päis ja infovaade on hetkel aktiivses arenduses", "notification_settings": "Uued teavituste seadistused", "notification_settings_beta_title": "Teavituste seadistused", - "oidc_native_flow": "Luba OIDC liidestus (aktiivselt arendamisel)", + "notifications": "Kasuta jututoa päises teavituste riba", + "oidc_native_flow": "OIDC-põhine autentimine", + "oidc_native_flow_description": "⚠ HOIATUS: Kasuta OIDC liidestust, kui server seda võimaldab (aktiivselt arendamisel).", "pinning": "Sõnumite esiletõstmine", "report_to_moderators": "Teata moderaatoritele", "report_to_moderators_description": "Kui jututoas on modereerimine kasutusel, siis nupust „Teata sisust“ avaneva vormi abil saad jututoa reegleid rikkuvast sisust teatada moderaatoritele.", "rust_crypto": "Rust'is teostatud krüptolahendus", + "rust_crypto_in_config": "Rust'i krüptograafiat ei saa selles %(brand)s'i paigalduses välja lülitada", + "rust_crypto_in_config_description": "Rust'i teekidel põhineva krüptograafia kasutusele võtmine eeldab andmete ümbertõstmist ja selleks võib kuluda õige mitu minutit. Hiljem ei saa seda funktsionaalsust enam välja lülitada. Palun ole kindel, et tead, mida teed!", + "rust_crypto_optin_warning": "Rust'i teekidel põhineva krüptograafia kasutusele võtmine eeldab andmete ümbertõstmist ja selleks võib kuluda õige mitu minutit. Selle funktsionaalsuse väljalülitamiseks pead võrgust välja logima ning seejärel tagasi logima. Palun ole kindel, et tead, mida teed!", + "rust_crypto_requires_logout": "Kui Rust'i põhised teegid on kasutusel, siis selle funktsionaalsuse väljalülitamiseks pead võrgust välja logima ning seejärel tagasi logima", "sliding_sync": "Järkjärgulise sünkroniseerimise režiim", "sliding_sync_checking": "Kontrollin…", "sliding_sync_configuration": "Sliding Sync konfiguratsioon", @@ -1476,14 +1496,6 @@ "view_rules": "Näita reegleid" }, "language_dropdown_label": "Keelevalik", - "lazy_loading": { - "disabled_action": "Tühjenda puhver ja sünkroniseeri andmed uuesti", - "disabled_description1": "Oled varem kasutanud %(brand)s serveriga %(host)s ja lubanud andmete laisa laadimise. Selles versioonis on laisk laadimine keelatud. Kuna kohalik vahemälu nende kahe seadistuse vahel ei ühildu, peab %(brand)s sinu konto uuesti sünkroonima.", - "disabled_description2": "Kui %(brand)s teine versioon on mõnel teisel vahekaardil endiselt avatud, palun sulge see. %(brand)s kasutamine samal serveril põhjustab vigu olukorras, kus laisk laadimine on samal ajal lubatud ja keelatud.", - "disabled_title": "Kohalikud andmepuhvrid ei ühildu", - "resync_description": "%(brand)s kasutab varasemaga võrreldes 3-5 korda vähem mälu, sest laadib teavet kasutajate kohta vaid siis, kui vaja. Palun oota hetke, kuni sünkroniseerime andmeid serveriga!", - "resync_title": "Uuendan rakendust %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Sa oled siin viimane osaleja. Kui sa nüüd lahkud, siis mitte keegi, kaasa arvatud sa ise, ei saa hiljem enam liituda.", "leave_room_question": "Kas oled kindel, et soovid lahkuda jututoast „%(roomName)s“?", @@ -1560,6 +1572,7 @@ "toast_description": "%(brand)s toimib nutiseadme veebibrauseris kastseliselt. Parima kasutajakogemuse ja uusima funktsionaalsuse jaoks kasuta meie rakendust.", "toast_title": "Rakendusega saad Matrix'is suhelda parimal viisil" }, + "name_and_id": "%(name)s (%(userId)s)", "no_more_results": "Rohkem otsingutulemusi pole", "notif_panel": { "empty_description": "Sul pole nähtavaid teavitusi.", @@ -2267,6 +2280,8 @@ }, "join_rule_upgrade_upgrading_room": "Uuendan jututoa versiooni", "public_without_alias_warning": "Sellele jututoale viitamiseks palun lisa talle aadress.", + "publish_room": "Tee see jututuba nähtavaks avalikus jututubade kataloogis.", + "publish_space": "Tee see kogukond nähtavaks avalikus jututubade kataloogis.", "strict_encryption": "Ära iialgi saada sellest sessioonist krüptitud sõnumeid verifitseerimata sessioonidesse selles jututoas", "title": "Turvalisus ja privaatsus" }, @@ -2366,7 +2381,7 @@ "layout_irc": "IRC (katseline)", "match_system_theme": "Kasuta süsteemset teemat", "subheading": "Välimuse kohendused kehtivad vaid selles %(brand)s'i sessioonis.", - "timeline_image_size": "Ajajoone piltide suurus", + "timeline_image_size": "Piltide suurus ajajoonel", "use_high_contrast": "Kasuta kontrastset välimust" }, "automatic_language_detection_syntax_highlight": "Kasuta süntaksi esiletõstmisel automaatset keeletuvastust", @@ -2699,6 +2714,7 @@ "device_verified_description": "See sessioon on valmis turvaliseks sõnumivahetuseks.", "device_verified_description_current": "Sinu praegune sessioon on valmis turvaliseks sõnumivahetuseks.", "error_pusher_state": "Tõuketeavituste teenuse oleku määramine ei õnnestunud", + "error_set_name": "Sessiooni nime määramine ei õnnestunud", "filter_all": "Kõik", "filter_inactive": "Pole pidevas kasutuses", "filter_inactive_description": "Pole olnud kasutusel %(inactiveAgeDays)s või enam päeva", @@ -3080,6 +3096,9 @@ "show_thread_filter": "Näita:", "unable_to_decrypt": "Sõnumi dekrüptimine ei õnnestunud" }, + "threads_activity_centre": { + "no_rooms_with_unreads_threads": "Sul veel pole lugemata jutulõngadega jututubasid." + }, "time": { "about_day_ago": "umbes päev tagasi", "about_hour_ago": "umbes tund aega tagasi", @@ -3924,6 +3943,7 @@ "l33t": "Ennustatavatest asendustest nagu '@' 'a' asemel pole eriti kasu", "longerKeyboardPattern": "Kasuta pikemaid klahvikombinatsioone, kus vajutatud klahvid pole kõrvuti ega kohakuti", "noNeed": "Sa ei pea sisestama erilisi tähemärke, numbreid ega suurtähti", + "pwned": "Kui sa kasutad seda salasõna mujalgi, siis palun muuda ta siin ära.", "recentYears": "Väldi hiljutisi aastaid", "repeated": "Väldi korduvaid sõnu ja tähemärke", "reverseWords": "Tagurpidi kirjutatud sõnu pole eriti keeruline ära arvata", @@ -3937,6 +3957,7 @@ "extendedRepeat": "Kordusi, nagu „abcabcabc“ on vaid natuke raskem ära arvata kui „abc“", "keyPattern": "Lühikesi klahvijärjestusi on lihtne ära arvata", "namesByThemselves": "Nimesid ja perenimesid on lihtne ära arvata", + "pwned": "Sinu salasõna on muutunud laiemas internetis toimunud ründe tõttu avalikuks.", "recentYears": "Hiljutisi aastaid on lihtne ära arvata", "sequences": "Jadasid nagu „abc“ või „6543“ on lihtne ära arvata", "similarToCommon": "See on sarnane tavaliselt kasutatavatele salasõnadele", @@ -3944,6 +3965,7 @@ "straightRow": "Klaviatuuril järjest paiknevaid klahvikombinatsioone on lihtne ära arvata", "topHundred": "See on saja levinuima salasõna seas", "topTen": "See on kümne levinuima salasõna seas", + "userInputs": "Siin ei tohiks olla ei isiklikku ega selle lehega seotud andmeid.", "wordByItself": "Üksikut sõna on lihtne ära arvata" } } diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/fa.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/fa.json index 218d7a7e67..aad57928ed 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/fa.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/fa.json @@ -422,12 +422,14 @@ "unmute": "صدادار", "unnamed_room": "اتاق بدون نام", "unnamed_space": "فضای کاری بدون نام", + "user": "کاربر", "user_avatar": "تصویر پروفایل", "username": "نام کاربری", "verification_cancelled": "تأیید هویت لغو شد", "video": "ویدئو", "view_message": "مشاهده پیام", - "warning": "هشدار" + "warning": "هشدار", + "welcome": "خوش آمدید" }, "composer": { "autocomplete": { @@ -1023,14 +1025,6 @@ "view_rules": "مشاهده قوانین" }, "language_dropdown_label": "منو زبان", - "lazy_loading": { - "disabled_action": "پاک کردن حافظه‌ی کش و همگام سازی مجدد", - "disabled_description1": "شما از %(brand)s بر روی %(host)s با قابلیت بارگیری اعضا به شکل تکه‌تکه استفاده می‌کنید. در این نسخه قابلیت بارگیری تکه‌تکه غیرفعال است. از آن‌جایی که حافظه‌ی کش مورد استفاده برای این دو پیکربندی با هم سازگار نیست، %(brand)s نیاز به همگام‌سازی مجدد حساب کاربری شما دارد.", - "disabled_description2": "اگر نسخه دیگری از %(brand)s هنوز در تب‌های دیگر باز است، لطفاً آن را ببندید زیرا استفاده از %(brand)s با قابلیت بارگیری تکه‌تکه‌ی فعال روی یکی و غیرفعال روی دیگری، باعث ایجاد مشکل می شود.", - "disabled_title": "حافظه‌ی محلی ناسازگار", - "resync_description": "هم‌اکنون %(brand)s از طریق بارگیری و نمایش اطلاعات کاربران تنها در زمان‌هایی که نیاز است، حدود ۳ تا ۵ مرتبه حافظه‌ی کمتری استفاده می‌کند. لطفا تا همگام‌سازی با سرور منتظر بمانید!", - "resync_title": "به‌روزرسانی %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "شما در این‌جا تنها هستید. اگر اینجا را ترک کنید، دیگر هیچ‌کس حتی خودتان امکان پیوستن مجدد را نخواهید داشت.", "leave_room_question": "آیا مطمئن هستید که می خواهید از اتاق '2%(roomName)s' خارج شوید؟", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/fi.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/fi.json index 0f8b9b5029..21535ba92b 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/fi.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/fi.json @@ -230,7 +230,6 @@ "phone_optional_label": "Puhelin (valinnainen)", "qr_code_login": { "connecting": "Yhdistetään…", - "devices_connected": "Yhdistetyt laitteet", "error_device_already_signed_in": "Toinen laite on jo sisäänkirjautunut.", "error_device_not_signed_in": "Toinen laite ei ole sisäänkirjautunut.", "error_device_unsupported": "Tämän laitteen kanssa linkittäminen ei ole tuettu.", @@ -240,7 +239,6 @@ "error_request_cancelled": "Pyyntö peruttiin.", "error_request_declined": "Pyyntö hylättiin toiselta laitteelta.", "error_unexpected": "Tapahtui odottamaton virhe.", - "review_and_approve": "Katselmoi ja hyväksy sisäänkirjautuminen", "sign_in_new_device": "Kirjaa sisään uusi laite", "waiting_for_device": "Odotetaan laitteen sisäänkirjautumista" }, @@ -679,7 +677,6 @@ "no_receipt_found": "Kuittausta ei löytynyt", "no_verification_requests_found": "Vahvistuspyyntöjä ei löytynyt", "number_of_users": "Käyttäjämäärä", - "observe_only": "Tarkkaile ainoastaan", "original_event_source": "Alkuperäinen tapahtumalähde", "phase": "Vaihe", "phase_cancelled": "Peruttu", @@ -687,7 +684,6 @@ "phase_requested": "Pyydetty", "phase_started": "Käynnistetty", "phase_transaction": "Transaktio", - "requester": "Pyytäjä", "room_id": "Huoneen ID-tunniste: %(roomId)s", "room_notifications_sender": "Lähettäjä: ", "save_setting_values": "Tallenna asetusarvot", @@ -1309,14 +1305,6 @@ "view_rules": "Näytä säännöt" }, "language_dropdown_label": "Kielipudotusvalikko", - "lazy_loading": { - "disabled_action": "Tyhjennä välimuisti ja hae tiedot uudelleen", - "disabled_description1": "Olet aikaisemmin käytttänyt %(brand)sia laitteella %(host)s, jossa oli jäsenten laiska lataus käytössä. Tässä versiossa laiska lataus on pois käytöstä. Koska paikallinen välimuisti ei ole yhteensopiva näiden kahden asetuksen välillä, %(brand)sin täytyy synkronoida tilisi tiedot uudelleen.", - "disabled_description2": "Jos sinulla on toinen %(brand)sin versio edelleen auki toisessa välilehdessä, suljethan sen, koska %(brand)sin käyttäminen samalla laitteella niin, että laiska lataus on toisessa välilehdessä käytössä ja toisessa ei, aiheuttaa ongelmia.", - "disabled_title": "Yhteensopimaton paikallinen välimuisti", - "resync_description": "%(brand)s käyttää nyt 3-5 kertaa vähemmän muistia, koska se lataa tietoa muista käyttäjistä vain tarvittaessa. Odotathan, kun haemme tarvittavat tiedot palvelimelta!", - "resync_title": "Päivitetään %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Olet ainoa henkilö täällä. Jos lähdet, kukaan ei voi liittyä tulevaisuudessa, et myöskään sinä.", "leave_room_question": "Oletko varma että haluat poistua huoneesta '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/fr.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/fr.json index 8fde6ba262..30441221cb 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/fr.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/fr.json @@ -249,7 +249,6 @@ "completing_setup": "Fin de la configuration de votre nouvel appareil", "confirm_code_match": "Vérifiez que le code ci-dessous correspond à celui sur votre autre appareil :", "connecting": "Connexion…", - "devices_connected": "Appareils connectés", "error_device_already_signed_in": "L’autre appareil est déjà connecté.", "error_device_not_signed_in": "L’autre appareil n’est pas connecté.", "error_device_unsupported": "L’appairage avec cet appareil n’est pas pris en charge.", @@ -260,12 +259,10 @@ "error_request_cancelled": "La demande a été annulée.", "error_request_declined": "La requête a été refusée sur l’autre appareil.", "error_unexpected": "Une erreur inattendue s’est produite.", - "review_and_approve": "Vérifier et autoriser la connexion", "scan_code_instruction": "Scannez le QR code ci-dessous avec l’appareil qui n’est pas connecté.", "scan_qr_code": "Scanner le QR code", "select_qr_code": "Sélectionnez « %(scanQRCode)s »", "sign_in_new_device": "Connecter le nouvel appareil", - "start_at_sign_in_screen": "Démarrez à l’écran de connexion", "waiting_for_device": "En attente de connexion de l’appareil" }, "register_action": "Créer un compte", @@ -742,7 +739,6 @@ "notification_state": "L’état des notifications est %(notificationState)s", "notifications_debug": "Débogage des notifications", "number_of_users": "Nombre d’utilisateurs", - "observe_only": "Observer uniquement", "original_event_source": "Évènement source original", "phase": "Phase", "phase_cancelled": "Annulé", @@ -750,7 +746,6 @@ "phase_requested": "Envoyé", "phase_started": "Démarré", "phase_transaction": "Transaction", - "requester": "Demandeur", "room_encrypted": "Le salon est chiffré ✅", "room_id": "Identifiant du salon : %(roomId)s", "room_not_encrypted": "Le salon n’est pas chiffré 🚨", @@ -763,6 +758,7 @@ "room_notifications_type": "Type : ", "room_status": "Statut du salon", "room_unread_status_count": { + "one": "Statut non-lus du salon : %(status)s, total : %(count)s", "other": "Statut non-lus du salon : %(status)s, total : %(count)s" }, "save_setting_values": "Enregistrer les valeurs des paramètres", @@ -1016,7 +1012,7 @@ "verify_reset_warning_1": "La réinitialisation de vos clés de vérification ne peut pas être annulé. Après la réinitialisation, vous n’aurez plus accès à vos anciens messages chiffrés, et tous les amis que vous aviez précédemment vérifiés verront des avertissement de sécurité jusqu'à ce vous les vérifiiez à nouveau.", "verify_reset_warning_2": "Veuillez ne continuer que si vous êtes certain d’avoir perdu tous vos autres appareils et votre Clé de Sécurité.", "verify_using_device": "Vérifier avec un autre appareil", - "verify_using_key": "Vérifié avec une clé de sécurité", + "verify_using_key": "Vérifier avec une clé de sécurité", "verify_using_key_or_phrase": "Vérifier avec une clé de sécurité ou une phrase", "waiting_for_user_accept": "En attente d’acceptation par %(displayName)s…", "waiting_other_device": "En attente de votre vérification sur votre autre appareil…", @@ -1510,14 +1506,6 @@ "view_rules": "Voir les règles" }, "language_dropdown_label": "Sélection de la langue", - "lazy_loading": { - "disabled_action": "Vider le cache et resynchroniser", - "disabled_description1": "Vous avez utilisé auparavant %(brand)s sur %(host)s avec le chargement différé activé. Dans cette version le chargement différé est désactivé. Comme le cache local n’est pas compatible entre ces deux réglages, %(brand)s doit resynchroniser votre compte.", - "disabled_description2": "Si l’autre version de %(brand)s est encore ouverte dans un autre onglet, merci de le fermer car l’utilisation de %(brand)s sur le même hôte avec le chargement différé activé et désactivé à la fois causera des problèmes.", - "disabled_title": "Cache local incompatible", - "resync_description": "%(brand)s utilise maintenant 3 à 5 fois moins de mémoire, en ne chargeant les informations des autres utilisateurs que quand elles sont nécessaires. Veuillez patienter pendant que l’on se resynchronise avec le serveur !", - "resync_title": "Mise à jour de %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Vous êtes la seule personne ici. Si vous partez, plus personne ne pourra rejoindre cette conversation, y compris vous.", "leave_room_question": "Voulez-vous vraiment quitter le salon « %(roomName)s » ?", @@ -2627,6 +2615,7 @@ "voip": "Appels audio et vidéo" }, "preferences": { + "Electron.enableHardwareAcceleration": "Activer l’accélération matérielle (redémarrez %(appName)s pour l'activer)", "always_show_menu_bar": "Toujours afficher la barre de menu de la fenêtre", "autocomplete_delay": "Délai pour l’autocomplétion (ms)", "code_blocks_heading": "Blocs de code", @@ -3488,6 +3477,7 @@ "other": "%(severalUsers)s ont changé de nom %(count)s fois", "one": "%(severalUsers)s ont changé de nom" }, + "format": "%(nameList)s %(transitionList)s", "hidden_event": { "one": "%(oneUser)s a envoyé un message caché", "other": "%(oneUser)s ont envoyé %(count)s messages cachés" diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/gl.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/gl.json index a1674da80b..e58b0ea5ad 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/gl.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/gl.json @@ -619,7 +619,6 @@ "methods": "Métodos", "no_verification_requests_found": "Non se atopan solicitudes de verificación", "number_of_users": "Número de usuarias", - "observe_only": "Só observar", "original_event_source": "Fonte orixinal do evento", "phase": "Fase", "phase_cancelled": "Cancelado", @@ -627,7 +626,6 @@ "phase_requested": "Solicitado", "phase_started": "Iniciado", "phase_transaction": "Transacción", - "requester": "Solicitante", "room_id": "ID da sala: %(roomId)s", "save_setting_values": "Gardar valores configurados", "send_custom_account_data_event": "Enviar evento de datos da conta personalizado", @@ -1263,14 +1261,6 @@ "view_rules": "Ver regras" }, "language_dropdown_label": "Selector de idioma", - "lazy_loading": { - "disabled_action": "Baleirar caché e sincronizar", - "disabled_description1": "Anteriormente utilizaches %(brand)s en %(host)s con carga preguiceira de membros. Nesta versión a carga preguiceira está desactivada. Como a caché local non é compatible entre as dúas configuracións, %(brand)s precisa volver a sincronizar a conta.", - "disabled_description2": "Se a outra versión de %(brand)s aínda está aberta noutra lapela, péchaa xa que usar %(brand)s no mesmo servidor con carga preguiceira activada e desactivada ao mesmo tempo causará problemas.", - "disabled_title": "Caché local incompatible", - "resync_description": "%(brand)s utiliza agora entre 3 e 5 veces menos memoria, cargando só información sobre as usuarias cando é preciso. Agarda mentras se sincroniza co servidor!", - "resync_title": "Actualizando %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Es a única persoa aquí. Se saes, ninguén poderá unirse no futuro, incluíndote a ti.", "leave_room_question": "Seguro que desexa saír da sala '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/he.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/he.json index e67efcb256..3a3c2ad736 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/he.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/he.json @@ -1057,14 +1057,6 @@ "view_rules": "צפה בכללים" }, "language_dropdown_label": "תפריט שפות", - "lazy_loading": { - "disabled_action": "נקה מטמון וסנכרן מחדש", - "disabled_description1": "השתמשת בעבר ב- %(brand)s ב- %(host)s עם טעינה עצלה של חברים מופעלת. בגרסה זו טעינה עצלה מושבתת. מכיוון שהמטמון המקומי אינו תואם בין שתי ההגדרות הללו, %(brand)s צריך לסנכרן מחדש את חשבונך.", - "disabled_description2": "אם הגרסה האחרת של %(brand)s עדיין פתוחה בכרטיסייה אחרת, אנא סגור אותה כשימוש ב-%(brand)s באותו מארח כאשר טעינה עצלה מופעלת וגם מושבתת בו זמנית תגרום לבעיות.", - "disabled_title": "מטמון מקומי לא תואם", - "resync_description": "%(brand)s משתמש כעת בזכרון פחות פי 3-5, על ידי טעינת מידע רק על משתמשים אחרים בעת הצורך. אנא המתן בזמן שאנחנו מסתנכרנים מחדש עם השרת!", - "resync_title": "מעדכן %(brand)s" - }, "leave_room_dialog": { "leave_room_question": "האם אתה בטוח שברצונך לעזוב את החדר '%(roomName)s'?", "room_rejoin_warning": "חדר זה אינו ציבורי. לא תוכל להצטרף שוב ללא הזמנה." diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/hu.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/hu.json index c3712453b5..69988db429 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/hu.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/hu.json @@ -243,7 +243,6 @@ "completing_setup": "Új eszköz beállításának elvégzése", "confirm_code_match": "Ellenőrizze, hogy az alábbi kód megegyezik a másik eszközödön lévővel:", "connecting": "Kapcsolás…", - "devices_connected": "Összekötött eszközök", "error_device_already_signed_in": "A másik eszköz már bejelentkezett.", "error_device_not_signed_in": "A másik eszköz még nincs bejelentkezve.", "error_device_unsupported": "Összekötés ezzel az eszközzel nem támogatott.", @@ -253,12 +252,10 @@ "error_request_cancelled": "A kérés megszakítva.", "error_request_declined": "A kérést elutasították a másik eszközön.", "error_unexpected": "Nemvárt hiba történt.", - "review_and_approve": "Belépés áttekintése és engedélyezés", "scan_code_instruction": "A kijelentkezett eszközzel olvasd be a QR kódot alább.", "scan_qr_code": "QR kód beolvasása", "select_qr_code": "Kiválasztás „%(scanQRCode)s”", "sign_in_new_device": "Új eszköz bejelentkeztetése", - "start_at_sign_in_screen": "Kezdje a bejelentkező képernyőn", "waiting_for_device": "Várakozás a másik eszköz bejelentkezésére" }, "register_action": "Fiók létrehozása", @@ -371,25 +368,25 @@ "verify_email_heading": "E-mail ellenőrzés a továbblépéshez" }, "bug_reporting": { - "additional_context": "Ha a hiba felderítésében további adat is segítséget adhat, mint az, hogy mit csináltál éppen, mi a szoba-, felhasználó azonosítója, stb... itt add meg.", - "before_submitting": "Mielőtt a naplót elküldöd, egy Github jegyet kell nyitni amiben leírod a problémádat.", + "additional_context": "Ha a hiba felderítésében további adatok is segíthetnek, mint az, hogy mit csinált épp, mik a szobák vagy felhasználók azonosítói, stb. Ezeket itt adja meg.", + "before_submitting": "Mielőtt elküldi a naplókat, hozzon létre egy jegyet a GitHubon, amelyben leírja a problémáját.", "collecting_information": "Alkalmazás verzióinformációinak összegyűjtése", "collecting_logs": "Naplók összegyűjtése", "create_new_issue": "Ahhoz hogy megvizsgálhassuk a hibát, hozzon létre egy új hibajegyet a GitHubon.", - "description": "A hibakeresési napló alkalmazáshasználati adatokat tartalmaz, amely tartalmazza a felhasználónevét, a felkeresett szobák azonosítóit vagy álneveit, az utolsó felhasználói felület elemét, amelyet használt, valamint a többi felhasználó neveit. A csevegési üzenetek szövegét nem tartalmazza.", - "download_logs": "Napló letöltése", + "description": "A hibakeresési naplók alkalmazáshasználati adatokat tartalmaznak, amelyek tartalmazzák a felkeresett szobák azonosítóit vagy álneveit, a legutóbb használt felületi elemeket, valamint a többi felhasználó neveit. A csevegőüzenetek szövegét nem tartalmazza.", + "download_logs": "Naplók letöltése", "downloading_logs": "Naplók letöltése folyamatban", "error_empty": "Kérlek mond el nekünk mi az ami nem működött, vagy még jobb, ha egy GitHub jegyben leírod a problémát.", "failed_send_logs": "Hiba a napló küldésénél: ", - "github_issue": "GitHub hibajegy", - "introduction": "Ha a GitHubon keresztül küldött be hibajegyet, akkor a hibakeresési napló segít nekünk felderíteni a problémát. ", + "github_issue": "GitHub-jegy", + "introduction": "Ha a GitHubon keresztül küldött be hibajegyet, akkor a hibakeresési naplók segítenek nekünk felderíteni a problémát. ", "log_request": "Segítsen abban, hogy ez később ne fordulhasson elő, küldje el nekünk a naplókat.", "logs_sent": "Napló elküldve", "matrix_security_issue": "A Matrixszal kapcsolatos biztonsági hibák jelentésével kapcsolatban olvassa el a Matrix.org biztonsági hibák közzétételi házirendjét.", "preparing_download": "Napló előkészítése feltöltéshez", "preparing_logs": "Előkészülés napló küldéshez", - "send_logs": "Naplófájlok elküldése", - "submit_debug_logs": "Hibakeresési napló elküldése", + "send_logs": "Naplók elküldése", + "submit_debug_logs": "Hibakeresési naplók elküldése", "textarea_label": "Megjegyzések", "thank_you": "Köszönjük!", "title": "Hibajelentés", @@ -575,9 +572,9 @@ "close_sticker_picker": "Matricák elrejtése", "edit_composer_label": "Üzenet szerkesztése", "format_bold": "Félkövér", - "format_code_block": "Kód blokk", - "format_decrease_indent": "Behúzás csökkentés", - "format_increase_indent": "Behúzás növelés", + "format_code_block": "Kódblokk", + "format_decrease_indent": "Behúzás csökkentése", + "format_increase_indent": "Behúzás növelése", "format_inline_code": "Kód", "format_insert_link": "Link beillesztése", "format_italic": "Dőlt", @@ -620,7 +617,7 @@ "console_wait": "Várjon!", "create_room": { "action_create_room": "Szoba létrehozása", - "action_create_video_room": "Videó szoba készítése", + "action_create_video_room": "Videószoba létrehozása", "encrypted_video_room_warning": "Ezt később nem lehet kikapcsolni. A szoba titkosítva lesz de a hívások nem.", "encrypted_warning": "Ezt később nem lehet kikapcsolni. A hidak és a legtöbb bot nem fog működni egyenlőre.", "encryption_forced": "A szervered megköveteli, hogy a titkosítás be legyen kapcsolva a privát szobákban.", @@ -639,7 +636,7 @@ "room_visibility_label": "Szoba láthatóság", "title_private_room": "Privát szoba létrehozása", "title_public_room": "Nyilvános szoba létrehozása", - "title_video_room": "Videó szoba készítése", + "title_video_room": "Videószoba létrehozása", "topic_label": "Téma (nem kötelező)", "unfederated": "A szobába ne léphessenek be azok, akik nem ezen a szerveren vannak: %(serverName)s.", "unfederated_label_default_off": "Beállíthatod, ha a szobát csak egy belső csoport használja majd a matrix szervereden. Ezt később nem lehet megváltoztatni.", @@ -716,7 +713,7 @@ "event_type": "Esemény típusa", "explore_account_data": "Fiókadatok felderítése", "explore_room_account_data": "Szoba fiók adatok felderítése", - "explore_room_state": "Szoba állapot felderítése", + "explore_room_state": "Szobaállapot felderítése", "failed_to_find_widget": "Hiba történt a kisalkalmazás keresése során.", "failed_to_load": "Betöltés sikertelen.", "failed_to_save": "A beállítások elmentése nem sikerült.", @@ -733,7 +730,6 @@ "notification_state": "Értesítés állapot: %(notificationState)s", "notifications_debug": "Értesítések hibakeresése", "number_of_users": "Felhasználószám", - "observe_only": "Csak megfigyel", "original_event_source": "Eredeti esemény forráskód", "phase": "Fázis", "phase_cancelled": "Megszakítva", @@ -741,7 +737,6 @@ "phase_requested": "Kérve", "phase_started": "Elindult", "phase_transaction": "Tranzakció", - "requester": "Kérelmező", "room_encrypted": "A szoba titkosított ✅", "room_id": "Szoba azon.: %(roomId)s", "room_not_encrypted": "A szoba nincs titkosítva 🚨", @@ -761,7 +756,7 @@ "send_custom_account_data_event": "Egyedi fiókadat esemény küldése", "send_custom_room_account_data_event": "Egyedi szoba fiókadat esemény küldése", "send_custom_state_event": "Egyedi állapotesemény küldése", - "send_custom_timeline_event": "Egyedi idővonal esemény küldése", + "send_custom_timeline_event": "Egyéni idővonal-esemény küldése", "server_info": "Kiszolgálóinformációk", "server_versions": "Kiszolgálóverziók", "settable_global": "Általánosan beállítható", @@ -1474,14 +1469,6 @@ "view_rules": "Szabályok megtekintése" }, "language_dropdown_label": "Nyelvválasztó lenyíló menü", - "lazy_loading": { - "disabled_action": "Gyorsítótár törlése és újraszinkronizálás", - "disabled_description1": "Előzőleg a szoba tagság késleltetett betöltésének engedélyével itt használtad a %(brand)sot: %(host)s. Ebben a verzióban viszont a késleltetett betöltés nem engedélyezett. Mivel a két gyorsítótár nem kompatibilis egymással így %(brand)snak újra kell szinkronizálnia a fiókot.", - "disabled_description2": "Ha a másik %(brand)s verzió még fut egy másik fülön, akkor zárja be, mert ha egy gépen használja a %(brand)sot úgy, hogy az egyiken be van kapcsolva a késleltetett betöltés, a másikon pedig ki, akkor problémák adódhatnak.", - "disabled_title": "A helyi gyorsítótár nem kompatibilis ezzel a verzióval", - "resync_description": "Az %(brand)s harmad-ötöd annyi memóriát használ azáltal, hogy csak akkor tölti be a felhasználók információit, amikor az szükséges. Kis türelmet, amíg megtörténik az újbóli szinkronizálás a kiszolgálóval.", - "resync_title": "%(brand)s frissítése" - }, "leave_room_dialog": { "last_person_warning": "Csak ön van itt. Ha kilép, akkor a jövőben senki nem tud majd ide belépni, beleértve önt is.", "leave_room_question": "Biztos, hogy elhagyja a(z) „%(roomName)s” szobát?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/id.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/id.json index 3a760aeb47..4f942d89da 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/id.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/id.json @@ -243,7 +243,6 @@ "completing_setup": "Menyelesaikan penyiapan perangkat baru Anda", "confirm_code_match": "Periksa bahwa kode di bawah cocok dengan perangkat Anda yang lain:", "connecting": "Menghubungkan…", - "devices_connected": "Perangkat terhubung", "error_device_already_signed_in": "Perangkat yang lain sudah masuk.", "error_device_not_signed_in": "Perangkat yang lain belum masuk.", "error_device_unsupported": "Penautan dengan perangkat ini tidak didukung.", @@ -253,12 +252,10 @@ "error_request_cancelled": "Permintaan dibatalkan.", "error_request_declined": "Permintaan ditolak di perangkat yang lain.", "error_unexpected": "Sebuah kesalahan terjadi secara tidak terduga.", - "review_and_approve": "Lihat dan perbolehkan pemasukan", "scan_code_instruction": "Pindai kode QR di bawah dengan perangkat Anda yang sudah keluar dari akun.", "scan_qr_code": "Pindai kode QR", "select_qr_code": "Pilih '%(scanQRCode)s'", "sign_in_new_device": "Masuk perangkat baru", - "start_at_sign_in_screen": "Mulai dari layar masuk", "waiting_for_device": "Menunggu perangkat untuk masuk" }, "register_action": "Buat Akun", @@ -732,7 +729,6 @@ "notification_state": "Keadaan notifikasi adalah %(notificationState)s", "notifications_debug": "Pengawakutuan notifikasi", "number_of_users": "Jumlah pengguna", - "observe_only": "Lihat saja", "original_event_source": "Sumber peristiwa asli", "phase": "Masa", "phase_cancelled": "Dibatalkan", @@ -740,7 +736,6 @@ "phase_requested": "Diminta", "phase_started": "Dimulai", "phase_transaction": "Transaksi", - "requester": "Peminta", "room_encrypted": "Ruangan terenkripsi ✅", "room_id": "ID ruangan: %(roomId)s", "room_not_encrypted": "Ruangan tidak terenkripsi 🚨", @@ -1412,9 +1407,13 @@ "msc3531_hide_messages_pending_moderation": "Memperbolehkan moderator untuk menyembunyikan pesan yang akan dimoderasikan.", "new_room_decoration_ui": "Dalam pengembangan aktif, tajuk ruangan & antarmuka detail baru", "notification_settings": "Pengaturan Notifikasi Baru", + "notification_settings_beta_caption": "Perkenalkan cara yang lebih sederhana untuk mengubah pengaturan notifikasi Anda. Sesuaikan %(brand)s Anda, sesuai keinginan Anda.", "notification_settings_beta_title": "Pengaturan Notifikasi", - "oidc_native_flow": "Aktifkan alur OIDC native baru (Dalam pengembangan aktif)", + "notifications": "Aktifkan panel notifikasi di tajuk ruangan", + "oidc_native_flow": "Autentikasi asli OIDC", "pinning": "Pin Pesan", + "render_reaction_images": "Render gambar khusus dalam reaksi", + "render_reaction_images_description": "Terkadang disebut sebagai \"emoji khusus\".", "report_to_moderators": "Laporkan ke moderator", "report_to_moderators_description": "Dalam ruangan yang mendukung moderasi, tombol “Laporkan” memungkinkan Anda untuk melaporkan penyalahgunaan ke moderator ruangan.", "rust_crypto": "Implementasi kriptografi Rust", @@ -1430,6 +1429,7 @@ "sliding_sync_server_specify_proxy": "Server Anda belum mendukungnya, Anda harus menetapkan sebuah proksi", "sliding_sync_server_support": "Server Anda mendukungnya", "under_active_development": "Dalam pengembangan aktif.", + "unrealiable_e2e": "Tidak dapat diandalkan di ruangan terenkripsi", "video_rooms": "Ruangan video", "video_rooms_a_new_way_to_chat": "Sebuah cara baru untuk mengobrol melalui suara dan video di %(brand)s.", "video_rooms_always_on_voip_channels": "Ruangan video adalah saluran VoIP yang selalu ada tersemat di dalam sebuah ruangan di %(brand)s.", @@ -1477,14 +1477,6 @@ "view_rules": "Tampilkan aturan" }, "language_dropdown_label": "Dropdown Bahasa", - "lazy_loading": { - "disabled_action": "Hapus cache dan sinkron ulang", - "disabled_description1": "Anda sebelumnya menggunakan %(brand)s di %(host)s dengan pemuatan malas pengguna diaktifkan. Di versi ini pemuatan malas dinonaktifkan. Karena cache lokal tidak kompatibel antara dua pengaturan ini, %(brand)s harus mengsinkronisasi ulang akun Anda.", - "disabled_description2": "Jika versi %(brand)s yang lain masih terbuka di tab yang lain, mohon menutupnya karena menggunakan %(brand)s di host yang sama dengan pemuatan malas diaktifkan dan dinonaktifkan secara bersamaan akan mengakibatkan masalah.", - "disabled_title": "Cache lokal tidak kompatibel", - "resync_description": "%(brand)s sekarang menggunakan memori 3-5x kecil dari sebelumnya dengan hanya memuat informasi tentang pengguna lain jika dibutuhkan. Mohon tunggu selagi kita mengsinkronisasi ulang dengan servernya!", - "resync_title": "Memperbarui %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Anda adalah satu-satunya di sini. Jika Anda keluar, tidak ada siapa saja dapat bergabung di masa mendatang, termasuk Anda.", "leave_room_question": "Anda yakin ingin meninggalkan ruangan '%(roomName)s'?", @@ -2277,6 +2269,7 @@ }, "join_rule_upgrade_upgrading_room": "Meningkatkan ruangan", "public_without_alias_warning": "Untuk menautkan ruangan ini, mohon tambahkan sebuah alamat.", + "publish_space": "Buat ruang ini terlihat di direktori ruangan publik.", "strict_encryption": "Jangan kirim pesan terenkripsi ke sesi yang belum diverifikasi di ruangan ini dari sesi ini", "title": "Keamanan & Privasi" }, diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/is.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/is.json index 2663a0eaef..8c8122b30b 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/is.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/is.json @@ -219,7 +219,6 @@ "phone_optional_label": "Sími (valfrjálst)", "qr_code_login": { "error_invalid_scanned_code": "Skannaði kóðinn er ógildur.", - "review_and_approve": "Yfirfarðu og samþykktu innskráninguna", "sign_in_new_device": "Skrá inn nýtt tæki", "waiting_for_device": "Bíð eftir að tækið skráist inn" }, @@ -630,14 +629,12 @@ "methods": "Aðferðir", "no_verification_requests_found": "Engar staðfestingarbeiðnir fundust", "number_of_users": "Fjöldi notenda", - "observe_only": "Aðeins fylgjast með", "phase": "Fasi", "phase_cancelled": "Hætt við", "phase_ready": "Tilbúið", "phase_requested": "Umbeðið", "phase_started": "Hafið", "phase_transaction": "Færsluaðgerð", - "requester": "Beiðandi", "room_id": "Auðkenni spjallrásar: %(roomId)s", "save_setting_values": "Vista gildi valkosta", "send_custom_state_event": "Senda sérsniðinn stöðuatburð", @@ -1154,6 +1151,7 @@ "group_rooms": "Spjallrásir", "group_spaces": "Svæði", "group_themes": "Þemu", + "group_threads": "Spjallþræðir", "group_voip": "Tal og myndmerki", "group_widgets": "Viðmótshlutar", "html_topic": "Birta HTML-framsetningu umfjöllunarefnis spjallrása", @@ -1212,11 +1210,6 @@ "view_rules": "Skoða reglur" }, "language_dropdown_label": "Fellilisti tungumála", - "lazy_loading": { - "disabled_action": "Hreinsa skyndiminni og endursamstilla", - "disabled_title": "Ósamhæft staðvært skyndiminni", - "resync_title": "Uppfæri %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Þú ert eini eintaklingurinn hérna. Ef þú ferð út, mun enginn framar geta tekið þátt, að þér meðtöldum.", "leave_room_question": "Ertu viss um að þú viljir yfirgefa spjallrásina '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/it.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/it.json index 94c30e89f2..46085e1050 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/it.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/it.json @@ -249,7 +249,6 @@ "completing_setup": "Completamento configurazione nuovo dispositivo", "confirm_code_match": "Controlla che il codice sottostante corrisponda nell'altro dispositivo:", "connecting": "In connessione…", - "devices_connected": "Dispositivo connesso", "error_device_already_signed_in": "L'altro dispositivo ha già fatto l'accesso.", "error_device_not_signed_in": "L'altro dispositivo non ha fatto l'accesso.", "error_device_unsupported": "Il collegamento con questo dispositivo non è supportato.", @@ -260,12 +259,10 @@ "error_request_cancelled": "La richiesta è stata annullata.", "error_request_declined": "La richiesta è stata negata sull'altro dispositivo.", "error_unexpected": "Si è verificato un errore imprevisto.", - "review_and_approve": "Verifica e approva l'accesso", "scan_code_instruction": "Scansiona il codice QR sottostante con il dispositivo che è disconnesso.", "scan_qr_code": "Scansiona codice QR", "select_qr_code": "Seleziona '%(scanQRCode)s'", "sign_in_new_device": "Accedi nel nuovo dispositivo", - "start_at_sign_in_screen": "Inizia nella schermata di accesso", "waiting_for_device": "In attesa che il dispositivo acceda" }, "register_action": "Crea account", @@ -742,7 +739,6 @@ "notification_state": "Lo stato di notifica è %(notificationState)s", "notifications_debug": "Debug notifiche", "number_of_users": "Numero di utenti", - "observe_only": "Osserva solo", "original_event_source": "Sorgente dell'evento originale", "phase": "Fase", "phase_cancelled": "Annullato", @@ -750,7 +746,6 @@ "phase_requested": "Richiesto", "phase_started": "Iniziato", "phase_transaction": "Transazione", - "requester": "Richiedente", "room_encrypted": "La stanza è crittografata ✅", "room_id": "ID stanza: %(roomId)s", "room_not_encrypted": "La stanza non è crittografata 🚨", @@ -1511,14 +1506,6 @@ "view_rules": "Vedi regole" }, "language_dropdown_label": "Lingua a tendina", - "lazy_loading": { - "disabled_action": "Svuota cache e risincronizza", - "disabled_description1": "Hai usato %(brand)s precedentemente su %(host)s con il caricamento lento dei membri attivato. In questa versione il caricamento lento è disattivato. Dato che la cache locale non è compatibile tra queste due impostazioni, %(brand)s deve risincronizzare il tuo account.", - "disabled_description2": "Se l'altra versione di %(brand)s è ancora aperta in un'altra scheda, chiudila perché usare %(brand)s nello stesso host con il caricamento lento sia attivato che disattivato può causare errori.", - "disabled_title": "Cache locale non compatibile", - "resync_description": "%(brand)s ora usa da 3 a 5 volte meno memoria, caricando le informazioni degli altri utenti solo quando serve. Si prega di attendere mentre ci risincronizziamo con il server!", - "resync_title": "Aggiornamento di %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Sei l'unica persona qui. Se esci, nessuno potrà entrare in futuro, incluso te.", "leave_room_question": "Sei sicuro di volere uscire dalla stanza '%(roomName)s'?", @@ -2422,6 +2409,7 @@ "custom_theme_success": "Tema aggiunto!", "custom_theme_url": "URL tema personalizzato", "font_size": "Dimensione carattere", + "font_size_default": "%(fontSize)s (predefinito)", "heading": "Personalizza l'aspetto", "image_size_default": "Predefinito", "image_size_large": "Grande", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/ja.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/ja.json index 40db2f6efb..22a17aabde 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/ja.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/ja.json @@ -233,7 +233,6 @@ "completing_setup": "新しい端末の設定を完了しています", "confirm_code_match": "以下のコードが他の端末と一致していることを確認してください:", "connecting": "接続しています…", - "devices_connected": "接続中の端末", "error_device_already_signed_in": "もう一方のデバイスは既にサインインしています。", "error_device_not_signed_in": "もう一方の端末はサインインしていません。", "error_device_unsupported": "この端末とのリンクはサポートしていません。", @@ -244,12 +243,10 @@ "error_request_cancelled": "リクエストはキャンセルされました。", "error_request_declined": "リクエストはもう一方の端末で拒否されました。", "error_unexpected": "予期しないエラーが発生しました。", - "review_and_approve": "サインインを確認して承認", "scan_code_instruction": "サインアウトした端末で以下のQRコードをスキャンしてください。", "scan_qr_code": "QRコードをスキャン", "select_qr_code": "「%(scanQRCode)s」を選択", "sign_in_new_device": "新しい端末でサインイン", - "start_at_sign_in_screen": "サインインの画面で開始", "waiting_for_device": "端末のサインインを待機しています" }, "register_action": "アカウントを作成", @@ -706,7 +703,6 @@ "no_verification_requests_found": "認証リクエストがありません", "notifications_debug": "通知のデバッグ", "number_of_users": "ユーザー数", - "observe_only": "観察のみ", "original_event_source": "元のイベントのソースコード", "phase": "フェーズ", "phase_cancelled": "キャンセル済", @@ -714,7 +710,6 @@ "phase_requested": "要求済", "phase_started": "開始済", "phase_transaction": "トランザクション", - "requester": "リクエストしたユーザー", "room_id": "ルームID:%(roomId)s", "room_notifications_dot": "ドット: ", "room_notifications_highlight": "ハイライト: ", @@ -1399,14 +1394,6 @@ "view_rules": "ルールを表示" }, "language_dropdown_label": "言語一覧", - "lazy_loading": { - "disabled_action": "キャッシュをクリアして再同期", - "disabled_description1": "以前%(host)sにて、メンバーの遅延ロードを有効にした%(brand)sが使用されていました。このバージョンでは、遅延ロードは無効です。ローカルのキャッシュにはこれらの2つの設定の間での互換性がないため、%(brand)sはアカウントを再同期する必要があります。", - "disabled_description2": "他のバージョンの%(brand)sが別のタブで開いている場合は、それを閉じてください。同じホスト上で遅延ロードを有効と無効の両方に設定して%(brand)sを使用すると、問題が発生します。", - "disabled_title": "互換性のないローカルキャッシュ", - "resync_description": "%(brand)sは、必要なときだけに他のユーザーに関する情報を読み込むようにすることで、メモリの使用量を3〜5倍減らしました。サーバーと再同期するのを待ってください!", - "resync_title": "%(brand)sを更新しています" - }, "leave_room_dialog": { "last_person_warning": "このルームの参加者はあなただけです。退出すると、今後あなたを含めて誰もこのルームに参加できなくなります。", "leave_room_question": "このルーム「%(roomName)s」から退出してよろしいですか?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/lo.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/lo.json index 524026be87..72f90e0f0a 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/lo.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/lo.json @@ -616,7 +616,6 @@ "methods": "ວິທີການ", "no_verification_requests_found": "ບໍ່ພົບການຮ້ອງຂໍການຢັ້ງຢືນ", "number_of_users": "ຈໍານວນຜູ້ໃຊ້", - "observe_only": "ສັງເກດເທົ່ານັ້ນ", "original_event_source": "ແຫຼ່ງຕົ້ນສະບັບ", "phase": "ໄລຍະ", "phase_cancelled": "ຍົກເລີກ", @@ -624,7 +623,6 @@ "phase_requested": "ຮ້ອງຂໍ", "phase_started": "ໄດ້ເລີ່ມແລ້ວ", "phase_transaction": "ທຸລະກໍາ", - "requester": "ຜູ້ຮ້ອງຂໍ", "room_id": "ID ຫ້ອງ: %(roomId)s", "save_setting_values": "ບັນທຶກຄ່າການຕັ້ງຄ່າ", "send_custom_account_data_event": "ສົ່ງຂໍ້ມູນບັນຊີແບບກຳນົດເອງທຸກເຫດການ", @@ -1184,6 +1182,7 @@ "group_rooms": "ຫ້ອງ", "group_spaces": "ພື້ນທີ່", "group_themes": "ຫົວຂໍ້", + "group_threads": "ກະທູ້", "group_voip": "ສຽງ & ວິດີໂອ", "group_widgets": "ວິດເຈັດ", "join_beta": "ເຂົ້າຮ່ວມເບຕ້າ", @@ -1226,14 +1225,6 @@ "view_rules": "ເບິ່ງກົດລະບຽບ" }, "language_dropdown_label": "ເລື່ອນພາສາລົງ", - "lazy_loading": { - "disabled_action": "ລຶບ cache ແລະ resync", - "disabled_description1": "ກ່ອນໜ້ານີ້ທ່ານເຄີຍໃຊ້ %(brand)sກັບ %(host)s ດ້ວຍການເປີດໂຫຼດສະມາຊິກ. ໃນເວີຊັ້ນນີ້ ໄດ້ປິດການໃຊ້ງານ. ເນື່ອງຈາກ cache ໃນເຄື່ອງບໍ່ເຂົ້າກັນລະຫວ່າງສອງການຕັ້ງຄ່ານີ້, %(brand)s ຕ້ອງການ sync ບັນຊີຂອງທ່ານຄືນໃໝ່.", - "disabled_description2": "ຖ້າເວີຊັ້ນອື່ນຂອງ %(brand)s ເປີດຢູ່ໃນແຖບອື່ນ, ກະລຸນາປິດການໃຊ້ %(brand)s ຢູ່ໃນໂຮດດຽວກັນທັງການໂຫຼດແບບ lazy ເປີດໃຊ້ງານ ແລະປິດໃຊ້ງານພ້ອມກັນຈະເຮັດໃຫ້ເກີດບັນຫາ.", - "disabled_title": "ແຄດໃນເຄື່ອງບໍ່ເຂົ້າກັນໄດ້", - "resync_description": "ຕອນນີ້ %(brand)s ໃຊ້ຄວາມຈຳໜ້ອຍກວ່າ 3-5x, ໂດຍການໂຫຼດຂໍ້ມູນກ່ຽວກັບຜູ້ໃຊ້ອື່ນເມື່ອຕ້ອງການເທົ່ານັ້ນ. ກະລຸນາລໍຖ້າໃນຂະນະທີ່ພວກເຮົາ synchronise ກັບເຊີບເວີ!", - "resync_title": "ກຳລັງອັບເດດ %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "ເຈົ້າເປັນພຽງຄົນດຽວຢູ່ທີ່ນີ້. ຖ້າທ່ານອອກໄປ, ບໍ່ມີໃຜຈະສາມາດເຂົ້າຮ່ວມໃນອະນາຄົດໄດ້, ລວມທັງທ່ານ.", "leave_room_question": "ທ່ານແນ່ໃຈບໍ່ວ່າຕ້ອງການອອກຈາກຫ້ອງ '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/lt.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/lt.json index bae89365f6..66deb29fe1 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/lt.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/lt.json @@ -928,14 +928,6 @@ "title": "Ignoruojami vartotojai", "view_rules": "Peržiūrėti taisykles" }, - "lazy_loading": { - "disabled_action": "Išvalyti talpyklą ir sinchronizuoti iš naujo", - "disabled_description1": "Jūs anksčiau naudojote %(brand)s ant %(host)s įjungę tingų narių įkėlimą. Šioje versijoje tingus įkėlimas yra išjungtas. Kadangi vietinė talpykla nesuderinama tarp šių dviejų nustatymų, %(brand)s reikia iš naujo sinchronizuoti jūsų paskyrą.", - "disabled_description2": "Jei kita %(brand)s versija vis dar yra atidaryta kitame skirtuke, uždarykite jį, nes %(brand)s naudojimas tame pačiame serveryje, tuo pačiu metu įjungus ir išjungus tingų įkėlimą, sukelks problemų.", - "disabled_title": "Nesuderinamas vietinis podėlis", - "resync_description": "%(brand)s dabar naudoja 3-5 kartus mažiau atminties, įkeliant vartotojų informaciją tik prireikus. Palaukite, kol mes iš naujo sinchronizuosime su serveriu!", - "resync_title": "Atnaujinama %(brand)s" - }, "leave_room_dialog": { "leave_room_question": "Ar tikrai norite išeiti iš kambario %(roomName)s?", "room_rejoin_warning": "Šis kambarys nėra viešas. Jūs negalėsite prisijungti iš naujo be pakvietimo." diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/nl.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/nl.json index 943369d05a..9352a3cf2f 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/nl.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/nl.json @@ -221,7 +221,6 @@ "approve_access_warning": "Door de toegang voor dit apparaat goed te keuren, heeft het volledige toegang tot jouw account.", "completing_setup": "De configuratie van je nieuwe apparaat voltooien", "confirm_code_match": "Controleer of de onderstaande code overeenkomt met je andere apparaat:", - "devices_connected": "Verbonden apparaten", "error_device_already_signed_in": "Het andere apparaat is al aangemeld.", "error_device_not_signed_in": "Het andere apparaat is niet ingelogd.", "error_device_unsupported": "Koppelen met dit apparaat wordt niet ondersteund.", @@ -231,10 +230,8 @@ "error_request_cancelled": "Het verzoek is geannuleerd.", "error_request_declined": "Het verzoek is afgewezen op het andere apparaat.", "error_unexpected": "Er is een onverwachte fout opgetreden.", - "review_and_approve": "Controleer en keur de aanmelding goed", "scan_code_instruction": "Scan de onderstaande QR-code met je apparaat dat is uitgelogd.", "sign_in_new_device": "Aanmelden nieuw apparaat", - "start_at_sign_in_screen": "Begin bij het inlogscherm", "waiting_for_device": "Wachten op apparaat om in te loggen" }, "register_action": "Registreren", @@ -630,7 +627,6 @@ "methods": "Methoden", "no_verification_requests_found": "Geen verificatieverzoeken gevonden", "number_of_users": "Aantal personen", - "observe_only": "Alleen observeren", "original_event_source": "Originele gebeurtenisbron", "phase": "Fase", "phase_cancelled": "Geannuleerd", @@ -638,7 +634,6 @@ "phase_requested": "Aangevraagd", "phase_started": "Begonnen", "phase_transaction": "Transactie", - "requester": "Aanvrager", "room_id": "Kamer ID: %(roomId)s", "save_setting_values": "Instelling waardes opslaan", "send_custom_account_data_event": "Aangepaste accountgegevens gebeurtenis versturen", @@ -1257,14 +1252,6 @@ "view_rules": "Bekijk regels" }, "language_dropdown_label": "Taalselectie", - "lazy_loading": { - "disabled_action": "Cache wissen en hersynchroniseren", - "disabled_description1": "Je hebt voorheen %(brand)s op %(host)s gebruikt met lui laden van leden ingeschakeld. In deze versie is lui laden uitgeschakeld. De lokale cache is niet compatibel tussen deze twee instellingen, zodat %(brand)s je account moet hersynchroniseren.", - "disabled_description2": "Indien de andere versie van %(brand)s nog open staat in een ander tabblad kan je dat beter sluiten, want het geeft problemen als %(brand)s op dezelfde host gelijktijdig met lui laden ingeschakeld en uitgeschakeld draait.", - "disabled_title": "Incompatibele lokale cache", - "resync_description": "%(brand)s verbruikt nu 3-5x minder geheugen, door informatie over andere personen enkel te laden wanneer nodig. Even geduld, we synchroniseren met de server!", - "resync_title": "%(brand)s wordt bijgewerkt" - }, "leave_room_dialog": { "last_person_warning": "Je bent de enige persoon hier. Als je weggaat, zal niemand in de toekomst kunnen toetreden, jij ook niet.", "leave_room_question": "Weet je zeker dat je de kamer ‘%(roomName)s’ wil verlaten?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/pl.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/pl.json index a2ada20042..9b349bdd0e 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/pl.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/pl.json @@ -47,7 +47,7 @@ "delete": "Usuń", "deny": "Odmów", "disable": "Wyłącz", - "disconnect": "Odłącz", + "disconnect": "Rozłącz", "dismiss": "Pomiń", "done": "Gotowe", "download": "Pobierz", @@ -112,7 +112,7 @@ "share": "Udostępnij", "show": "Pokaż", "show_advanced": "Pokaż zaawansowane", - "show_all": "Zobacz wszystko", + "show_all": "Pokaż wszystko", "sign_in": "Zaloguj", "sign_out": "Wyloguj", "skip": "Pomiń", @@ -146,10 +146,10 @@ "accept_button": "To jest w porządku", "bullet_1": "Nie zapisujemy żadnych danych, ani nie profilujemy Twojego konta", "bullet_2": "Nie udostępniamy żadnych informacji stronom trzecim", - "consent_migration": "Wcześniej wyraziłeś zgodę na udostępnianie zanonimizowanych danych z nami. Teraz aktualizujemy jak to działa.", - "disable_prompt": "Możesz to wyłączyć kiedy zechcesz w ustawieniach", + "consent_migration": "Wyrażono zgodę na udostępnianie z nami anonimowych danych. Teraz aktualizujemy jak to działa.", + "disable_prompt": "Możesz to wyłączyć kiedykolwiek w ustawieniach", "enable_prompt": "Pomóż poprawić %(analyticsOwner)s", - "learn_more": "Udostępnij anonimowe dane, aby pomóc nam zidentyfikować problemy. Nic osobistego. Żadnych podmiotów zewnętrznych. Dowiedz się więcej", + "learn_more": "Udostępnij anonimowe dane, aby pomóc nam w identyfikacji problemów. Nic osobistego. Żadnych podmiotów zewnętrznych. Dowiedz się więcej", "privacy_policy": "Możesz przeczytać wszystkie nasze warunki tutaj", "pseudonymous_usage_data": "Pomóż nam zidentyfikować problemy i ulepszyć %(analyticsOwner)s, udostępniając anonimowe dane o użytkowaniu. Aby zrozumieć, w jaki sposób użytkownicy korzystają z wielu urządzeń, wygenerujemy losowy identyfikator dzielony pomiędzy Twoimi urządzeniami.", "shared_data_heading": "Wszystkie wymienione dane mogą być udostępnione:" @@ -157,7 +157,7 @@ "auth": { "3pid_in_use": "Ten adres e-mail lub numer telefonu jest już w użyciu.", "account_clash": "Twoje nowe konto (%(newAccountId)s) zostało zarejestrowane, lecz jesteś już zalogowany na innym koncie (%(loggedInUserId)s).", - "account_clash_previous_account": "Kontynuuj, używając poprzedniego konta", + "account_clash_previous_account": "Kontynuuj używając poprzedniego konta.", "account_deactivated": "To konto zostało zdezaktywowane.", "autodiscovery_generic_failure": "Nie udało się uzyskać konfiguracji autodiscovery z serwera", "autodiscovery_hs_incompatible": "Twój serwer domowy jest za stary i nie obsługuje wymaganej minimalnej wersji API. Skontaktuj się z właścicielem serwera lub zaktualizuj swój serwer.", @@ -249,7 +249,6 @@ "completing_setup": "Kończenie konfiguracji nowego urządzenia", "confirm_code_match": "Potwierdź, że kod poniżej pasuje z Twoim drugim urządzeniem:", "connecting": "Łączenie…", - "devices_connected": "Urządzenia połączone", "error_device_already_signed_in": "Drugie urządzenie jest już zalogowane.", "error_device_not_signed_in": "Drugie urządzenie nie jest zalogowane.", "error_device_unsupported": "Wiązanie z tym urządzeniem nie jest wspierane.", @@ -260,12 +259,13 @@ "error_request_cancelled": "Żądanie zostało anulowane.", "error_request_declined": "Żądanie zostało odrzucone przez drugie urządzenie.", "error_unexpected": "Wystąpił niespodziewany błąd.", - "review_and_approve": "Sprawdź i potwierdź logowanie", - "scan_code_instruction": "Zeskanuj kod QR poniżej za pomocą urządzenia, które jest wylogowane.", + "follow_remaining_instructions": "Podążaj zgodnie z pozostałymi instrukcjami, aby zweryfikować drugie urządzenie", + "open_element_other_device": "Otwórz %(brand)s na swoim drugim urządzeniu", + "point_the_camera": "Skieruj kamerę na widoczny kod QR", + "scan_code_instruction": "Skanuj kod QR za pomocą innego urządzenia", "scan_qr_code": "Skanuj kod QR", - "select_qr_code": "Wybierz '%(scanQRCode)s'", + "select_qr_code": "Wybierz \"%(scanQRCode)s\"", "sign_in_new_device": "Zaloguj nowe urządzenie", - "start_at_sign_in_screen": "Rozpocznij na ekranie logowania", "waiting_for_device": "Oczekiwanie na logowanie urządzenia" }, "register_action": "Utwórz konto", @@ -743,15 +743,14 @@ "notification_state": "Status powiadomień %(notificationState)s", "notifications_debug": "Debug powiadomień", "number_of_users": "Liczba użytkowników", - "observe_only": "Tylko obserwuj", "original_event_source": "Oryginalne źródło wydarzenia", + "other_user": "Inny użytkownik", "phase": "Etap", "phase_cancelled": "Anulowano", "phase_ready": "Gotowe", "phase_requested": "Żądane", "phase_started": "Rozpoczęto", "phase_transaction": "Transakcja", - "requester": "Żądający", "room_encrypted": "Pokój jest szyfrowany ✅", "room_id": "ID pokoju: %(roomId)s", "room_not_encrypted": "Pokój nie jest szyfrowany 🚨", @@ -791,6 +790,7 @@ "thread_root_id": "ID Root Wątku:%(threadRootId)s", "threads_timeline": "Oś czasu wątków", "timeout": "Czas oczekiwania", + "timeout_none": "Brak", "title": "Ustawienia deweloperskie", "toggle_event": "przełącz wydarzenie", "toolbox": "Przybornik", @@ -1188,7 +1188,7 @@ "peek_note": "Należy dołączyć do pokoju by zobaczyć jego pliki" }, "forward": { - "filter_placeholder": "Szukaj pokojów i ludzi", + "filter_placeholder": "Szukaj pokoi lub osób", "message_preview_heading": "Podgląd wiadomości", "no_perms_title": "Nie masz uprawnień aby to zrobić", "open_room": "Otwórz pokój", @@ -1264,8 +1264,8 @@ "error_find_user_description": "Ci użytkownicy mogą nie istnieć lub są nieprawidłowi, i nie mogą zostać zaproszeni: %(csvNames)s", "error_find_user_title": "Nie udało się znaleźć tych użytkowników", "error_invite": "Nie udało się zaprosić tych użytkowników. Proszę sprawdzić zaproszonych użytkowników i spróbować ponownie.", - "error_permissions_room": "Nie masz uprawnień do zapraszania ludzi do tego pokoju.", - "error_permissions_space": "Nie masz uprawnień, by zapraszać ludzi do tej przestrzeni.", + "error_permissions_room": "Nie masz uprawnień do zapraszania osób do tego pokoju.", + "error_permissions_space": "Nie masz uprawnień do zapraszania osób do tej przestrzeni.", "error_profile_undisclosed": "Użytkownik może istnieć lub nie", "error_transfer_multiple_target": "Połączenie może zostać przekazane tylko do pojedynczego użytkownika.", "error_unfederated_room": "Ten pokój jest niezrzeszony. Nie możesz zapraszać osób z serwerów zewnętrznych.", @@ -1463,7 +1463,7 @@ "sliding_sync_server_specify_proxy": "Twój serwer nie posiada wsparcia natywnego, musisz podać serwer proxy", "sliding_sync_server_support": "Twój serwer posiada wsparcie natywne", "threads_activity_centre": "Centrum aktywności wątków (w trakcie rozwoju)", - "threads_activity_centre_description": "Ostrzeżenie: W trakcie aktywnego rozwoju; przeładowuje Element.", + "threads_activity_centre_description": "Ostrzeżenie: W trakcie aktywnego rozwoju; przeładowuje %(brand)s.", "under_active_development": "W trakcie aktywnego rozwoju.", "unrealiable_e2e": "Problematyczny w pokojach szyfrowanych", "video_rooms": "Pokoje wideo", @@ -1513,18 +1513,12 @@ "view_rules": "Zobacz zasady" }, "language_dropdown_label": "Rozwiń języki", - "lazy_loading": { - "disabled_action": "Wyczyść pamięć podręczną i zsynchronizuj ponownie", - "disabled_description1": "Ostatnia sesja %(brand)s na %(host)s miała włączone leniwe ładowanie członków. W tej wersji leniwe ładowanie jest wyłączone. Ponieważ lokalna pamięć podręczna nie jest kompatybilna pomiędzy tymi wersjami, %(brand)s musi zsynchronizować ponownie Twoje konto.", - "disabled_description2": "Jeśli inna wersja %(brand)s jest nadal otwarta w innej zakładce, proszę zamknij ją, ponieważ używanie %(brand)s na tym samym komputerze z włączonym i wyłączonym jednocześnie leniwym ładowaniem będzie powodować problemy.", - "disabled_title": "Niekompatybilna lokalna pamięć podręczna", - "resync_description": "%(brand)s używa teraz 3-5x mniej pamięci, ładując informacje o innych użytkownikach tylko wtedy, gdy jest to konieczne. Poczekaj, aż ponownie zsynchronizujemy się z serwerem!", - "resync_title": "Aktualizowanie %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Jesteś jedyną osoba tutaj. Jeśli wyjdziesz, nikt nie będzie w stanie dołączyć w przyszłości, włączając Ciebie.", "leave_room_question": "Czy na pewno chcesz opuścić pokój '%(roomName)s'?", "leave_space_question": "Czy na pewno chcesz opuścić przestrzeń '%(spaceName)s'?", + "room_leave_admin_warning": "Jesteś jedynym administratorem w tym pokoju. Jeśli odejdziesz, nikt nie będzie mógł zmienić ustawień pokoju, ani podjąć innych ważnych działań.", + "room_leave_mod_warning": "Jesteś jedynym moderatorem w tym pokoju. Jeśli odejdziesz, nikt nie będzie mógł zmienić ustawień pokoju, ani podjąć innych ważnych działań.", "room_rejoin_warning": "Ten pokój nie jest publiczny. Nie będziesz w stanie do niego dołączyć bez zaproszenia.", "space_rejoin_warning": "Ta przestrzeń nie jest publiczna. Nie będziesz w stanie dołączyć bez zaproszenia." }, @@ -1592,7 +1586,7 @@ }, "member_list_back_action_label": "Członkowie pokoju", "message_edit_dialog_title": "Edycje wiadomości", - "migrating_crypto": "Trzymaj się mocno. Aktualizujemy Element, aby szyfrowanie było szybsze i bardziej niezawodne.", + "migrating_crypto": "Trzymaj się mocno. Aktualizujemy %(brand)s, aby szyfrowanie było szybsze i bardziej niezawodne.", "mobile_guide": { "toast_accept": "Użyj aplikacji", "toast_description": "%(brand)s jest eksperymentalne na przeglądarce mobilnej. Dla lepszego doświadczenia i najnowszych funkcji użyj naszej darmowej natywnej aplikacji.", @@ -1658,7 +1652,7 @@ "find_friends": "Znajdź i zaproś swoich znajomych", "find_friends_action": "Znajdź znajomych", "find_friends_description": "Po to tu jesteś, więc bierzmy się do roboty", - "find_people": "Znajdź ludzi", + "find_people": "Znajdź osoby", "free_e2ee_messaging_unlimited_voip": "Za pomocą darmowych wiadomości szyfrowanych end-to-end i nielimitowanymi rozmowami głosowymi i wideo, %(brand)s jest świetnym sposobem, aby pozostać w kontakcie.", "get_stuff_done": "Załatwiaj sprawy znajdując swoich znajomych", "google_trademarks": "Google Play i logo Google Play są znakami towarowymi Google LLC.", @@ -1894,6 +1888,7 @@ "forget": "Zapomnij pokój", "low_priority": "Niski priorytet", "mark_read": "Oznacz jako przeczytane", + "mark_unread": "Oznacz jako nieprzeczytane", "mentions_only": "Tylko wzmianki", "notifications_default": "Dopasuj z ustawieniami domyślnymi", "notifications_mute": "Wycisz pokój", @@ -2425,6 +2420,7 @@ "custom_theme_success": "Dodano motyw!", "custom_theme_url": "Niestandardowy adres URL motywu", "font_size": "Rozmiar czcionki", + "font_size_default": "%(fontSize)s (domyślny)", "heading": "Dostosuj wygląd", "image_size_default": "Zwykły", "image_size_large": "Duży", @@ -2809,9 +2805,9 @@ "security_recommendations_description": "Zwiększ bezpieczeństwo swojego konta kierując się tymi rekomendacjami.", "session_id": "Identyfikator sesji", "show_details": "Pokaż szczegóły", - "sign_in_with_qr": "Zaloguj się za pomocą kodu QR", + "sign_in_with_qr": "Połącz nowe urządzenie", "sign_in_with_qr_button": "Pokaż kod QR", - "sign_in_with_qr_description": "Możesz użyć tego urządzenia, aby zalogować nowe za pomocą kodu QR. Zeskanuj kod QR wyświetlany na tym urządzeniu za pomocą drugiego wylogowanego.", + "sign_in_with_qr_description": "Użyj kodu QR, aby zalogować się na innym urządzeniu i skonfigurować bezpieczne przesyłanie wiadomości.", "sign_out": "Wyloguj się z tej sesji", "sign_out_all_other_sessions": "Wyloguj się z wszystkich pozostałych sesji (%(otherSessionsCount)s)", "sign_out_confirm_description": { @@ -2860,6 +2856,9 @@ "metaspaces_orphans_description": "Pogrupuj wszystkie pokoje, które nie są częścią przestrzeni, w jednym miejscu.", "metaspaces_people_description": "Pogrupuj wszystkie osoby w jednym miejscu.", "metaspaces_subsection": "Wyświetlanie przestrzeni", + "metaspaces_video_rooms": "Pokoje wideo i konferencje", + "metaspaces_video_rooms_description": "Grupuj wszystkie prywatne pokoje wideo i konferencje.", + "metaspaces_video_rooms_description_invite_extension": "Na konferencjach możesz zaprosić osoby spoza matrix.", "spaces_explainer": "Przestrzenie to sposób grupowania pokoi i osób. Oprócz przestrzeni, w których się znajdujesz, możesz również korzystać z już wstępnie zbudowanych.", "title": "Pasek boczny" }, @@ -2898,6 +2897,9 @@ "link_title": "Link do pokoju", "permalink_message": "Link do zaznaczonej wiadomości", "permalink_most_recent": "Link do najnowszej wiadomości", + "share_call": "Link zaproszenia do konferencji", + "share_call_subtitle": "Link dla użytkowników zewnętrznych, aby dołączyć do połączenia bez konta matrix:", + "title_link": "Udostępnij link", "title_message": "Udostępnij wiadomość w pokoju", "title_room": "Udostępnij pokój", "title_user": "Udostępnij użytkownika" @@ -3025,7 +3027,7 @@ "failed_load_rooms": "Nie udało się wczytać listy pokoi.", "failed_remove_rooms": "Nie udało się usunąć niektórych pokojów. Spróbuj ponownie później", "incompatible_server_hierarchy": "Twój serwer nie obsługuje wyświetlania hierarchii przestrzeni.", - "invite": "Zaproś ludzi", + "invite": "Zaproś osoby", "invite_description": "Zaproś przy użyciu adresu email lub nazwy użytkownika", "invite_link": "Udostępnij link zaproszenia", "invite_this_space": "Zaproś do tej przestrzeni", @@ -3152,6 +3154,7 @@ "empty_heading": "Organizuj dyskusje za pomocą wątków", "empty_tip": "Tip: Użyj “%(replyInThread)s” najeżdżając na wiadomość.", "error_start_thread_existing_relation": "Nie można utworzyć wątku z wydarzenia z istniejącą relacją", + "mark_all_read": "Oznacz wszystkie jako przeczytane", "my_threads": "Moje wątki", "my_threads_description": "Pokazuje wszystkie wątki, w których brałeś udział", "open_thread": "Otwórz wątek", @@ -3828,6 +3831,7 @@ "expand": "Wróć do połączenia", "failed_call_live_broadcast_description": "Nie możesz rozpocząć połączenia, ponieważ już nagrywasz transmisję na żywo. Zakończ transmisję na żywo, aby rozpocząć połączenie.", "failed_call_live_broadcast_title": "Nie można rozpocząć połączenia", + "get_call_link": "Udostępnij link do połączenia", "hangup": "Rozłącz", "hide_sidebar_button": "Ukryj pasek boczny", "input_devices": "Urządzenia wejściowe", @@ -3837,6 +3841,9 @@ "legacy_call": "Połączenie Legacy", "maximise": "Wypełnij ekran", "maximise_call": "Maksymalizuj połączenie", + "metaspace_video_rooms": { + "conference_room_section": "Konferencje" + }, "minimise_call": "Minimalizuj połączenie", "misconfigured_server": "Połączenie nie udało się przez błędną konfigurację serwera", "misconfigured_server_description": "Poproś administratora swojego serwera głównego (%(homeserverDomain)s) by skonfigurował serwer TURN aby rozmowy działały bardziej niezawodnie.", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/pt_BR.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/pt_BR.json index 3e1fbc8b50..6d322e1f66 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/pt_BR.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/pt_BR.json @@ -1036,14 +1036,6 @@ "view_rules": "Ver regras" }, "language_dropdown_label": "Menu suspenso de idiomas", - "lazy_loading": { - "disabled_action": "Limpar cache e ressincronizar", - "disabled_description1": "Você já usou o %(brand)s em %(host)s com o carregamento Lazy de participantes ativado. Nesta versão, o carregamento Lazy está desativado. Como o cache local não é compatível entre essas duas configurações, o %(brand)s precisa ressincronizar sua conta.", - "disabled_description2": "Se a outra versão do %(brand)s ainda estiver aberta em outra aba, por favor, feche-a pois usar o %(brand)s no mesmo host com o carregamento Lazy ativado e desativado simultaneamente causará problemas.", - "disabled_title": "Cache local incompatível", - "resync_description": "%(brand)s agora usa de 3 a 5 vezes menos memória, pois carrega as informações dos outros usuários apenas quando for necessário. Por favor, aguarde enquanto ressincronizamos com o servidor!", - "resync_title": "Atualizando o %(brand)s" - }, "leave_room_dialog": { "leave_room_question": "Tem certeza de que deseja sair da sala '%(roomName)s'?", "leave_space_question": "Tem certeza de que deseja sair desse espaço '%(spaceName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/ru.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/ru.json index 7433ca2eb0..f9a84fd00d 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/ru.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/ru.json @@ -244,7 +244,6 @@ "completing_setup": "Завершение настройки нового устройства", "confirm_code_match": "Проверьте, чтобы код ниже совпадал с тем, что показан на другом устройстве:", "connecting": "Подключение…", - "devices_connected": "Подключенные устройства", "error_device_already_signed_in": "Уже выполнен вход на другом устройстве.", "error_device_not_signed_in": "На другом устройстве вход не выполнен.", "error_device_unsupported": "Соединение с этим устройством не поддерживается.", @@ -254,12 +253,10 @@ "error_request_cancelled": "Запрос был отменён.", "error_request_declined": "Запрос был отклонен на другом устройстве.", "error_unexpected": "Произошла неожиданная ошибка.", - "review_and_approve": "Проверьте и подтвердите вход", "scan_code_instruction": "Отсканируйте приведенный ниже QR-код на устройстве, которое вышло из системы.", "scan_qr_code": "Сканировать QR-код", "select_qr_code": "Выберите '%(scanQRCode)s'", "sign_in_new_device": "Войдите в систему c нового устройства", - "start_at_sign_in_screen": "Начните с экрана входа в систему", "waiting_for_device": "Ожидание входа устройства в систему" }, "register_action": "Создать учётную запись", @@ -735,7 +732,6 @@ "notification_state": "Состояние уведомления %(notificationState)s", "notifications_debug": "Отладка уведомлений", "number_of_users": "Количество пользователей", - "observe_only": "Только наблюдать", "original_event_source": "Оригинальный исходный код", "phase": "Фаза", "phase_cancelled": "Отменено", @@ -743,7 +739,6 @@ "phase_requested": "Запрошено", "phase_started": "Начато", "phase_transaction": "Транзакция", - "requester": "Адресат", "room_encrypted": "Комната зашифрована ✅", "room_id": "ID комнаты: %(roomId)s", "room_not_encrypted": "Комната не имеет шифрования 🚨", @@ -1494,14 +1489,6 @@ "view_rules": "Посмотреть правила" }, "language_dropdown_label": "Список языков", - "lazy_loading": { - "disabled_action": "Очистить кэш и выполнить повторную синхронизацию", - "disabled_description1": "Ранее вы использовали %(brand)s на %(host)s с отложенной загрузкой участников. В этой версии отложенная загрузка отключена. Поскольку локальный кеш не совместим между этими двумя настройками, %(brand)s необходимо повторно синхронизировать вашу учётную запись.", - "disabled_description2": "Если другая версия %(brand)s все еще открыта на другой вкладке, закройте ее, так как использование %(brand)s на том же хосте с включенной и отключенной ленивой загрузкой одновременно вызовет проблемы.", - "disabled_title": "Несовместимый локальный кэш", - "resync_description": "%(brand)s теперь использует в 3-5 раз меньше памяти, загружая информацию о других пользователях только когда это необходимо. Пожалуйста, подождите, пока мы ресинхронизируемся с сервером!", - "resync_title": "Обновление %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Вы здесь единственный человек. Если вы уйдете, никто не сможет присоединиться в будущем, включая вас.", "leave_room_question": "Уверены, что хотите покинуть '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/sk.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/sk.json index 1170467eb0..ca7b24e476 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/sk.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/sk.json @@ -244,7 +244,6 @@ "completing_setup": "Dokončenie nastavenia nového zariadenia", "confirm_code_match": "Skontrolujte, či sa nižšie uvedený kód zhoduje s vaším druhým zariadením:", "connecting": "Pripájanie…", - "devices_connected": "Zariadenia pripojené", "error_device_already_signed_in": "Druhé zariadenie je už prihlásené.", "error_device_not_signed_in": "Druhé zariadenie nie je prihlásené.", "error_device_unsupported": "Prepojenie s týmto zariadením nie je podporované.", @@ -254,12 +253,10 @@ "error_request_cancelled": "Žiadosť bola zrušená.", "error_request_declined": "Žiadosť bola na druhom zariadení zamietnutá.", "error_unexpected": "Vyskytla sa neočakávaná chyba.", - "review_and_approve": "Skontrolujte a schváľte prihlásenie", "scan_code_instruction": "Naskenujte nižšie uvedený QR kód pomocou zariadenia, ktoré je odhlásené.", "scan_qr_code": "Skenovať QR kód", "select_qr_code": "Vyberte '%(scanQRCode)s'", "sign_in_new_device": "Prihlásiť nové zariadenie", - "start_at_sign_in_screen": "Začnite na prihlasovacej obrazovke", "waiting_for_device": "Čaká sa na prihlásenie zariadenia" }, "register_action": "Vytvoriť účet", @@ -735,7 +732,6 @@ "notification_state": "Stav oznámenia je %(notificationState)s", "notifications_debug": "Ladenie oznámení", "number_of_users": "Počet používateľov", - "observe_only": "Iba pozorovať", "original_event_source": "Pôvodný zdroj udalosti", "phase": "Fáza", "phase_cancelled": "Zrušené", @@ -743,7 +739,6 @@ "phase_requested": "Vyžiadané", "phase_started": "Spustené", "phase_transaction": "Transakcia", - "requester": "Žiadateľ", "room_encrypted": "Miestnosť je šifrovaná ✅", "room_id": "ID miestnosti: %(roomId)s", "room_not_encrypted": "Miestnosť nie je šifrovaná 🚨", @@ -1499,14 +1494,6 @@ "view_rules": "Zobraziť pravidlá" }, "language_dropdown_label": "Rozbaľovací zoznam jazykov", - "lazy_loading": { - "disabled_action": "Vymazať vyrovnávaciu pamäť a synchronizovať znovu", - "disabled_description1": "Použili ste aj %(brand)s na adrese %(host)s so zapnutou voľbou Načítanie zoznamu členov pri prvom zobrazení. V tejto verzii je Načítanie zoznamu členov pri prvom zobrazení vypnuté. Keď že lokálna vyrovnávacia pamäť nie je vzájomne kompatibilná s takýmito nastaveniami, %(brand)s potrebuje znovu synchronizovať údaje z vašeho účtu.", - "disabled_description2": "Ak máte %(brand)s s iným nastavením otvorený na ďalšej karte, prosím zatvorte ju, pretože použitie %(brand)s s rôznym nastavením na jednom zariadení vám spôsobí len problémy.", - "disabled_title": "Nekompatibilná lokálna vyrovnávacia pamäť", - "resync_description": "%(brand)s teraz vyžaduje 3-5× menej pamäte, pretože informácie o ostatných používateľoch načítava len podľa potreby. Prosím počkajte na dokončenie synchronizácie so serverom!", - "resync_title": "Prebieha aktualizácia %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Ste tu jediný človek. Ak odídete, nikto sa už v budúcnosti nebude môcť pripojiť do tejto miestnosti, vrátane vás.", "leave_room_question": "Ste si istí, že chcete opustiť miestnosť '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/sq.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/sq.json index 27c8311553..c75782696c 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/sq.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/sq.json @@ -235,7 +235,6 @@ "completing_setup": "Po plotësohet ujdisja e pajisjes tuaj të re", "confirm_code_match": "Kontrolloni se kodi më poshtë përkon me atë në pajisjen tuaj tjetër:", "connecting": "Po lidhet…", - "devices_connected": "Pajisje të lidhura", "error_device_already_signed_in": "Nga pajisja tjetër është bërë tashmë hyrja.", "error_device_not_signed_in": "Te pajisja tjetër s’është bërë hyrja.", "error_device_unsupported": "Lidhja me këtë pajisje nuk mbulohet.", @@ -246,12 +245,10 @@ "error_request_cancelled": "Kërkesa u anulua.", "error_request_declined": "Kërkesa u hodh poshtë në pajisjen tjetër.", "error_unexpected": "Ndodhi një gabim të papritur.", - "review_and_approve": "Shqyrtoni dhe miratojeni hyrjen", "scan_code_instruction": "Skanoni kodin QR më poshtë me pajisjen ku është bërë dalja.", "scan_qr_code": "Skanoni kodin QR", "select_qr_code": "Përzgjidhni “%(scanQRCode)s”", "sign_in_new_device": "Hyni në pajisje të re", - "start_at_sign_in_screen": "Filloja në skenën e hyrjes", "waiting_for_device": "Po pritet që të bëhet hyrja te pajisja" }, "register_action": "Krijoni Llogari", @@ -706,7 +703,6 @@ "notification_state": "Gjendje njoftimi është %(notificationState)s", "notifications_debug": "Diagnostikim njoftimesh", "number_of_users": "Numër përdoruesish", - "observe_only": "Vetëm vëzhgo", "original_event_source": "Burim i veprimtarisë origjinale", "phase": "Fazë", "phase_cancelled": "Anuluar", @@ -714,7 +710,6 @@ "phase_requested": "E kërkuar", "phase_started": "Nisur më", "phase_transaction": "Transaksion", - "requester": "Kërkues", "room_encrypted": "Dhoma është e fshehtëzuar ✅", "room_id": "ID Dhome: %(roomId)s", "room_not_encrypted": "Dhoma është e pafshehtëzuar 🚨", @@ -1410,14 +1405,6 @@ "view_rules": "Shihni rregulla" }, "language_dropdown_label": "Menu Hapmbyll Gjuhësh", - "lazy_loading": { - "disabled_action": "Spastro fshehtinën dhe rinjëkohëso", - "disabled_description1": "Më parë përdornit %(brand)s në %(host)s me lazy loading anëtarësh të aktivizuar. Në këtë version lazy loading është çaktivizuar. Ngaqë fshehtina vendore s’është e përputhshme mes këtyre dy rregullimeve, %(brand)s-i lyp të rinjëkohësohet llogaria juaj.", - "disabled_description2": "Nëse versioni tjetër i %(brand)s-it është ende i hapur në një skedë tjetër, ju lutemi, mbylleni, ngaqë përdorimi njëkohësisht i %(brand)s-it në të njëjtën strehë, në njërën anë me lazy loading të aktivizuar dhe në anën tjetër të çaktivizuar do të shkaktojë probleme.", - "disabled_title": "Fshehtinë vendore e papërputhshme", - "resync_description": "%(brand)s-i tani përdor 3 deri 5 herë më pak kujtesë, duke ngarkuar të dhëna mbi përdorues të tjerë vetëm kur duhen. Ju lutemi, prisni, teksa njëkohësojmë të dhënat me shërbyesin!", - "resync_title": "%(brand)s-i po përditësohet" - }, "leave_room_dialog": { "last_person_warning": "Jeni i vetmi person këtu. Nëse e braktisni, askush s’do të jetë në gjendje të hyjë në të ardhmen, përfshi ju.", "leave_room_question": "Jeni i sigurt se doni të dilni nga dhoma '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/sv.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/sv.json index b41d66a1c4..722ef247af 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/sv.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/sv.json @@ -249,7 +249,6 @@ "completing_setup": "Slutför inställning av din nya enhet", "confirm_code_match": "Kolla att koden nedan matchar din andra enhet:", "connecting": "Kopplar upp …", - "devices_connected": "Enheter anslutna", "error_device_already_signed_in": "Den andra enheten är redan inloggad.", "error_device_not_signed_in": "Den andra enheten är inte inloggad.", "error_device_unsupported": "Länkning med den här enheten stöds inte.", @@ -260,12 +259,10 @@ "error_request_cancelled": "Förfrågan avbröts.", "error_request_declined": "Förfrågan nekades på den andra enheten.", "error_unexpected": "Ett oväntade fel inträffade.", - "review_and_approve": "Granska och godkänn inloggningen", "scan_code_instruction": "Skanna QR-koden nedan med din andra enhet som är utloggad.", "scan_qr_code": "Skanna QR-kod", "select_qr_code": "Välj '%(scanQRCode)s'", "sign_in_new_device": "Logga in ny enhet", - "start_at_sign_in_screen": "Börja på inloggningsskärmen", "waiting_for_device": "Väntar på att enheter loggar in" }, "register_action": "Skapa konto", @@ -742,7 +739,6 @@ "notification_state": "Aviseringsstatus är %(notificationState)s", "notifications_debug": "Aviseringsfelsökning", "number_of_users": "Antal användare", - "observe_only": "Bara kolla", "original_event_source": "Ursprunglig händelsekällkod", "phase": "Fas", "phase_cancelled": "Avbruten", @@ -750,7 +746,6 @@ "phase_requested": "Efterfrågad", "phase_started": "Påbörjad", "phase_transaction": "Transaktion", - "requester": "Den som skickat förfrågan", "room_encrypted": "Rummet är krypterat ✅", "room_id": "Rums-ID: %(roomId)s", "room_not_encrypted": "Rummet är inte krypterat 🚨", @@ -1511,14 +1506,6 @@ "view_rules": "Visa regler" }, "language_dropdown_label": "Språkmeny", - "lazy_loading": { - "disabled_action": "Töm cache och synkronisera om", - "disabled_description1": "Du har tidigare använt %(brand)s på %(host)s med fördröjd inladdning av medlemmar aktiverat. I den här versionen är fördröjd inladdning inaktiverat. Eftersom den lokala cachen inte är kompatibel mellan dessa två inställningar behöver %(brand)s synkronisera om ditt konto.", - "disabled_description2": "Om den andra versionen av %(brand)s fortfarande är öppen i en annan flik, stäng den eftersom användning av %(brand)s på samma värd med fördröjd inladdning både aktiverad och inaktiverad samtidigt kommer att orsaka problem.", - "disabled_title": "Inkompatibel lokal cache", - "resync_description": "%(brand)s använder nu 3-5 gånger mindre minne, genom att bara ladda information om andra användare när det behövs. Vänta medan vi återsynkroniserar med servern!", - "resync_title": "Uppdaterar %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Du är den enda personen här. Om du lämnar så kommer ingen kunna gå med igen, inklusive du.", "leave_room_question": "Vill du lämna rummet '%(roomName)s'?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/uk.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/uk.json index 84c639c8f1..b9b307889e 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/uk.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/uk.json @@ -241,7 +241,6 @@ "completing_setup": "Завершення налаштування нового пристрою", "confirm_code_match": "Перевірте, чи збігається наведений внизу код з кодом на вашому іншому пристрої:", "connecting": "З'єднання…", - "devices_connected": "Пристрої під'єднано", "error_device_already_signed_in": "На іншому пристрої вхід було виконано.", "error_device_not_signed_in": "На іншому пристрої вхід не виконано.", "error_device_unsupported": "Зв'язок з цим пристроєм не підтримується.", @@ -252,12 +251,10 @@ "error_request_cancelled": "Запит було скасовано.", "error_request_declined": "На іншому пристрої запит відхилено.", "error_unexpected": "Виникла непередбачувана помилка.", - "review_and_approve": "Розглянути та схвалити вхід", "scan_code_instruction": "Скануйте QR-код знизу своїм пристроєм, на якому ви вийшли.", "scan_qr_code": "Скануйте QR-код", "select_qr_code": "Виберіть «%(scanQRCode)s»", "sign_in_new_device": "Увійти на новому пристрої", - "start_at_sign_in_screen": "Почніть з екрана входу", "waiting_for_device": "Очікування входу з пристрою" }, "register_action": "Створити обліковий запис", @@ -728,7 +725,6 @@ "notification_state": "Стан сповіщень %(notificationState)s", "notifications_debug": "Сповіщення зневадження", "number_of_users": "Кількість користувачів", - "observe_only": "Лише спостерігати", "original_event_source": "Оригінальний початковий код", "phase": "Фаза", "phase_cancelled": "Скасовано", @@ -736,7 +732,6 @@ "phase_requested": "Подано запит", "phase_started": "Почато", "phase_transaction": "Транзакція", - "requester": "Адресант", "room_encrypted": "Кімната зашифрована ✅", "room_id": "ID кімнати: %(roomId)s", "room_not_encrypted": "Кімната не зашифрована 🚨", @@ -1458,14 +1453,6 @@ "view_rules": "Переглянути правила" }, "language_dropdown_label": "Спадне меню мов", - "lazy_loading": { - "disabled_action": "Очистити кеш і повторно синхронізувати", - "disabled_description1": "Ви використовували %(brand)s на %(host)s, ввімкнувши відкладене звантаження учасників. У цій версії відкладене звантаження вимкнене. Оскільки локальне кешування не підтримує переходу між цими опціями, %(brand)s мусить заново синхронізувати ваш обліковий запис.", - "disabled_description2": "Якщо інший примірник %(brand)s досі відкритий в іншій вкладці, просимо закрити її, бо використання %(brand)s із водночас увімкненим і вимкненим відкладеним звантаженням створюватиме проблеми.", - "disabled_title": "Несумісний локальний кеш", - "resync_description": "%(brand)s тепер використовує в 3-5 разів менше пам'яті, звантажуючи дані про інших користувачів лише за потреби. Зачекайте, поки ми синхронізуємося з сервером!", - "resync_title": "Оновлення %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Тут лише ви. Якщо ви вийдете, ніхто більше не зможе приєднатися, навіть ви самі.", "leave_room_question": "Ви впевнені, що хочете вийти з «%(roomName)s»?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/vi.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/vi.json index cb3441462c..7fc2c66760 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/vi.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/vi.json @@ -1341,14 +1341,6 @@ "view_rules": "Xem các quy tắc" }, "language_dropdown_label": "Danh sách ngôn ngữ", - "lazy_loading": { - "disabled_action": "Xóa bộ nhớ cache và đồng bộ hóa lại", - "disabled_description1": "Trước đây, bạn đã sử dụng %(brand)s trên %(host)s khi đã bật tính năng tải chậm các thành viên. Trong phiên bản này, tính năng tải lười biếng bị vô hiệu hóa. Vì bộ nhớ cache cục bộ không tương thích giữa hai cài đặt này, %(brand)s cần phải đồng bộ hóa lại tài khoản của bạn.", - "disabled_description2": "Nếu phiên bản khác của %(brand)s vẫn đang mở trong một tab khác, vui lòng đóng nó lại vì việc sử dụng %(brand)s trên cùng một máy chủ với cả hai chế độ tải chậm được bật và tắt đồng thời sẽ gây ra sự cố.", - "disabled_title": "Bộ nhớ cache cục bộ không tương thích", - "resync_description": "%(brand)s hiện sử dụng bộ nhớ ít hơn 3-5 lần, bằng cách chỉ tải thông tin về những người dùng khác khi cần thiết. Vui lòng đợi trong khi chúng tôi đồng bộ hóa lại với máy chủ!", - "resync_title": "Đang cập nhật %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "Bạn là người duy nhất ở đây. Nếu bạn rời, không ai có thể tham gia trong tương lai, kể cả bạn.", "leave_room_question": "Bạn có chắc chắn muốn rời khỏi phòng '%(roomName)s' không?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hans.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hans.json index 9d159b6c2d..e03a592144 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hans.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hans.json @@ -206,7 +206,7 @@ "forgot_password_email_required": "必须输入和你账户关联的邮箱地址。", "forgot_password_prompt": "忘记你的密码了吗?", "forgot_password_send_email": "发送重置连接", - "identifier_label": "第三方登录", + "identifier_label": "登录方式", "incorrect_credentials": "用户名或密码错误。", "incorrect_credentials_detail": "请注意,你正在登录 %(hs)s,而非 matrix.org。", "incorrect_password": "密码错误", @@ -244,7 +244,6 @@ "completing_setup": "完成新设备的设置", "confirm_code_match": "检查以下代码是否与你的其他设备匹配:", "connecting": "正在连接……", - "devices_connected": "已连接的设备", "error_homeserver_lacks_support": "此服务器不支持多设备登录" }, "register_action": "创建账户", @@ -277,7 +276,7 @@ "server_picker_description": "你可以使用自定义服务器选项来指定不同的家服务器URL以登录其他Matrix服务器。这让你能把%(brand)s和不同家服务器上的已有Matrix账户搭配使用。", "server_picker_description_matrix.org": "免费加入最大的公共服务器,成为数百万用户中的一员", "server_picker_dialog_title": "决定账户托管位置", - "server_picker_explainer": "使用你偏好的Matrix家服务器,如果你有的话,或自己架设一个。", + "server_picker_explainer": "使用你的Matrix服务器,或自己架设一个。", "server_picker_failed_validate_homeserver": "无法验证家服务器", "server_picker_intro": "我们将您可以托管账户的地方称为“服务器组”。", "server_picker_invalid_url": "URL 无效", @@ -686,14 +685,12 @@ "methods": "方法", "no_verification_requests_found": "未找到验证请求", "number_of_users": "用户数", - "observe_only": "仅观察", "original_event_source": "原始事件源码", "phase": "阶段", "phase_cancelled": "已取消", "phase_requested": "已请求", "phase_started": "已开始", "phase_transaction": "交易", - "requester": "请求者", "room_id": "房间ID: %(roomId)s", "save_setting_values": "保存设置值", "send_custom_account_data_event": "发送自定义账户数据事件", @@ -1363,14 +1360,6 @@ "view_rules": "查看规则" }, "language_dropdown_label": "语言下拉菜单", - "lazy_loading": { - "disabled_action": "清除缓存并重新同步", - "disabled_description1": "你之前在 %(host)s 上开启了 %(brand)s 的成员列表延迟加载设置。目前版本中延迟加载功能已被停用。因为本地缓存在这两个设置项上不相容,%(brand)s 需要重新同步你的账户。", - "disabled_description2": "如果别的 %(brand)s 版本在别的标签页中仍然开启,请关闭它,因为在同一宿主上同时使用开启了延迟加载和关闭了延迟加载的 %(brand)s 会导致问题。", - "disabled_title": "本地缓存不兼容", - "resync_description": "通过仅在需要时加载其他用户的信息,%(brand)s 现在使用的内存减少到了原来的三分之一至五分之一。 请等待与服务器重新同步!", - "resync_title": "正在更新 %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "你是这里唯一的人。如果你离开了,以后包括你在内任何人都将无法加入。", "leave_room_question": "你确定要离开房间 “%(roomName)s” 吗?", diff --git a/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hant.json b/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hant.json index b9cda836ee..0f02cb8ed0 100644 --- a/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hant.json +++ b/linked-dependencies/matrix-react-sdk/src/i18n/strings/zh_Hant.json @@ -241,7 +241,6 @@ "completing_setup": "完成您新裝置的設定", "confirm_code_match": "請確認下列代碼與您另一台裝置上的代碼相符:", "connecting": "連線中…", - "devices_connected": "裝置已連線", "error_device_already_signed_in": "其他裝置已登入。", "error_device_not_signed_in": "其他裝置未登入。", "error_device_unsupported": "不支援與此裝置連結。", @@ -252,12 +251,10 @@ "error_request_cancelled": "請求已取消。", "error_request_declined": "請求在另一台裝置上被拒絕。", "error_unexpected": "發生預料之外的錯誤。", - "review_and_approve": "審閱並批准登入", "scan_code_instruction": "請用您已登出的裝置掃描下列 QR Code。", "scan_qr_code": "掃描 QR Code", "select_qr_code": "選取「%(scanQRCode)s」", "sign_in_new_device": "登入新裝置", - "start_at_sign_in_screen": "從登入畫面開始", "waiting_for_device": "正在等待裝置登入" }, "register_action": "建立帳號", @@ -424,6 +421,7 @@ "other": "與另 %(count)s 個人…", "one": "與另 1 個人…" }, + "android": "安卓", "appearance": "外觀", "application": "應用程式", "are_you_sure": "您確定嗎?", @@ -462,6 +460,7 @@ "identity_server": "身分伺服器", "image": "圖片", "integration_manager": "整合管理員", + "ios": "iOS", "joined": "已加入", "labs": "實驗室", "legal": "法律", @@ -469,6 +468,7 @@ "loading": "載入中…", "location": "位置", "low_priority": "低優先度", + "matrix": "Matrix", "message": "訊息", "message_layout": "訊息佈局", "microphone": "麥克風", @@ -726,7 +726,6 @@ "notification_state": "通知狀態為 %(notificationState)s", "notifications_debug": "通知除錯", "number_of_users": "使用者數量", - "observe_only": "僅觀察", "original_event_source": "原始活動來源", "phase": "階段", "phase_cancelled": "已取消", @@ -734,7 +733,6 @@ "phase_requested": "已請求", "phase_started": "已開始", "phase_transaction": "交易", - "requester": "請求者", "room_encrypted": "聊天室已加密 ✅", "room_id": "聊天室 ID:%(roomId)s", "room_not_encrypted": "聊天室未加密 🚨", @@ -1458,14 +1456,6 @@ "view_rules": "檢視規則" }, "language_dropdown_label": "語言下拉式選單", - "lazy_loading": { - "disabled_action": "清除快取並重新同步", - "disabled_description1": "您之前曾在 %(host)s 上使用 %(brand)s 並啟用成員列表的延遲載入。在此版本中延遲載入已停用。由於本機快取在這兩個設定間不相容,%(brand)s 必須重新同步您的帳號。", - "disabled_description2": "如果其他版本的 %(brand)s 仍在其他分頁中開啟,請關閉它,因為在同一主機上使用同時啟用與停用惰性載入的 %(brand)s 可能會造成問題。", - "disabled_title": "不相容的本機快取", - "resync_description": "%(brand)s 現在僅使用低於原本3-5倍的記憶體,僅在需要時才會載入其他使用者的資訊。請等待我們與伺服器重新同步!", - "resync_title": "正在更新 %(brand)s" - }, "leave_room_dialog": { "last_person_warning": "您是這裡唯一的人。如果您離開,包含您在內的任何人都無法加入。", "leave_room_question": "您確定要離開聊天室「%(roomName)s」嗎?", diff --git a/linked-dependencies/matrix-react-sdk/src/indexing/EventIndex.ts b/linked-dependencies/matrix-react-sdk/src/indexing/EventIndex.ts index 69cb0e1218..15419eecf6 100644 --- a/linked-dependencies/matrix-react-sdk/src/indexing/EventIndex.ts +++ b/linked-dependencies/matrix-react-sdk/src/indexing/EventIndex.ts @@ -38,6 +38,7 @@ import { TimelineIndex, TimelineWindow, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { sleep } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; @@ -533,7 +534,7 @@ export default class EventIndex extends EventEmitter { const profiles: Record = {}; stateEvents.forEach((ev) => { - if (ev.getContent().membership === "join") { + if (ev.getContent().membership === KnownMembership.Join) { profiles[ev.getSender()!] = { displayname: ev.getContent().displayname, avatar_url: ev.getContent().avatar_url, @@ -754,7 +755,7 @@ export default class EventIndex extends EventEmitter { // This is sets the avatar URL. const memberEvent = eventMapper({ content: { - membership: "join", + membership: KnownMembership.Join, avatar_url: e.profile.avatar_url, displayname: e.profile.displayname, }, diff --git a/linked-dependencies/matrix-react-sdk/src/mjolnir/BanList.ts b/linked-dependencies/matrix-react-sdk/src/mjolnir/BanList.ts index 68c15282c1..b0b63c0817 100644 --- a/linked-dependencies/matrix-react-sdk/src/mjolnir/BanList.ts +++ b/linked-dependencies/matrix-react-sdk/src/mjolnir/BanList.ts @@ -16,12 +16,14 @@ limitations under the License. // Inspiration largely taken from Mjolnir itself +import { EventType } from "matrix-js-sdk/src/matrix"; + import { ListRule, RECOMMENDATION_BAN, recommendationToStable } from "./ListRule"; import { MatrixClientPeg } from "../MatrixClientPeg"; -export const RULE_USER = "m.policy.rule.user"; -export const RULE_ROOM = "m.policy.rule.room"; -export const RULE_SERVER = "m.policy.rule.server"; +export const RULE_USER = EventType.PolicyRuleUser; +export const RULE_ROOM = EventType.PolicyRuleRoom; +export const RULE_SERVER = EventType.PolicyRuleServer; // m.room.* events are legacy from when MSC2313 changed to m.policy.* last minute. export const USER_RULE_TYPES = [RULE_USER, "m.room.rule.user", "org.matrix.mjolnir.rule.user"]; @@ -29,7 +31,9 @@ export const ROOM_RULE_TYPES = [RULE_ROOM, "m.room.rule.room", "org.matrix.mjoln export const SERVER_RULE_TYPES = [RULE_SERVER, "m.room.rule.server", "org.matrix.mjolnir.rule.server"]; export const ALL_RULE_TYPES = [...USER_RULE_TYPES, ...ROOM_RULE_TYPES, ...SERVER_RULE_TYPES]; -export function ruleTypeToStable(rule: string): string | null { +export function ruleTypeToStable( + rule: string, +): EventType.PolicyRuleUser | EventType.PolicyRuleRoom | EventType.PolicyRuleServer | null { if (USER_RULE_TYPES.includes(rule)) { return RULE_USER; } @@ -72,7 +76,7 @@ export class BanList { { entity: entity, reason: reason, - recommendation: recommendationToStable(RECOMMENDATION_BAN, true), + recommendation: recommendationToStable(RECOMMENDATION_BAN, true)!, }, "rule:" + entity, ); diff --git a/linked-dependencies/matrix-react-sdk/src/mjolnir/ListRule.ts b/linked-dependencies/matrix-react-sdk/src/mjolnir/ListRule.ts index 3fc1b00768..c6595b33b3 100644 --- a/linked-dependencies/matrix-react-sdk/src/mjolnir/ListRule.ts +++ b/linked-dependencies/matrix-react-sdk/src/mjolnir/ListRule.ts @@ -14,14 +14,24 @@ See the License for the specific language governing permissions and limitations under the License. */ +// We are using experimental APIs here, so we need to disable the linter +// eslint-disable-next-line no-restricted-imports +import { PolicyRecommendation } from "matrix-js-sdk/src/models/invites-ignorer"; + import { MatrixGlob } from "../utils/MatrixGlob"; // Inspiration largely taken from Mjolnir itself -export const RECOMMENDATION_BAN = "m.ban"; -export const RECOMMENDATION_BAN_TYPES = [RECOMMENDATION_BAN, "org.matrix.mjolnir.ban"]; +export const RECOMMENDATION_BAN = PolicyRecommendation.Ban; +export const RECOMMENDATION_BAN_TYPES: PolicyRecommendation[] = [ + RECOMMENDATION_BAN, + "org.matrix.mjolnir.ban" as PolicyRecommendation, +]; -export function recommendationToStable(recommendation: string, unstable = true): string | null { +export function recommendationToStable( + recommendation: PolicyRecommendation, + unstable = true, +): PolicyRecommendation | null { if (RECOMMENDATION_BAN_TYPES.includes(recommendation)) { return unstable ? RECOMMENDATION_BAN_TYPES[RECOMMENDATION_BAN_TYPES.length - 1] : RECOMMENDATION_BAN; } @@ -35,7 +45,7 @@ export class ListRule { private readonly _reason: string; private readonly _kind: string; - public constructor(entity: string, action: string, reason: string, kind: string) { + public constructor(entity: string, action: PolicyRecommendation, reason: string, kind: string) { this._glob = new MatrixGlob(entity); this._entity = entity; this._action = recommendationToStable(action, false); diff --git a/linked-dependencies/matrix-react-sdk/src/models/Call.ts b/linked-dependencies/matrix-react-sdk/src/models/Call.ts index b6c1cda662..c7d53284cc 100644 --- a/linked-dependencies/matrix-react-sdk/src/models/Call.ts +++ b/linked-dependencies/matrix-react-sdk/src/models/Call.ts @@ -24,6 +24,7 @@ import { Room, RoomMember, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership, Membership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { randomString } from "matrix-js-sdk/src/randomstring"; import { CallType } from "matrix-js-sdk/src/webrtc/call"; @@ -57,6 +58,7 @@ import { UPDATE_EVENT } from "../stores/AsyncStore"; import { getJoinedNonFunctionalMembers } from "../utils/room/getJoinedNonFunctionalMembers"; import { isVideoRoom } from "../utils/video-rooms"; import { FontWatcher } from "../settings/watchers/FontWatcher"; +import { JitsiCallMemberContent, JitsiCallMemberEventType } from "../call-types"; const TIMEOUT_MS = 16000; @@ -307,8 +309,8 @@ export abstract class Call extends TypedEventEmitter => { - if (membership !== "join") this.setDisconnected(); + private onMyMembership = async (_room: Room, membership: Membership): Promise => { + if (membership !== KnownMembership.Join) this.setDisconnected(); }; private onStopMessaging = (uid: string): void => { @@ -321,18 +323,13 @@ export abstract class Call extends TypedEventEmitter this.setDisconnected(); } -export interface JitsiCallMemberContent { - // Connected device IDs - devices: string[]; - // Time at which this state event should be considered stale - expires_ts: number; -} +export type { JitsiCallMemberContent }; /** * A group call using Jitsi as a backend. */ export class JitsiCall extends Call { - public static readonly MEMBER_EVENT_TYPE = "io.element.video.member"; + public static readonly MEMBER_EVENT_TYPE = JitsiCallMemberEventType; public readonly STUCK_DEVICE_TIMEOUT_MS = 1000 * 60 * 60; // 1 hour private resendDevicesTimer: number | null = null; @@ -386,7 +383,7 @@ export class JitsiCall extends Call { devices = devices.filter((d) => d !== this.client.getDeviceId()); } // Must have a connected device and still be joined to the room - if (devices.length > 0 && member?.membership === "join") { + if (devices.length > 0 && member?.membership === KnownMembership.Join) { participants.set(member, new Set(devices)); if (expiresAt < allExpireAt) allExpireAt = expiresAt; } @@ -416,7 +413,7 @@ export class JitsiCall extends Call { * returns null, the update is skipped. */ private async updateDevices(fn: (devices: string[]) => string[] | null): Promise { - if (this.room.getMyMembership() !== "join") return; + if (this.room.getMyMembership() !== KnownMembership.Join) return; const event = this.room.currentState.getStateEvents(JitsiCall.MEMBER_EVENT_TYPE, this.client.getUserId()!); const content = event?.getContent(); @@ -758,7 +755,7 @@ export class ElementCall extends Call { name: "Element Call", type: WidgetType.CALL.preferred, url: url.toString(), - // waitForIframeLoad: false, + waitForIframeLoad: false, data: ElementCall.getWidgetData( client, roomId, @@ -781,7 +778,10 @@ export class ElementCall extends Call { overwriteData: IWidgetData, ): IWidgetData { let perParticipantE2EE = false; - if (client.isRoomEncrypted(roomId) && !SettingsStore.getValue("feature_disable_call_per_sender_encryption")) + if ( + client.getRoom(roomId)?.hasEncryptionStateEvent() && + !SettingsStore.getValue("feature_disable_call_per_sender_encryption") + ) perParticipantE2EE = true; return { ...currentData, diff --git a/linked-dependencies/matrix-react-sdk/src/models/RoomUpload.ts b/linked-dependencies/matrix-react-sdk/src/models/RoomUpload.ts index d6e0be4ca9..cc1b35315f 100644 --- a/linked-dependencies/matrix-react-sdk/src/models/RoomUpload.ts +++ b/linked-dependencies/matrix-react-sdk/src/models/RoomUpload.ts @@ -15,8 +15,7 @@ limitations under the License. */ import { IEventRelation, UploadProgress } from "matrix-js-sdk/src/matrix"; - -import { EncryptedFile } from "../customisations/models/IMediaEventContent"; +import { EncryptedFile } from "matrix-js-sdk/src/types"; export class RoomUpload { public readonly abortController = new AbortController(); diff --git a/linked-dependencies/matrix-react-sdk/src/modules/ModuleRunner.ts b/linked-dependencies/matrix-react-sdk/src/modules/ModuleRunner.ts index 1a94eb16b3..0c609f6f66 100644 --- a/linked-dependencies/matrix-react-sdk/src/modules/ModuleRunner.ts +++ b/linked-dependencies/matrix-react-sdk/src/modules/ModuleRunner.ts @@ -17,18 +17,108 @@ limitations under the License. import { safeSet } from "matrix-js-sdk/src/utils"; import { TranslationStringsObject } from "@matrix-org/react-sdk-module-api/lib/types/translations"; import { AnyLifecycle } from "@matrix-org/react-sdk-module-api/lib/lifecycles/types"; +import { + DefaultCryptoSetupExtensions, + ProvideCryptoSetupExtensions, +} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CryptoSetupExtensions"; +import { + DefaultExperimentalExtensions, + ProvideExperimentalExtensions, +} from "@matrix-org/react-sdk-module-api/lib/lifecycles/ExperimentalExtensions"; import { AppModule } from "./AppModule"; import { ModuleFactory } from "./ModuleFactory"; import "./ModuleComponents"; +/** + * Handles and manages extensions provided by modules. + */ +class ExtensionsManager { + // Private backing fields for extensions + private cryptoSetupExtension: ProvideCryptoSetupExtensions; + private experimentalExtension: ProvideExperimentalExtensions; + + /** `true` if `cryptoSetupExtension` is the default implementation; `false` if it is implemented by a module. */ + private hasDefaultCryptoSetupExtension = true; + + /** `true` if `experimentalExtension` is the default implementation; `false` if it is implemented by a module. */ + private hasDefaultExperimentalExtension = true; + + /** + * Create a new instance. + */ + public constructor() { + // Set up defaults + this.cryptoSetupExtension = new DefaultCryptoSetupExtensions(); + this.experimentalExtension = new DefaultExperimentalExtensions(); + } + + /** + * Provides a crypto setup extension. + * + * @returns The registered extension. If no module provides this extension, a default implementation is returned. + */ + public get cryptoSetup(): ProvideCryptoSetupExtensions { + return this.cryptoSetupExtension; + } + + /** + * Provides an experimental extension. + * + * @remarks + * This method extension is provided to simplify experimentation and development, and is not intended for production code. + * + * @returns The registered extension. If no module provides this extension, a default implementation is returned. + */ + public get experimental(): ProvideExperimentalExtensions { + return this.experimentalExtension; + } + + /** + * Add any extensions provided by the module. + * + * @param module - The appModule to check for extensions. + * + * @throws if an extension is provided by more than one module. + */ + public addExtensions(module: AppModule): void { + const runtimeModule = module.module; + + /* Add the cryptoSetup extension if any */ + if (runtimeModule.extensions?.cryptoSetup) { + if (this.hasDefaultCryptoSetupExtension) { + this.cryptoSetupExtension = runtimeModule.extensions?.cryptoSetup; + this.hasDefaultCryptoSetupExtension = false; + } else { + throw new Error( + `adding cryptoSetup extension implementation from module ${runtimeModule.moduleName} but an implementation was already provided.`, + ); + } + } + + /* Add the experimental extension if any */ + if (runtimeModule.extensions?.experimental) { + if (this.hasDefaultExperimentalExtension) { + this.experimentalExtension = runtimeModule.extensions?.experimental; + this.hasDefaultExperimentalExtension = false; + } else { + throw new Error( + `adding experimental extension implementation from module ${runtimeModule.moduleName} but an implementation was already provided.`, + ); + } + } + } +} + /** * Handles and coordinates the operation of modules. */ export class ModuleRunner { public static readonly instance = new ModuleRunner(); + private extensionsManager = new ExtensionsManager(); + private modules: AppModule[] = []; private constructor() { @@ -36,12 +126,22 @@ export class ModuleRunner { } /** - * Resets the runner, clearing all known modules. + * Exposes all extensions which may be overridden/provided by modules. + * + * @returns An `ExtensionsManager` which exposes the extensions. + */ + public get extensions(): ExtensionsManager { + return this.extensionsManager; + } + + /** + * Resets the runner, clearing all known modules, and all extensions * * Intended for test usage only. */ public reset(): void { this.modules = []; + this.extensionsManager = new ExtensionsManager(); } /** @@ -72,7 +172,12 @@ export class ModuleRunner { * @param factory The module factory. */ public registerModule(factory: ModuleFactory): void { - this.modules.push(new AppModule(factory)); + const appModule = new AppModule(factory); + + this.modules.push(appModule); + + // Check if the new module provides any extensions, and also ensure a given extension is only provided by a single runtime module. + this.extensionsManager.addExtensions(appModule); } /** diff --git a/linked-dependencies/matrix-react-sdk/src/settings/Settings.tsx b/linked-dependencies/matrix-react-sdk/src/settings/Settings.tsx index 3dc842945e..6be0a6b46f 100644 --- a/linked-dependencies/matrix-react-sdk/src/settings/Settings.tsx +++ b/linked-dependencies/matrix-react-sdk/src/settings/Settings.tsx @@ -1,6 +1,6 @@ /* Copyright 2017 Travis Ralston -Copyright 2018 - 2023 The Matrix.org Foundation C.I.C. +Copyright 2018 - 2024 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -89,6 +89,7 @@ export enum LabGroup { Encryption, Experimental, Developer, + Ui, } export enum Features { @@ -98,6 +99,7 @@ export enum Features { OidcNativeFlow = "feature_oidc_native_flow", // If true, every new login will use the new rust crypto implementation RustCrypto = "feature_rust_crypto", + ReleaseAnnouncement = "feature_release_announcement", } export const labGroupNames: Record = { @@ -114,6 +116,7 @@ export const labGroupNames: Record = { [LabGroup.Encryption]: _td("labs|group_encryption"), [LabGroup.Experimental]: _td("labs|group_experimental"), [LabGroup.Developer]: _td("labs|group_developer"), + [LabGroup.Ui]: _td("labs|group_ui"), }; export type SettingValueType = @@ -583,14 +586,23 @@ export const SETTINGS: { [setting: string]: ISetting } = { supportedLevels: LEVELS_ROOM_OR_ACCOUNT, default: false, }, + // Used to be a feature, name kept for backwards compat "feature_hidebold": { - isFeature: true, - labsGroup: LabGroup.Rooms, - configDisablesSetting: true, supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, displayName: _td("labs|hidebold"), default: false, }, + "Notifications.showbold": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + displayName: _td("settings|showbold"), + default: false, + invertedSettingName: "feature_hidebold", + }, + "Notifications.tac_only_notifications": { + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + displayName: _td("settings|tac_only_notifications"), + default: true, + }, "feature_ask_to_join": { isFeature: true, labsGroup: LabGroup.Rooms, @@ -1145,6 +1157,24 @@ export const SETTINGS: { [setting: string]: ISetting } = { default: false, isFeature: true, }, + /** + * Enable or disable the release announcement feature + */ + [Features.ReleaseAnnouncement]: { + isFeature: true, + labsGroup: LabGroup.Ui, + supportedLevels: LEVELS_DEVICE_ONLY_SETTINGS_WITH_CONFIG, + default: true, + displayName: _td("labs|release_announcement"), + }, + /** + * Managed by the {@link ReleaseAnnouncementStore} + * Store the release announcement data + */ + "releaseAnnouncementData": { + supportedLevels: LEVELS_ACCOUNT_SETTINGS, + default: {}, + }, [UIFeature.RoomHistorySettings]: { supportedLevels: LEVELS_UI_FEATURE, default: true, diff --git a/linked-dependencies/matrix-react-sdk/src/settings/handlers/AccountSettingsHandler.ts b/linked-dependencies/matrix-react-sdk/src/settings/handlers/AccountSettingsHandler.ts index e931a92600..639bef628c 100644 --- a/linked-dependencies/matrix-react-sdk/src/settings/handlers/AccountSettingsHandler.ts +++ b/linked-dependencies/matrix-react-sdk/src/settings/handlers/AccountSettingsHandler.ts @@ -17,6 +17,7 @@ limitations under the License. import { ClientEvent, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { defer } from "matrix-js-sdk/src/utils"; +import { isEqual } from "lodash"; import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler"; import { objectClone, objectKeyChanges } from "../../utils/objects"; @@ -168,7 +169,7 @@ export default class AccountSettingsHandler extends MatrixClientBackedSettingsHa // which race between different lines. const deferred = defer(); const handler = (event: MatrixEvent): void => { - if (event.getType() !== eventType || event.getContent()[field] !== value) return; + if (event.getType() !== eventType || !isEqual(event.getContent()[field], value)) return; this.client.off(ClientEvent.AccountData, handler); deferred.resolve(); }; diff --git a/linked-dependencies/matrix-react-sdk/src/settings/handlers/RoomSettingsHandler.ts b/linked-dependencies/matrix-react-sdk/src/settings/handlers/RoomSettingsHandler.ts index 12c3124365..652c323a9e 100644 --- a/linked-dependencies/matrix-react-sdk/src/settings/handlers/RoomSettingsHandler.ts +++ b/linked-dependencies/matrix-react-sdk/src/settings/handlers/RoomSettingsHandler.ts @@ -15,7 +15,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { MatrixClient, MatrixEvent, RoomState, RoomStateEvent } from "matrix-js-sdk/src/matrix"; +import { MatrixClient, MatrixEvent, RoomState, RoomStateEvent, StateEvents } from "matrix-js-sdk/src/matrix"; import { defer } from "matrix-js-sdk/src/utils"; import MatrixClientBackedSettingsHandler from "./MatrixClientBackedSettingsHandler"; @@ -24,6 +24,9 @@ import { SettingLevel } from "../SettingLevel"; import { WatchManager } from "../WatchManager"; const DEFAULT_SETTINGS_EVENT_TYPE = "im.vector.web.settings"; +const PREVIEW_URLS_EVENT_TYPE = "org.matrix.room.preview_urls"; + +type RoomSettingsEventType = typeof DEFAULT_SETTINGS_EVENT_TYPE | typeof PREVIEW_URLS_EVENT_TYPE; /** * Gets and sets settings at the "room" level. @@ -88,7 +91,12 @@ export default class RoomSettingsHandler extends MatrixClientBackedSettingsHandl } // helper function to send state event then await it being echoed back - private async sendStateEvent(roomId: string, eventType: string, field: string, value: any): Promise { + private async sendStateEvent( + roomId: string, + eventType: K, + field: F, + value: StateEvents[K][F], + ): Promise { const content = this.getSettings(roomId, eventType) || {}; content[field] = value; diff --git a/linked-dependencies/matrix-react-sdk/src/shouldHideEvent.ts b/linked-dependencies/matrix-react-sdk/src/shouldHideEvent.ts index dcfc5d920c..0ee16009e1 100644 --- a/linked-dependencies/matrix-react-sdk/src/shouldHideEvent.ts +++ b/linked-dependencies/matrix-react-sdk/src/shouldHideEvent.ts @@ -15,6 +15,7 @@ */ import { MatrixEvent, EventType, RelationType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import SettingsStore from "./settings/SettingsStore"; import { IRoomState } from "./components/structures/RoomView"; @@ -39,10 +40,11 @@ function memberEventDiff(ev: MatrixEvent): IDiff { const prevContent = ev.getPrevContent(); const isMembershipChanged = content.membership !== prevContent.membership; - diff.isJoin = isMembershipChanged && content.membership === "join"; - diff.isPart = isMembershipChanged && content.membership === "leave" && ev.getStateKey() === ev.getSender(); + diff.isJoin = isMembershipChanged && content.membership === KnownMembership.Join; + diff.isPart = + isMembershipChanged && content.membership === KnownMembership.Leave && ev.getStateKey() === ev.getSender(); - const isJoinToJoin = !isMembershipChanged && content.membership === "join"; + const isJoinToJoin = !isMembershipChanged && content.membership === KnownMembership.Join; diff.isDisplaynameChange = isJoinToJoin && content.displayname !== prevContent.displayname; diff.isAvatarChange = isJoinToJoin && content.avatar_url !== prevContent.avatar_url; return diff; diff --git a/linked-dependencies/matrix-react-sdk/src/slash-commands/interface.ts b/linked-dependencies/matrix-react-sdk/src/slash-commands/interface.ts index 94e95126c0..8efc2b3ce9 100644 --- a/linked-dependencies/matrix-react-sdk/src/slash-commands/interface.ts +++ b/linked-dependencies/matrix-react-sdk/src/slash-commands/interface.ts @@ -17,7 +17,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { IContent } from "matrix-js-sdk/src/matrix"; +import { RoomMessageEventContent } from "matrix-js-sdk/src/types"; import { _td } from "../languageHandler"; import { XOR } from "../@types/common"; @@ -31,4 +31,4 @@ export const CommandCategories = { other: _td("slash_command|category_other"), }; -export type RunResult = XOR<{ error: Error }, { promise: Promise }>; +export type RunResult = XOR<{ error: Error }, { promise: Promise }>; diff --git a/linked-dependencies/matrix-react-sdk/src/stores/BreadcrumbsStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/BreadcrumbsStore.ts index bacbfe97be..36bb0a78b6 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/BreadcrumbsStore.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/BreadcrumbsStore.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { Room, RoomEvent, ClientEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import SettingsStore from "../settings/SettingsStore"; @@ -91,7 +92,7 @@ export class BreadcrumbsStore extends AsyncStoreWithClient { // The tests might not result in a valid room object. const room = this.matrixClient.getRoom(payload.room_id); const membership = room?.getMyMembership(); - if (room && membership === "join") await this.appendRoom(room); + if (room && membership === KnownMembership.Join) await this.appendRoom(room); } } else if (payload.action === Action.JoinRoom) { const room = this.matrixClient.getRoom(payload.roomId); diff --git a/linked-dependencies/matrix-react-sdk/src/stores/MemberListStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/MemberListStore.ts index d7c50e0078..f9e1df79a4 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/MemberListStore.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/MemberListStore.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { Room, RoomMember } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import SettingsStore from "../settings/SettingsStore"; import { SdkContextClass } from "../contexts/SDKContext"; @@ -90,7 +91,7 @@ export class MemberListStore { // pull straight from the server. Don't use a since token as we don't have earlier deltas // accumulated. room.currentState.markOutOfBandMembersStarted(); - const response = await this.stores.client!.members(roomId, undefined, "leave"); + const response = await this.stores.client!.members(roomId, undefined, KnownMembership.Leave); const memberEvents = response.chunk.map(this.stores.client!.getEventMapper()); room.currentState.setOutOfBandMembers(memberEvents); } else { @@ -167,7 +168,7 @@ export class MemberListStore { invited: [], }; members.forEach((m) => { - if (m.membership !== "join" && m.membership !== "invite") { + if (m.membership !== KnownMembership.Join && m.membership !== KnownMembership.Invite) { return; // bail early for left/banned users } if (query) { @@ -179,10 +180,10 @@ export class MemberListStore { } } switch (m.membership) { - case "join": + case KnownMembership.Join: result.joined.push(m); break; - case "invite": + case KnownMembership.Invite: result.invited.push(m); break; } diff --git a/linked-dependencies/matrix-react-sdk/src/stores/OwnBeaconStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/OwnBeaconStore.ts index e2b4a0c07b..55399ef264 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/OwnBeaconStore.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/OwnBeaconStore.ts @@ -28,6 +28,7 @@ import { MBeaconInfoEventContent, M_BEACON, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import defaultDispatcher from "../dispatcher/dispatcher"; @@ -313,7 +314,7 @@ export class OwnBeaconStore extends AsyncStoreWithClient { // in PSF-797 // stop watching beacons in rooms where user is no longer a member - if (member.membership === "leave" || member.membership === "ban") { + if (member.membership === KnownMembership.Leave || member.membership === KnownMembership.Ban) { this.beaconsByRoomId.get(roomState.roomId)?.forEach(this.removeBeacon); this.beaconsByRoomId.delete(roomState.roomId); } diff --git a/linked-dependencies/matrix-react-sdk/src/stores/ReleaseAnnouncementStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/ReleaseAnnouncementStore.ts new file mode 100644 index 0000000000..9beeed4f70 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/stores/ReleaseAnnouncementStore.ts @@ -0,0 +1,176 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import { TypedEventEmitter } from "matrix-js-sdk/src/matrix"; +import { logger } from "matrix-js-sdk/src/logger"; + +import SettingsStore from "../settings/SettingsStore"; +import { SettingLevel } from "../settings/SettingLevel"; +import { Features } from "../settings/Settings"; + +/** + * The features are shown in the array order. + */ +const FEATURES = ["threadsActivityCentre"] as const; +/** + * All the features that can be shown in the release announcements. + */ +export type Feature = (typeof FEATURES)[number]; +/** + * The stored settings for the release announcements. + * The boolean is at true when the user has viewed the feature + */ +type StoredSettings = Record; + +/** + * The events emitted by the ReleaseAnnouncementStore. + */ +type ReleaseAnnouncementStoreEvents = "releaseAnnouncementChanged"; +/** + * The handlers for the ReleaseAnnouncementStore events. + */ +type HandlerMap = { + releaseAnnouncementChanged: (newFeature: Feature | null) => void; +}; + +/** + * The ReleaseAnnouncementStore is responsible for managing the release announcements. + * It keeps track of the viewed release announcements and emits events when the release announcement changes. + */ +export class ReleaseAnnouncementStore extends TypedEventEmitter { + /** + * The singleton instance of the ReleaseAnnouncementStore. + * @private + */ + private static internalInstance: ReleaseAnnouncementStore; + /** + * The index of the feature to show. + * @private + */ + private index = 0; + + /** + * The singleton instance of the ReleaseAnnouncementStore. + */ + public static get instance(): ReleaseAnnouncementStore { + if (!ReleaseAnnouncementStore.internalInstance) { + ReleaseAnnouncementStore.internalInstance = new ReleaseAnnouncementStore(); + } + return ReleaseAnnouncementStore.internalInstance; + } + + /** + * Should be used only for testing purposes. + * @internal + */ + public constructor() { + super(); + SettingsStore.watchSetting("releaseAnnouncementData", null, () => { + this.emit("releaseAnnouncementChanged", this.getReleaseAnnouncement()); + }); + } + + /** + * Get the viewed release announcements from the settings. + * @private + */ + private getViewedReleaseAnnouncements(): StoredSettings { + return SettingsStore.getValue("releaseAnnouncementData"); + } + + /** + * Check if the release announcement is enabled. + * @private + */ + private isReleaseAnnouncementEnabled(): boolean { + return SettingsStore.getValue(Features.ReleaseAnnouncement); + } + + /** + * Get the release announcement that should be displayed + * @returns The feature to announce or null if there is no feature to announce + */ + public getReleaseAnnouncement(): Feature | null { + // Do nothing if the release announcement is disabled + const isReleaseAnnouncementEnabled = this.isReleaseAnnouncementEnabled(); + if (!isReleaseAnnouncementEnabled) return null; + + const viewedReleaseAnnouncements = this.getViewedReleaseAnnouncements(); + + // Find the first feature that has not been viewed + for (let i = this.index; i < FEATURES.length; i++) { + if (!viewedReleaseAnnouncements[FEATURES[i]]) { + this.index = i; + return FEATURES[this.index]; + } + } + + // All features have been viewed + return null; + } + + /** + * Mark the current release announcement as viewed. + * This will update the account settings + * @private + */ + private async markReleaseAnnouncementAsViewed(): Promise { + // Do nothing if the release announcement is disabled + const isReleaseAnnouncementEnabled = this.isReleaseAnnouncementEnabled(); + if (!isReleaseAnnouncementEnabled) return; + + const viewedReleaseAnnouncements = this.getViewedReleaseAnnouncements(); + + // If the index is out of bounds, do nothing + // Normally it shouldn't happen, but it's better to be safe + const feature = FEATURES[this.index]; + if (!feature) return; + + // Mark the feature as viewed + viewedReleaseAnnouncements[FEATURES[this.index]] = true; + this.index++; + + // Do sanity check if we can store the new value in the settings + const isSupported = SettingsStore.isLevelSupported(SettingLevel.ACCOUNT); + if (!isSupported) return; + + const canSetValue = SettingsStore.canSetValue("releaseAnnouncementData", null, SettingLevel.ACCOUNT); + if (canSetValue) { + try { + await SettingsStore.setValue( + "releaseAnnouncementData", + null, + SettingLevel.ACCOUNT, + viewedReleaseAnnouncements, + ); + } catch (e) { + logger.log("Failed to set release announcement settings", e); + } + } + } + + /** + * Mark the current release announcement as viewed and move to the next release announcement. + * This will update the account settings and emit the `releaseAnnouncementChanged` event + */ + public async nextReleaseAnnouncement(): Promise { + await this.markReleaseAnnouncementAsViewed(); + + this.emit("releaseAnnouncementChanged", this.getReleaseAnnouncement()); + } +} diff --git a/linked-dependencies/matrix-react-sdk/src/stores/RoomViewStore.tsx b/linked-dependencies/matrix-react-sdk/src/stores/RoomViewStore.tsx index 7d91192ff3..29104354df 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/RoomViewStore.tsx +++ b/linked-dependencies/matrix-react-sdk/src/stores/RoomViewStore.tsx @@ -19,6 +19,7 @@ limitations under the License. import React, { ReactNode } from "react"; import * as utils from "matrix-js-sdk/src/utils"; import { MatrixError, JoinRule, Room, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { ViewRoom as ViewRoomEvent } from "@matrix-org/analytics-events/types/typescript/ViewRoom"; import { JoinedRoom as JoinedRoomEvent } from "@matrix-org/analytics-events/types/typescript/JoinedRoom"; @@ -62,6 +63,7 @@ import { ActionPayload } from "../dispatcher/payloads"; import { CancelAskToJoinPayload } from "../dispatcher/payloads/CancelAskToJoinPayload"; import { SubmitAskToJoinPayload } from "../dispatcher/payloads/SubmitAskToJoinPayload"; import { ModuleRunner } from "../modules/ModuleRunner"; +import { setMarkedUnreadState } from "../utils/notifications"; const NUM_JOIN_RETRY = 5; @@ -497,6 +499,8 @@ export class RoomViewStore extends EventEmitter { if (room) { pauseNonLiveBroadcastFromOtherRoom(room, this.stores.voiceBroadcastPlaybacksStore); this.doMaybeSetCurrentVoiceBroadcastPlayback(room); + + await setMarkedUnreadState(room, MatrixClientPeg.safeGet(), false); } } else if (payload.room_alias) { // Try the room alias to room ID navigation cache first to avoid @@ -607,7 +611,7 @@ export class RoomViewStore extends EventEmitter { private getInvitingUserId(roomId: string): string | undefined { const cli = MatrixClientPeg.safeGet(); const room = cli.getRoom(roomId); - if (room?.getMyMembership() === "invite") { + if (room?.getMyMembership() === KnownMembership.Invite) { const myMember = room.getMember(cli.getSafeUserId()); const inviteEvent = myMember ? myMember.events.member : null; return inviteEvent?.getSender(); diff --git a/linked-dependencies/matrix-react-sdk/src/stores/SetupEncryptionStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/SetupEncryptionStore.ts index 72e463a9c7..e3069d4333 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/SetupEncryptionStore.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/SetupEncryptionStore.ts @@ -1,5 +1,5 @@ /* -Copyright 2020 The Matrix.org Foundation C.I.C. +Copyright 2020, 2024 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -17,10 +17,9 @@ limitations under the License. import EventEmitter from "events"; import { VerificationPhase, VerificationRequest, VerificationRequestEvent } from "matrix-js-sdk/src/crypto-api"; import { IKeyBackupInfo } from "matrix-js-sdk/src/crypto/keybackup"; -import { ISecretStorageKeyInfo } from "matrix-js-sdk/src/crypto/api"; import { logger } from "matrix-js-sdk/src/logger"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; -import { Device } from "matrix-js-sdk/src/matrix"; +import { Device, SecretStorage } from "matrix-js-sdk/src/matrix"; import { MatrixClientPeg } from "../MatrixClientPeg"; import { AccessCancelledError, accessSecretStorage } from "../SecurityManager"; @@ -29,6 +28,7 @@ import InteractiveAuthDialog from "../components/views/dialogs/InteractiveAuthDi import { _t } from "../languageHandler"; import { SdkContextClass } from "../contexts/SDKContext"; import { asyncSome } from "../utils/arrays"; +import { initialiseDehydration } from "../utils/device/dehydration"; export enum Phase { Loading = 0, @@ -48,7 +48,7 @@ export class SetupEncryptionStore extends EventEmitter { // ID of the key that the secrets we want are encrypted with public keyId: string | null = null; // Descriptor of the key that the secrets we want are encrypted with - public keyInfo: ISecretStorageKeyInfo | null = null; + public keyInfo: SecretStorage.SecretStorageKeyDescription | null = null; public hasDevicesToVerifyAgainst?: boolean; public static sharedInstance(): SetupEncryptionStore { @@ -112,8 +112,12 @@ export class SetupEncryptionStore extends EventEmitter { const userDevices: Iterable = (await crypto.getUserDeviceInfo([ownUserId])).get(ownUserId)?.values() ?? []; this.hasDevicesToVerifyAgainst = await asyncSome(userDevices, async (device) => { - // ignore the dehydrated device + // Ignore dehydrated devices. `dehydratedDevice` is set by the + // implementation of MSC2697, whereas MSC3814 proposes that devices + // should set a `dehydrated` flag in the device key. We ignore + // both types of dehydrated devices. if (dehydratedDevice && device.deviceId == dehydratedDevice?.device_id) return false; + if (device.dehydrated) return false; // ignore devices without an identity key if (!device.getIdentityKey()) return false; @@ -145,11 +149,17 @@ export class SetupEncryptionStore extends EventEmitter { await new Promise((resolve: (value?: unknown) => void, reject: (reason?: any) => void) => { accessSecretStorage(async (): Promise => { await cli.checkOwnCrossSigningTrust(); + + // The remaining tasks (device dehydration and restoring + // key backup) may take some time due to processing many + // to-device messages in the case of device dehydration, or + // having many keys to restore in the case of key backups, + // so we allow the dialog to advance before this. resolve(); + + await initialiseDehydration(); + if (backupInfo) { - // A complete restore can take many minutes for large - // accounts / slow servers, so we allow the dialog - // to advance before this. await cli.restoreKeyBackupWithSecretStorage(backupInfo); } }).catch(reject); @@ -256,6 +266,9 @@ export class SetupEncryptionStore extends EventEmitter { }, setupNewCrossSigning: true, }); + + await initialiseDehydration(true); + this.phase = Phase.Finished; }, true); } catch (e) { diff --git a/linked-dependencies/matrix-react-sdk/src/stores/notifications/RoomNotificationState.ts b/linked-dependencies/matrix-react-sdk/src/stores/notifications/RoomNotificationState.ts index 0503485584..80ffbd03f4 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/notifications/RoomNotificationState.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/notifications/RoomNotificationState.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { MatrixEventEvent, RoomEvent, ClientEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import type { Room, MatrixEvent } from "matrix-js-sdk/src/matrix"; import type { IDestroyable } from "../../utils/IDestroyable"; @@ -23,6 +24,7 @@ import { readReceiptChangeIsFor } from "../../utils/read-receipts"; import * as RoomNotifs from "../../RoomNotifs"; import { NotificationState } from "./NotificationState"; import SettingsStore from "../../settings/SettingsStore"; +import { MARKED_UNREAD_TYPE_STABLE, MARKED_UNREAD_TYPE_UNSTABLE } from "../../utils/notifications"; export class RoomNotificationState extends NotificationState implements IDestroyable { public constructor( @@ -36,6 +38,7 @@ export class RoomNotificationState extends NotificationState implements IDestroy this.room.on(RoomEvent.LocalEchoUpdated, this.handleLocalEchoUpdated); this.room.on(RoomEvent.Timeline, this.handleRoomEventUpdate); this.room.on(RoomEvent.Redaction, this.handleRoomEventUpdate); + this.room.on(RoomEvent.AccountData, this.handleRoomAccountDataUpdate); this.room.on(RoomEvent.UnreadNotifications, this.handleNotificationCountUpdate); // for server-sent counts cli.on(MatrixEventEvent.Decrypted, this.onEventDecrypted); @@ -51,6 +54,7 @@ export class RoomNotificationState extends NotificationState implements IDestroy this.room.removeListener(RoomEvent.LocalEchoUpdated, this.handleLocalEchoUpdated); this.room.removeListener(RoomEvent.Timeline, this.handleRoomEventUpdate); this.room.removeListener(RoomEvent.Redaction, this.handleRoomEventUpdate); + this.room.removeListener(RoomEvent.AccountData, this.handleRoomAccountDataUpdate); cli.removeListener(MatrixEventEvent.Decrypted, this.onEventDecrypted); cli.removeListener(ClientEvent.AccountData, this.handleAccountDataUpdate); } @@ -90,13 +94,20 @@ export class RoomNotificationState extends NotificationState implements IDestroy } }; + private handleRoomAccountDataUpdate = (ev: MatrixEvent): void => { + if ([MARKED_UNREAD_TYPE_STABLE, MARKED_UNREAD_TYPE_UNSTABLE].includes(ev.getType())) { + this.updateNotificationState(); + } + }; + private updateNotificationState(): void { const snapshot = this.snapshot(); const { level, symbol, count } = RoomNotifs.determineUnreadState(this.room, undefined, this.includeThreads); const muted = RoomNotifs.getRoomNotifsState(this.room.client, this.room.roomId) === RoomNotifs.RoomNotifState.Mute; - const knocked = SettingsStore.getValue("feature_ask_to_join") && this.room.getMyMembership() === "knock"; + const knocked = + SettingsStore.getValue("feature_ask_to_join") && this.room.getMyMembership() === KnownMembership.Knock; this._level = level; this._symbol = symbol; this._count = count; diff --git a/linked-dependencies/matrix-react-sdk/src/stores/room-list/RoomListStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/room-list/RoomListStore.ts index b6e65fada7..16c4d3be5b 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/room-list/RoomListStore.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/room-list/RoomListStore.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { MatrixClient, Room, RoomState, EventType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import SettingsStore from "../../settings/SettingsStore"; @@ -233,7 +234,12 @@ export class RoomListStoreClass extends AsyncStoreWithClient implements return; } } - await this.handleRoomUpdate(updatedRoom, RoomUpdateCause.Timeline); + // If the join rule changes we need to update the tags for the room. + // A conference tag is determined by the room public join rule. + if (eventPayload.event.getType() === EventType.RoomJoinRules) + await this.handleRoomUpdate(updatedRoom, RoomUpdateCause.PossibleTagChange); + else await this.handleRoomUpdate(updatedRoom, RoomUpdateCause.Timeline); + this.updateFn.trigger(); }; if (!room) { @@ -350,7 +356,7 @@ export class RoomListStoreClass extends AsyncStoreWithClient implements } private async handleRoomUpdate(room: Room, cause: RoomUpdateCause): Promise { - if (cause === RoomUpdateCause.NewRoom && room.getMyMembership() === "invite") { + if (cause === RoomUpdateCause.NewRoom && room.getMyMembership() === KnownMembership.Invite) { // Let the visibility provider know that there is a new invited room. It would be nice // if this could just be an event that things listen for but the point of this is that // we delay doing anything about this room until the VoipUserMapper had had a chance diff --git a/linked-dependencies/matrix-react-sdk/src/stores/room-list/algorithms/Algorithm.ts b/linked-dependencies/matrix-react-sdk/src/stores/room-list/algorithms/Algorithm.ts index 0645b7e49b..267b9bd742 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/room-list/algorithms/Algorithm.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/room-list/algorithms/Algorithm.ts @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { Room } from "matrix-js-sdk/src/matrix"; +import { JoinRule, Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { isNullOrUndefined } from "matrix-js-sdk/src/utils"; import { EventEmitter } from "events"; import { logger } from "matrix-js-sdk/src/logger"; @@ -172,7 +173,7 @@ export class Algorithm extends EventEmitter { } private doUpdateStickyRoom(val: Room | null): void { - if (val?.isSpaceRoom() && val.getMyMembership() !== "invite") { + if (val?.isSpaceRoom() && val.getMyMembership() !== KnownMembership.Invite) { // no-op sticky rooms for spaces - they're effectively virtual rooms val = null; } @@ -576,6 +577,9 @@ export class Algorithm extends EventEmitter { tags = [DefaultTagID.DM]; } } + if (room.isCallRoom() && (room.getJoinRule() === JoinRule.Public || room.getJoinRule() === JoinRule.Knock)) { + tags.push(DefaultTagID.Conference); + } return tags; } diff --git a/linked-dependencies/matrix-react-sdk/src/stores/room-list/models.ts b/linked-dependencies/matrix-react-sdk/src/stores/room-list/models.ts index 1c19f82494..d8b0488842 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/room-list/models.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/room-list/models.ts @@ -21,6 +21,7 @@ export enum DefaultTagID { LowPriority = "m.lowpriority", Favourite = "m.favourite", DM = "im.vector.fake.direct", + Conference = "im.vector.fake.conferences", ServerNotice = "m.server_notice", Suggested = "im.vector.fake.suggested", } @@ -29,6 +30,7 @@ export const OrderedDefaultTagIDs = [ DefaultTagID.Invite, DefaultTagID.Favourite, DefaultTagID.DM, + DefaultTagID.Conference, DefaultTagID.Untagged, DefaultTagID.LowPriority, DefaultTagID.ServerNotice, diff --git a/linked-dependencies/matrix-react-sdk/src/stores/spaces/SpaceStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/spaces/SpaceStore.ts index 0075e99231..966b564d68 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/spaces/SpaceStore.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/spaces/SpaceStore.ts @@ -26,6 +26,7 @@ import { ClientEvent, ISendEventResponse, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { AsyncStoreWithClient } from "../AsyncStoreWithClient"; @@ -74,7 +75,13 @@ interface IState {} const ACTIVE_SPACE_LS_KEY = "mx_active_space"; -const metaSpaceOrder: MetaSpace[] = [MetaSpace.Home, MetaSpace.Favourites, MetaSpace.People, MetaSpace.Orphans]; +const metaSpaceOrder: MetaSpace[] = [ + MetaSpace.Home, + MetaSpace.Favourites, + MetaSpace.People, + MetaSpace.Orphans, + MetaSpace.VideoRooms, +]; const MAX_SUGGESTED_ROOMS = 20; @@ -255,8 +262,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient { // else view space home or home depending on what is being clicked on if ( roomId && - cliSpace?.getMyMembership() !== "invite" && - this.matrixClient.getRoom(roomId)?.getMyMembership() === "join" && + cliSpace?.getMyMembership() !== KnownMembership.Invite && + this.matrixClient.getRoom(roomId)?.getMyMembership() === KnownMembership.Join && this.isRoomInSpace(space, roomId) ) { defaultDispatcher.dispatch({ @@ -325,7 +332,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { .filter((roomInfo) => { return ( roomInfo.room_type !== RoomType.Space && - this.matrixClient?.getRoom(roomInfo.room_id)?.getMyMembership() !== "join" + this.matrixClient?.getRoom(roomInfo.room_id)?.getMyMembership() !== KnownMembership.Join ); }) .map((roomInfo) => ({ @@ -368,7 +375,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient { return history[history.length - 1]; }) .filter((room) => { - return room?.getMyMembership() === "join" || room?.getMyMembership() === "invite"; + return ( + room?.getMyMembership() === KnownMembership.Join || + room?.getMyMembership() === KnownMembership.Invite + ); }) || [] ); } @@ -379,7 +389,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { public getChildSpaces(spaceId: string): Room[] { // don't show invited subspaces as they surface at the top level for better visibility - return this.getChildren(spaceId).filter((r) => r.isSpaceRoom() && r.getMyMembership() === "join"); + return this.getChildren(spaceId).filter((r) => r.isSpaceRoom() && r.getMyMembership() === KnownMembership.Join); } public getParents(roomId: string, canonicalOnly = false): Room[] { @@ -428,7 +438,9 @@ export class SpaceStoreClass extends AsyncStoreWithClient { if (space === MetaSpace.Home && this.allRoomsInHome) { return true; } - + if (space === MetaSpace.VideoRooms) { + return !!this.matrixClient?.getRoom(roomId)?.isCallRoom(); + } if (this.getSpaceFilteredRoomIds(space, includeDescendantSpaces)?.has(roomId)) { return true; } @@ -593,7 +605,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { private rebuildParentMap = (): void => { if (!this.matrixClient) return; const joinedSpaces = this.matrixClient.getVisibleRooms(this._msc3946ProcessDynamicPredecessor).filter((r) => { - return r.isSpaceRoom() && r.getMyMembership() === "join"; + return r.isSpaceRoom() && r.getMyMembership() === KnownMembership.Join; }); this.parentMap = new EnhancedMap>(); @@ -717,12 +729,12 @@ export class SpaceStoreClass extends AsyncStoreWithClient { return ( !this.parentMap.get(room.roomId)?.size || // put all orphaned rooms in the Home Space !!DMRoomMap.shared().getUserIdForRoomId(room.roomId) || // put all DMs in the Home Space - room.getMyMembership() === "invite" + room.getMyMembership() === KnownMembership.Invite ); // put all invites in the Home Space }; private static isInSpace(member?: RoomMember | null): boolean { - return member?.membership === "join" || member?.membership === "invite"; + return member?.membership === KnownMembership.Join || member?.membership === KnownMembership.Invite; } // Method for resolving the impact of a single user's membership change in the given Space and its hierarchy @@ -766,7 +778,8 @@ export class SpaceStoreClass extends AsyncStoreWithClient { const hiddenChildren = new EnhancedMap>(); visibleRooms.forEach((room) => { - if (!["join", "invite"].includes(room.getMyMembership())) return; + if (!([KnownMembership.Join, KnownMembership.Invite] as Array).includes(room.getMyMembership())) + return; this.getParents(room.roomId).forEach((parent) => { hiddenChildren.getOrCreate(parent.roomId, new Set()).add(room.roomId); }); @@ -796,7 +809,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { space ?.getMembers() .filter((m) => { - return m.membership === "join" || m.membership === "invite"; + return m.membership === KnownMembership.Join || m.membership === KnownMembership.Invite; }) .map((m) => m.userId), ); @@ -924,7 +937,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { if (!room.isSpaceRoom()) { this.onRoomsUpdate(); - if (membership === "join") { + if (membership === KnownMembership.Join) { // the user just joined a room, remove it from the suggested list if it was there const numSuggestedRooms = this._suggestedRooms.length; this._suggestedRooms = this._suggestedRooms.filter((r) => r.room_id !== room.roomId); @@ -935,7 +948,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } // if the room currently being viewed was just joined then switch to its related space - if (newMembership === "join" && room.roomId === SdkContextClass.instance.roomViewStore.getRoomId()) { + if ( + newMembership === KnownMembership.Join && + room.roomId === SdkContextClass.instance.roomViewStore.getRoomId() + ) { this.switchSpaceIfNeeded(room.roomId); } } @@ -943,13 +959,13 @@ export class SpaceStoreClass extends AsyncStoreWithClient { } // Space - if (membership === "invite") { + if (membership === KnownMembership.Invite) { const len = this._invitedSpaces.size; this._invitedSpaces.add(room); if (len !== this._invitedSpaces.size) { this.emit(UPDATE_INVITED_SPACES, this.invitedSpaces); } - } else if (oldMembership === "invite" && membership !== "join") { + } else if (oldMembership === KnownMembership.Invite && membership !== KnownMembership.Join) { if (this._invitedSpaces.delete(room)) { this.emit(UPDATE_INVITED_SPACES, this.invitedSpaces); } @@ -962,10 +978,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.emit(room.roomId); } - if (membership === "join" && room.roomId === SdkContextClass.instance.roomViewStore.getRoomId()) { + if (membership === KnownMembership.Join && room.roomId === SdkContextClass.instance.roomViewStore.getRoomId()) { // if the user was looking at the space and then joined: select that space this.setActiveSpace(room.roomId, false); - } else if (membership === "leave" && room.roomId === this.activeSpace) { + } else if (membership === KnownMembership.Leave && room.roomId === this.activeSpace) { // user's active space has gone away, go back to home this.goToFirstSpace(true); } @@ -1000,7 +1016,7 @@ export class SpaceStoreClass extends AsyncStoreWithClient { if ( room.roomId === this.activeSpace && // current space - target?.getMyMembership() !== "join" && // target not joined + target?.getMyMembership() !== KnownMembership.Join && // target not joined ev.getPrevContent().suggested !== ev.getContent().suggested // suggested flag changed ) { this.loadSuggestedRooms(room); @@ -1025,6 +1041,10 @@ export class SpaceStoreClass extends AsyncStoreWithClient { this.onRoomsUpdate(); } break; + case EventType.RoomCreate: + // The room might become a video room. We need to tag it for that videoRooms space. + this.onRoomsUpdate(); + break; } }; diff --git a/linked-dependencies/matrix-react-sdk/src/stores/spaces/index.ts b/linked-dependencies/matrix-react-sdk/src/stores/spaces/index.ts index 7d6a8bb504..c1d9e8160a 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/spaces/index.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/spaces/index.ts @@ -32,6 +32,7 @@ export enum MetaSpace { Favourites = "favourites-space", People = "people-space", Orphans = "orphans-space", + VideoRooms = "video-rooms-space", } export const getMetaSpaceName = (spaceKey: MetaSpace, allRoomsInHome = false): string => { @@ -47,6 +48,8 @@ export const getMetaSpaceName = (spaceKey: MetaSpace, allRoomsInHome = false): s // end TCHAP case MetaSpace.Orphans: return _t("common|orphan_rooms"); + case MetaSpace.VideoRooms: + return _t("voip|metaspace_video_rooms|conference_room_section"); } }; @@ -61,6 +64,7 @@ export function isMetaSpace(spaceKey?: SpaceKey): boolean { spaceKey === MetaSpace.Home || spaceKey === MetaSpace.Favourites || spaceKey === MetaSpace.People || - spaceKey === MetaSpace.Orphans + spaceKey === MetaSpace.Orphans || + spaceKey === MetaSpace.VideoRooms ); } diff --git a/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidget.ts b/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidget.ts index bec4371af2..36ade5d594 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidget.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidget.ts @@ -15,6 +15,7 @@ */ import { Room, MatrixEvent, MatrixEventEvent, MatrixClient, ClientEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { ClientWidgetApi, IModalWidgetOpenRequest, @@ -544,7 +545,7 @@ export class StopGapWidget extends EventEmitter { const evId = ev.getId(); if (evRoomId && evId) { const room = this.client.getRoom(evRoomId); - if (room && room.getMyMembership() === "join" && !isRelationToUnknown) { + if (room && room.getMyMembership() === KnownMembership.Join && !isRelationToUnknown) { this.readUpToMap[evRoomId] = evId; } } diff --git a/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidgetDriver.ts b/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidgetDriver.ts index c2453ebccf..248c520ddd 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidgetDriver.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/widgets/StopGapWidgetDriver.ts @@ -43,6 +43,8 @@ import { Room, Direction, THREAD_RELATION_TYPE, + StateEvents, + TimelineEvents, } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { @@ -139,6 +141,9 @@ export class StopGapWidgetDriver extends WidgetDriver { this.allowedCapabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, "org.matrix.msc3401.call").raw, ); + this.allowedCapabilities.add( + WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomEncryption).raw, + ); this.allowedCapabilities.add( WidgetEventCapability.forStateEvent( EventDirection.Send, @@ -241,6 +246,18 @@ export class StopGapWidgetDriver extends WidgetDriver { return allAllowed; } + public async sendEvent( + eventType: K, + content: StateEvents[K], + stateKey?: string, + targetRoomId?: string, + ): Promise; + public async sendEvent( + eventType: K, + content: TimelineEvents[K], + stateKey: null, + targetRoomId?: string, + ): Promise; public async sendEvent( eventType: string, content: IContent, @@ -255,13 +272,22 @@ export class StopGapWidgetDriver extends WidgetDriver { let r: { event_id: string } | null; if (stateKey !== null) { // state event - r = await client.sendStateEvent(roomId, eventType, content, stateKey); + r = await client.sendStateEvent( + roomId, + eventType as keyof StateEvents, + content as StateEvents[keyof StateEvents], + stateKey, + ); } else if (eventType === EventType.RoomRedaction) { // special case: extract the `redacts` property and call redact r = await client.redactEvent(roomId, content["redacts"]); } else { // message event - r = await client.sendEvent(roomId, eventType, content); + r = await client.sendEvent( + roomId, + eventType as keyof TimelineEvents, + content as TimelineEvents[keyof TimelineEvents], + ); if (eventType === EventType.RoomMessage) { CHAT_EFFECTS.forEach((effect) => { diff --git a/linked-dependencies/matrix-react-sdk/src/stores/widgets/WidgetLayoutStore.ts b/linked-dependencies/matrix-react-sdk/src/stores/widgets/WidgetLayoutStore.ts index c965836c8b..eef5d84d0d 100644 --- a/linked-dependencies/matrix-react-sdk/src/stores/widgets/WidgetLayoutStore.ts +++ b/linked-dependencies/matrix-react-sdk/src/stores/widgets/WidgetLayoutStore.ts @@ -28,55 +28,10 @@ import { ReadyWatchingStore } from "../ReadyWatchingStore"; import { SettingLevel } from "../../settings/SettingLevel"; import { arrayFastClone } from "../../utils/arrays"; import { UPDATE_EVENT } from "../AsyncStore"; +import { Container, IStoredLayout, ILayoutStateEvent, WIDGET_LAYOUT_EVENT_TYPE, IWidgetLayouts } from "./types"; -export const WIDGET_LAYOUT_EVENT_TYPE = "io.element.widgets.layout"; - -export enum Container { - // "Top" is the app drawer, and currently the only sensible value. - Top = "top", - - // "Right" is the right panel, and the default for widgets. Setting - // this as a container on a widget is essentially like saying "no - // changes needed", though this may change in the future. - Right = "right", - - Center = "center", -} - -export interface IStoredLayout { - // Where to store the widget. Required. - container: Container; - - // The index (order) to position the widgets in. Only applies for - // ordered containers (like the top container). Smaller numbers first, - // and conflicts resolved by comparing widget IDs. - index?: number; - - // Percentage (integer) for relative width of the container to consume. - // Clamped to 0-100 and may have minimums imposed upon it. Only applies - // to containers which support inner resizing (currently only the top - // container). - width?: number; - - // Percentage (integer) for relative height of the container. Note that - // this only applies to the top container currently, and that container - // will take the highest value among widgets in the container. Clamped - // to 0-100 and may have minimums imposed on it. - height?: number | null; - - // TODO: [Deferred] Maximizing (fullscreen) widgets by default. -} - -interface IWidgetLayouts { - [widgetId: string]: IStoredLayout; -} - -interface ILayoutStateEvent { - // TODO: [Deferred] Forced layout (fixed with no changes) - - // The widget layouts. - widgets: IWidgetLayouts; -} +export type { IStoredLayout, ILayoutStateEvent }; +export { Container, WIDGET_LAYOUT_EVENT_TYPE }; interface ILayoutSettings extends ILayoutStateEvent { overrides?: string; // event ID for layout state event, if present diff --git a/linked-dependencies/matrix-react-sdk/src/stores/widgets/types.ts b/linked-dependencies/matrix-react-sdk/src/stores/widgets/types.ts new file mode 100644 index 0000000000..36d5d86472 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/stores/widgets/types.ts @@ -0,0 +1,64 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export interface IStoredLayout { + // Where to store the widget. Required. + container: Container; + + // The index (order) to position the widgets in. Only applies for + // ordered containers (like the top container). Smaller numbers first, + // and conflicts resolved by comparing widget IDs. + index?: number; + + // Percentage (integer) for relative width of the container to consume. + // Clamped to 0-100 and may have minimums imposed upon it. Only applies + // to containers which support inner resizing (currently only the top + // container). + width?: number; + + // Percentage (integer) for relative height of the container. Note that + // this only applies to the top container currently, and that container + // will take the highest value among widgets in the container. Clamped + // to 0-100 and may have minimums imposed on it. + height?: number | null; + + // TODO: [Deferred] Maximizing (fullscreen) widgets by default. +} + +export interface IWidgetLayouts { + [widgetId: string]: IStoredLayout; +} + +export interface ILayoutStateEvent { + // TODO: [Deferred] Forced layout (fixed with no changes) + + // The widget layouts. + widgets: IWidgetLayouts; +} + +export const WIDGET_LAYOUT_EVENT_TYPE = "io.element.widgets.layout"; + +export enum Container { + // "Top" is the app drawer, and currently the only sensible value. + Top = "top", + + // "Right" is the right panel, and the default for widgets. Setting + // this as a container on a widget is essentially like saying "no + // changes needed", though this may change in the future. + Right = "right", + + Center = "center", +} diff --git a/linked-dependencies/matrix-react-sdk/src/toasts/SetupEncryptionToast.ts b/linked-dependencies/matrix-react-sdk/src/toasts/SetupEncryptionToast.ts index 6be92b88ba..72b82d208c 100644 --- a/linked-dependencies/matrix-react-sdk/src/toasts/SetupEncryptionToast.ts +++ b/linked-dependencies/matrix-react-sdk/src/toasts/SetupEncryptionToast.ts @@ -21,7 +21,8 @@ import SetupEncryptionDialog from "../components/views/dialogs/security/SetupEnc import { accessSecretStorage } from "../SecurityManager"; import ToastStore from "../stores/ToastStore"; import GenericToast from "../components/views/toasts/GenericToast"; -import SecurityCustomisations from "../customisations/Security"; +import { ModuleRunner } from "../modules/ModuleRunner"; +import { SetupEncryptionStore } from "../stores/SetupEncryptionStore"; import Spinner from "../components/views/elements/Spinner"; const TOAST_KEY = "setupencryption"; @@ -83,7 +84,12 @@ const onReject = (): void => { }; export const showToast = (kind: Kind): void => { - if (SecurityCustomisations.setupEncryptionNeeded?.(kind)) { + if ( + ModuleRunner.instance.extensions.cryptoSetup.setupEncryptionNeeded({ + kind: kind as any, + storeProvider: { getInstance: () => SetupEncryptionStore.sharedInstance() }, + }) + ) { return; } diff --git a/linked-dependencies/matrix-react-sdk/src/utils/DMRoomMap.ts b/linked-dependencies/matrix-react-sdk/src/utils/DMRoomMap.ts index eafbe07d5d..cdabb50ec0 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/DMRoomMap.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/DMRoomMap.ts @@ -16,6 +16,7 @@ limitations under the License. import { uniq } from "lodash"; import { Room, MatrixEvent, EventType, ClientEvent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { Optional } from "matrix-events-sdk"; @@ -172,7 +173,7 @@ export default class DMRoomMap { const joinedRooms = commonRooms .map((r) => this.matrixClient.getRoom(r)) - .filter((r) => r && r.getMyMembership() === "join"); + .filter((r) => r && r.getMyMembership() === KnownMembership.Join); return joinedRooms[0]; } diff --git a/linked-dependencies/matrix-react-sdk/src/utils/DecryptFile.ts b/linked-dependencies/matrix-react-sdk/src/utils/DecryptFile.ts index 9b72c13bd3..c72f57589f 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/DecryptFile.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/DecryptFile.ts @@ -17,9 +17,9 @@ limitations under the License. // Pull in the encryption lib so that we can decrypt attachments. import encrypt from "matrix-encrypt-attachment"; import { parseErrorResponse } from "matrix-js-sdk/src/matrix"; +import { EncryptedFile, MediaEventInfo } from "matrix-js-sdk/src/types"; import { mediaFromContent } from "../customisations/Media"; -import { EncryptedFile, IMediaEventInfo } from "../customisations/models/IMediaEventContent"; import { getBlobSafeMimeType } from "./blobs"; export class DownloadError extends Error { @@ -44,10 +44,10 @@ export class DecryptError extends Error { * This passed to [link]{@link https://github.com/matrix-org/matrix-encrypt-attachment} * as the encryption info object, so will also have the those keys in addition to * the keys below. - * @param {IMediaEventInfo} info The info parameter taken from the matrix event. + * @param {MediaEventInfo} info The info parameter taken from the matrix event. * @returns {Promise} Resolves to a Blob of the file. */ -export async function decryptFile(file?: EncryptedFile, info?: IMediaEventInfo): Promise { +export async function decryptFile(file?: EncryptedFile, info?: MediaEventInfo): Promise { // throws if file is falsy const media = mediaFromContent({ file }); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/FileUtils.ts b/linked-dependencies/matrix-react-sdk/src/utils/FileUtils.ts index 8423a54ce4..75511756f5 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/FileUtils.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/FileUtils.ts @@ -25,22 +25,22 @@ import { FileSizeReturnArray, FileSizeReturnObject, } from "filesize"; +import { MediaEventContent } from "matrix-js-sdk/src/types"; -import { IMediaEventContent } from "../customisations/models/IMediaEventContent"; import { _t } from "../languageHandler"; /** * Extracts a human-readable label for the file attachment to use as * link text. * - * @param {IMediaEventContent} content The "content" key of the matrix event. + * @param {MediaEventContent} content The "content" key of the matrix event. * @param {string} fallbackText The fallback text * @param {boolean} withSize Whether to include size information. Default true. * @param {boolean} shortened Ensure the extension of the file name is visible. Default false. * @return {string} the human-readable link text for the attachment. */ export function presentableTextForFile( - content: IMediaEventContent, + content: MediaEventContent, fallbackText = _t("common|attachment"), withSize = true, shortened = false, diff --git a/linked-dependencies/matrix-react-sdk/src/utils/MediaEventHelper.ts b/linked-dependencies/matrix-react-sdk/src/utils/MediaEventHelper.ts index ea14b175ae..b9ceae9db5 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/MediaEventHelper.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/MediaEventHelper.ts @@ -15,12 +15,12 @@ limitations under the License. */ import { MatrixEvent, EventType, MsgType } from "matrix-js-sdk/src/matrix"; +import { FileContent, ImageContent, MediaEventContent } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { LazyValue } from "./LazyValue"; import { Media, mediaFromContent } from "../customisations/Media"; import { decryptFile } from "./DecryptFile"; -import { FileContent, ImageContent, IMediaEventContent } from "../customisations/models/IMediaEventContent"; import { IDestroyable } from "./IDestroyable"; // TODO: We should consider caching the blobs. https://github.com/vector-im/element-web/issues/17192 @@ -48,7 +48,7 @@ export class MediaEventHelper implements IDestroyable { public get fileName(): string { return ( this.event.getContent().filename || - this.event.getContent().body || + this.event.getContent().body || "download" ); } @@ -81,7 +81,7 @@ export class MediaEventHelper implements IDestroyable { private fetchSource = (): Promise => { if (this.media.isEncrypted) { - const content = this.event.getContent(); + const content = this.event.getContent(); return decryptFile(content.file!, content.info); } return this.media.downloadSource().then((r) => r.blob()); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/MultiInviter.ts b/linked-dependencies/matrix-react-sdk/src/utils/MultiInviter.ts index 0983dc180c..5c2b076f24 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/MultiInviter.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/MultiInviter.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { MatrixError, MatrixClient, EventType, HistoryVisibility } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { defer, IDeferred } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; @@ -159,17 +160,17 @@ export default class MultiInviter { if (!room) throw new Error("Room not found"); const member = room.getMember(addr); - if (member?.membership === "join") { + if (member?.membership === KnownMembership.Join) { throw new MatrixError({ errcode: USER_ALREADY_JOINED, error: "Member already joined", }); - } else if (member?.membership === "invite") { + } else if (member?.membership === KnownMembership.Invite) { throw new MatrixError({ errcode: USER_ALREADY_INVITED, error: "Member already invited", }); - } else if (member?.membership === "ban") { + } else if (member?.membership === KnownMembership.Ban) { let proceed = false; // Check if we can unban the invitee. // See https://spec.matrix.org/v1.7/rooms/v10/#authorization-rules, particularly 4.5.3 and 4.5.4. diff --git a/linked-dependencies/matrix-react-sdk/src/utils/RoomUpgrade.ts b/linked-dependencies/matrix-react-sdk/src/utils/RoomUpgrade.ts index 88fc904541..ea9f773e34 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/RoomUpgrade.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/RoomUpgrade.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { Room, EventType, ClientEvent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { inviteUsersToRoom } from "../RoomInvite"; @@ -67,7 +68,10 @@ export async function upgradeRoom( let toInvite: string[] = []; if (inviteUsers) { - toInvite = [...room.getMembersWithMembership("join"), ...room.getMembersWithMembership("invite")] + toInvite = [ + ...room.getMembersWithMembership(KnownMembership.Join), + ...room.getMembersWithMembership(KnownMembership.Invite), + ] .map((m) => m.userId) .filter((m) => m !== cli.getUserId()); } @@ -131,7 +135,7 @@ export async function upgradeRoom( EventType.SpaceChild, { ...(currentEv?.getContent() || {}), // copy existing attributes like suggested - via: [cli.getDomain()], + via: [cli.getDomain()!], }, newRoomId, ); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/SortMembers.ts b/linked-dependencies/matrix-react-sdk/src/utils/SortMembers.ts index 534fe6a82e..413f7971b2 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/SortMembers.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/SortMembers.ts @@ -16,6 +16,7 @@ limitations under the License. import { groupBy, mapValues, maxBy, minBy, sumBy, takeRight } from "lodash"; import { MatrixClient, Room, RoomMember } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { Member } from "./direct-messages"; import DMRoomMap from "./DMRoomMap"; @@ -52,7 +53,7 @@ function joinedRooms(cli: MatrixClient): Room[] { return ( cli .getRooms() - .filter((r) => r.getMyMembership() === "join") + .filter((r) => r.getMyMembership() === KnownMembership.Join) // Skip low priority rooms and DMs .filter((r) => !DMRoomMap.shared().getUserIdForRoomId(r.roomId)) .filter((r) => !Object.keys(r.tags).includes("m.lowpriority")) diff --git a/linked-dependencies/matrix-react-sdk/src/utils/WidgetUtils.ts b/linked-dependencies/matrix-react-sdk/src/utils/WidgetUtils.ts index 11918d1458..3272a14e4e 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/WidgetUtils.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/WidgetUtils.ts @@ -18,6 +18,7 @@ limitations under the License. import { base32 } from "rfc4648"; import { IWidget, IWidgetData } from "matrix-widget-api"; import { Room, ClientEvent, MatrixClient, RoomStateEvent, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import { CallType } from "matrix-js-sdk/src/webrtc/call"; import { randomString, randomLowercaseString, randomUppercaseString } from "matrix-js-sdk/src/randomstring"; @@ -83,7 +84,7 @@ export default class WidgetUtils { return false; } - if (room.getMyMembership() !== "join") { + if (room.getMyMembership() !== KnownMembership.Join) { logger.warn(`User ${me} is not in room ${roomId}`); return false; } @@ -520,7 +521,7 @@ export default class WidgetUtils { // safe to send. // We'll end up using a local render URL when we see a Jitsi widget anyways, so this is // really just for backwards compatibility and to appease the spec. - baseUrl = "https://app.element.io/"; + baseUrl = PlatformPeg.get()!.baseUrl; } const url = new URL("jitsi.html#" + queryString, baseUrl); // this strips hash fragment from baseUrl return url.href; diff --git a/linked-dependencies/matrix-react-sdk/src/utils/colour.ts b/linked-dependencies/matrix-react-sdk/src/utils/colour.ts index 518b11f835..8262718a39 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/colour.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/colour.ts @@ -27,13 +27,13 @@ export function textToHtmlRainbow(str: string): string { const [a, b] = generateAB(i * frequency, 1); const [red, green, blue] = labToRGB(75, a, b); return ( - '' + c + - "" + "" ); }) .join(""); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/createVoiceMessageContent.ts b/linked-dependencies/matrix-react-sdk/src/utils/createVoiceMessageContent.ts index 28ba5befac..06bd335389 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/createVoiceMessageContent.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/createVoiceMessageContent.ts @@ -14,7 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { IContent, IEncryptedFile, MsgType } from "matrix-js-sdk/src/matrix"; +import { IEncryptedFile, MsgType } from "matrix-js-sdk/src/matrix"; +import { RoomMessageEventContent } from "matrix-js-sdk/src/types"; /** * @param {string} mxc MXC URL of the file @@ -31,7 +32,7 @@ export const createVoiceMessageContent = ( size: number, file?: IEncryptedFile, waveform?: number[], -): IContent => { +): RoomMessageEventContent => { return { "body": "Voice message", //"msgtype": "org.matrix.msc2516.voice", diff --git a/linked-dependencies/matrix-react-sdk/src/utils/device/dehydration.ts b/linked-dependencies/matrix-react-sdk/src/utils/device/dehydration.ts new file mode 100644 index 0000000000..83297f42a4 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/utils/device/dehydration.ts @@ -0,0 +1,57 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { logger } from "matrix-js-sdk/src/logger"; +import { CryptoApi } from "matrix-js-sdk/src/matrix"; + +import { MatrixClientPeg } from "../../MatrixClientPeg"; + +/** + * Check if device dehydration is enabled. + * + * Note that this doesn't necessarily mean that device dehydration has been initialised + * (yet) on this client; rather, it means that the server supports it, the crypto backend + * supports it, and the application configuration suggests that it *should* be + * initialised on this device. + * + * Dehydration can currently only be enabled by setting a flag in the .well-known file. + */ +async function deviceDehydrationEnabled(crypto: CryptoApi | undefined): Promise { + if (!crypto) { + return false; + } + if (!(await crypto.isDehydrationSupported())) { + return false; + } + const wellknown = await MatrixClientPeg.safeGet().waitForClientWellKnown(); + return !!wellknown?.["org.matrix.msc3814"]; +} + +/** + * If dehydration is enabled (i.e., it is supported by the server and enabled in + * the configuration), rehydrate a device (if available) and create + * a new dehydrated device. + * + * @param createNewKey: force a new dehydration key to be created, even if one + * already exists. This is used when we reset secret storage. + */ +export async function initialiseDehydration(createNewKey: boolean = false): Promise { + const crypto = MatrixClientPeg.safeGet().getCrypto(); + if (await deviceDehydrationEnabled(crypto)) { + logger.log("Device dehydration enabled"); + await crypto!.startDehydration(createNewKey); + } +} diff --git a/linked-dependencies/matrix-react-sdk/src/utils/dm/createDmLocalRoom.ts b/linked-dependencies/matrix-react-sdk/src/utils/dm/createDmLocalRoom.ts index ac14834303..5ffa491bcf 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/dm/createDmLocalRoom.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/dm/createDmLocalRoom.ts @@ -16,6 +16,7 @@ limitations under the License. import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib"; import { EventType, KNOWN_SAFE_ROOM_VERSION, MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../../src/models/LocalRoom"; import { determineCreateRoomEncryptionOption, Member } from "../../../src/utils/direct-messages"; @@ -76,7 +77,7 @@ export async function createDmLocalRoom(client: MatrixClient, targets: Member[]) type: EventType.RoomMember, content: { displayname: userId, - membership: "join", + membership: KnownMembership.Join, }, state_key: userId, user_id: userId, @@ -93,7 +94,7 @@ export async function createDmLocalRoom(client: MatrixClient, targets: Member[]) content: { displayname: target.name, avatar_url: target.getMxcAvatarUrl() ?? undefined, - membership: "invite", + membership: KnownMembership.Invite, isDirect: true, }, state_key: target.userId, @@ -108,7 +109,7 @@ export async function createDmLocalRoom(client: MatrixClient, targets: Member[]) content: { displayname: target.name, avatar_url: target.getMxcAvatarUrl() ?? undefined, - membership: "join", + membership: KnownMembership.Join, }, state_key: target.userId, sender: target.userId, @@ -118,7 +119,7 @@ export async function createDmLocalRoom(client: MatrixClient, targets: Member[]) }); localRoom.targets = targets; - localRoom.updateMyMembership("join"); + localRoom.updateMyMembership(KnownMembership.Join); localRoom.addLiveEvents(events); localRoom.currentState.setStateEvents(events); localRoom.name = localRoom.getDefaultRoomName(client.getUserId()!); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/dm/findDMForUser.ts b/linked-dependencies/matrix-react-sdk/src/utils/dm/findDMForUser.ts index 92575d41be..55b5f0093f 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/dm/findDMForUser.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/dm/findDMForUser.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import DMRoomMap from "../DMRoomMap"; import { isLocalRoom } from "../localRoom/isLocalRoom"; @@ -42,7 +43,7 @@ function extractSuitableRoom(rooms: Room[], userId: string, findRoomWithThirdpar // a DM is a room of two people that contains those two people exactly. This does mean // that bots, assistants, etc will ruin a room's DM-ness, though this is a problem for // canonical DMs to solve. - if (r && r.getMyMembership() === "join") { + if (r && r.getMyMembership() === KnownMembership.Join) { if (isLocalRoom(r)) return false; const functionalUsers = getFunctionalMembers(r); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/Exporter.ts b/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/Exporter.ts index 9a4f3d4208..57b19e618b 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/Exporter.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/Exporter.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { Direction, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; +import { MediaEventContent } from "matrix-js-sdk/src/types"; import { saveAs } from "file-saver"; import { logger } from "matrix-js-sdk/src/logger"; import sanitizeFilename from "sanitize-filename"; @@ -24,7 +25,6 @@ import { decryptFile } from "../DecryptFile"; import { mediaFromContent } from "../../customisations/Media"; import { formatFullDateNoDay, formatFullDateNoDayISO } from "../../DateUtils"; import { isVoiceMessage } from "../EventUtils"; -import { IMediaEventContent } from "../../customisations/models/IMediaEventContent"; import { _t } from "../../languageHandler"; import SdkConfig from "../../SdkConfig"; @@ -225,7 +225,7 @@ export default abstract class Exporter { let blob: Blob | undefined = undefined; try { const isEncrypted = event.isEncrypted(); - const content = event.getContent(); + const content = event.getContent(); const shouldDecrypt = isEncrypted && content.hasOwnProperty("file") && event.getType() !== "m.sticker"; if (shouldDecrypt) { blob = await decryptFile(content.file); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/JSONExport.ts b/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/JSONExport.ts index d0470576d2..8805f95d65 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/JSONExport.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/exportUtils/JSONExport.ts @@ -74,9 +74,7 @@ export default class JSONExporter extends Exporter { logger.log("Error fetching file: " + err); } } - const jsonEvent: any = mxEv.toJSON(); - const clearEvent = mxEv.isEncrypted() ? jsonEvent.decrypted : jsonEvent; - return clearEvent; + return mxEv.getEffectiveEvent(); } protected async createOutput(events: MatrixEvent[]): Promise { diff --git a/linked-dependencies/matrix-react-sdk/src/utils/image-media.ts b/linked-dependencies/matrix-react-sdk/src/utils/image-media.ts index fa252ee1ae..096fddbcbe 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/image-media.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/image-media.ts @@ -14,8 +14,9 @@ See the License for the specific language governing permissions and limitations under the License. */ +import { EncryptedFile } from "matrix-js-sdk/src/types"; + import { BlurhashEncoder } from "../BlurhashEncoder"; -import { EncryptedFile } from "../customisations/models/IMediaEventContent"; type ThumbnailableElement = HTMLImageElement | HTMLVideoElement; diff --git a/linked-dependencies/matrix-react-sdk/src/utils/location/index.ts b/linked-dependencies/matrix-react-sdk/src/utils/location/index.ts index 035fe52694..8a107451c6 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/location/index.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/location/index.ts @@ -18,6 +18,6 @@ export * from "./findMapStyleUrl"; export * from "./isSelfLocation"; export * from "./locationEventGeoUri"; export * from "./LocationShareErrors"; -export * from "./map"; +export * from "./links"; export * from "./parseGeoUri"; export * from "./positionFailureMessage"; diff --git a/linked-dependencies/matrix-react-sdk/src/utils/location/links.ts b/linked-dependencies/matrix-react-sdk/src/utils/location/links.ts new file mode 100644 index 0000000000..cafae1ae1a --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/src/utils/location/links.ts @@ -0,0 +1,47 @@ +/* +Copyright 2022 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { MatrixEvent, M_LOCATION } from "matrix-js-sdk/src/matrix"; + +import { parseGeoUri } from "./parseGeoUri"; + +export const makeMapSiteLink = (coords: GeolocationCoordinates): string => { + return ( + "https://www.openstreetmap.org/" + + `?mlat=${coords.latitude}` + + `&mlon=${coords.longitude}` + + `#map=16/${coords.latitude}/${coords.longitude}` + ); +}; + +export const createMapSiteLinkFromEvent = (event: MatrixEvent): string | null => { + const content = event.getContent(); + const mLocation = content[M_LOCATION.name]; + if (mLocation !== undefined) { + const uri = mLocation["uri"]; + if (uri !== undefined) { + const geoCoords = parseGeoUri(uri); + return geoCoords ? makeMapSiteLink(geoCoords) : null; + } + } else { + const geoUri = content["geo_uri"]; + if (geoUri) { + const geoCoords = parseGeoUri(geoUri); + return geoCoords ? makeMapSiteLink(geoCoords) : null; + } + } + return null; +}; diff --git a/linked-dependencies/matrix-react-sdk/src/utils/location/map.ts b/linked-dependencies/matrix-react-sdk/src/utils/location/map.ts index 78f17c9868..707d703bea 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/location/map.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/location/map.ts @@ -15,11 +15,10 @@ limitations under the License. */ import * as maplibregl from "maplibre-gl"; -import { MatrixClient, MatrixEvent, M_LOCATION } from "matrix-js-sdk/src/matrix"; +import { MatrixClient } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../languageHandler"; -import { parseGeoUri } from "./parseGeoUri"; import { findMapStyleUrl } from "./findMapStyleUrl"; import { LocationShareError } from "./LocationShareErrors"; @@ -75,31 +74,3 @@ export const createMarker = (coords: GeolocationCoordinates, element: HTMLElemen }).setLngLat({ lon: coords.longitude, lat: coords.latitude }); return marker; }; - -export const makeMapSiteLink = (coords: GeolocationCoordinates): string => { - return ( - "https://www.openstreetmap.org/" + - `?mlat=${coords.latitude}` + - `&mlon=${coords.longitude}` + - `#map=16/${coords.latitude}/${coords.longitude}` - ); -}; - -export const createMapSiteLinkFromEvent = (event: MatrixEvent): string | null => { - const content = event.getContent(); - const mLocation = content[M_LOCATION.name]; - if (mLocation !== undefined) { - const uri = mLocation["uri"]; - if (uri !== undefined) { - const geoCoords = parseGeoUri(uri); - return geoCoords ? makeMapSiteLink(geoCoords) : null; - } - } else { - const geoUri = content["geo_uri"]; - if (geoUri) { - const geoCoords = parseGeoUri(geoUri); - return geoCoords ? makeMapSiteLink(geoCoords) : null; - } - } - return null; -}; diff --git a/linked-dependencies/matrix-react-sdk/src/utils/location/useMap.ts b/linked-dependencies/matrix-react-sdk/src/utils/location/useMap.ts index f6fc0aa62d..98ec53ffde 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/location/useMap.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/location/useMap.ts @@ -15,8 +15,8 @@ limitations under the License. */ import { useEffect, useState } from "react"; -import { Map as MapLibreMap } from "maplibre-gl"; +import type { Map as MapLibreMap } from "maplibre-gl"; import { createMap } from "./map"; import { useMatrixClientContext } from "../../contexts/MatrixClientContext"; diff --git a/linked-dependencies/matrix-react-sdk/src/utils/membership.ts b/linked-dependencies/matrix-react-sdk/src/utils/membership.ts index df012e442b..2ff99fa360 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/membership.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/membership.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { Room, RoomMember, RoomState, RoomStateEvent, MatrixEvent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { KnownMembership, Membership } from "matrix-js-sdk/src/types"; import { MatrixClientPeg } from "../MatrixClientPeg"; import SettingsStore from "../settings/SettingsStore"; @@ -65,10 +66,13 @@ export function splitRoomsByMembership(rooms: Room[]): MembershipSplit { return split; } -export function getEffectiveMembership(membership: string): EffectiveMembership { - if (membership === "invite") { +export function getEffectiveMembership(membership: Membership): EffectiveMembership { + if (membership === KnownMembership.Invite) { return EffectiveMembership.Invite; - } else if (membership === "join" || (SettingsStore.getValue("feature_ask_to_join") && membership === "knock")) { + } else if ( + membership === KnownMembership.Join || + (SettingsStore.getValue("feature_ask_to_join") && membership === KnownMembership.Knock) + ) { return EffectiveMembership.Join; } else { // Probably a leave, kick, or ban @@ -81,7 +85,7 @@ export function isKnockDenied(room: Room): boolean | undefined { const member = memberId ? room.getMember(memberId) : null; const previousMembership = member?.events.member?.getPrevContent().membership; - return member?.isKicked() && previousMembership === "knock"; + return member?.isKicked() && previousMembership === KnownMembership.Knock; } export function getEffectiveMembershipTag(room: Room, membership?: string): EffectiveMembership { @@ -90,7 +94,7 @@ export function getEffectiveMembershipTag(room: Room, membership?: string): Effe : getEffectiveMembership(membership ?? room.getMyMembership()); } -export function isJoinedOrNearlyJoined(membership: string): boolean { +export function isJoinedOrNearlyJoined(membership: Membership): boolean { const effective = getEffectiveMembership(membership); return effective === EffectiveMembership.Join || effective === EffectiveMembership.Invite; } diff --git a/linked-dependencies/matrix-react-sdk/src/utils/notifications.ts b/linked-dependencies/matrix-react-sdk/src/utils/notifications.ts index 1dd2dd7788..46e61fc984 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/notifications.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/notifications.ts @@ -21,6 +21,7 @@ import { Room, LocalNotificationSettings, ReceiptType, + IMarkedUnreadEvent, } from "matrix-js-sdk/src/matrix"; import { IndicatorIcon } from "@vector-im/compound-web"; @@ -28,6 +29,19 @@ import SettingsStore from "../settings/SettingsStore"; import { NotificationLevel } from "../stores/notifications/NotificationLevel"; import { doesRoomHaveUnreadMessages } from "../Unread"; +// MSC2867 is not yet spec at time of writing. We read from both stable +// and unstable prefixes and accept the risk that the format may change, +// since the stable prefix is not actually defined yet. + +/** + * Unstable identifier for the marked_unread event, per MSC2867 + */ +export const MARKED_UNREAD_TYPE_UNSTABLE = "com.famedly.marked_unread"; +/** + * Stable identifier for the marked_unread event + */ +export const MARKED_UNREAD_TYPE_STABLE = "m.marked_unread"; + export const deviceNotificationSettingsKeys = [ "notificationsEnabled", "notificationBodyEnabled", @@ -74,6 +88,8 @@ export function localNotificationsAreSilenced(cli: MatrixClient): boolean { export async function clearRoomNotification(room: Room, client: MatrixClient): Promise<{} | undefined> { const lastEvent = room.getLastLiveEvent(); + await setMarkedUnreadState(room, client, false); + try { if (lastEvent) { const receiptType = SettingsStore.getValue("sendReadReceipts", room.roomId) @@ -117,6 +133,39 @@ export function clearAllNotifications(client: MatrixClient): Promise()?.unread; + const currentStateUnstable = room + .getAccountData(MARKED_UNREAD_TYPE_UNSTABLE) + ?.getContent()?.unread; + return currentStateStable ?? currentStateUnstable; +} + +/** + * Sets the marked_unread state of the given room. This sets some room account data that indicates to + * clients that the user considers this room to be 'unread', but without any actual notifications. + * + * @param room The room to set + * @param client MatrixClient object to use + * @param unread The new marked_unread state of the room + */ +export async function setMarkedUnreadState(room: Room, client: MatrixClient, unread: boolean): Promise { + // if there's no event, treat this as false as we don't need to send the flag to clear it if the event isn't there + const currentState = getMarkedUnreadState(room); + + if (Boolean(currentState) !== unread) { + // Assuming MSC2867 passes FCP with no changes, we should update to start writing + // the flag to the stable prefix (or both) and then ultimately use only the + // stable prefix. + await client.setRoomAccountData(room.roomId, MARKED_UNREAD_TYPE_UNSTABLE, { unread }); + } +} + /** * A helper to transform a notification color to the what the Compound Icon Button * expects diff --git a/linked-dependencies/matrix-react-sdk/src/utils/permalinks/Permalinks.ts b/linked-dependencies/matrix-react-sdk/src/utils/permalinks/Permalinks.ts index 9af7476a39..537494b26b 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/permalinks/Permalinks.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/permalinks/Permalinks.ts @@ -17,6 +17,7 @@ limitations under the License. import isIp from "is-ip"; import * as utils from "matrix-js-sdk/src/utils"; import { Room, MatrixClient, RoomStateEvent, EventType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { logger } from "matrix-js-sdk/src/logger"; import MatrixToPermalinkConstructor, { @@ -178,7 +179,7 @@ export class RoomPermalinkCreator { const entries = Object.entries(users); const allowedEntries = entries.filter(([userId]) => { const member = this.room?.getMember(userId); - if (!member || member.membership !== "join") { + if (!member || member.membership !== KnownMembership.Join) { return false; } const serverName = getServerName(userId); diff --git a/linked-dependencies/matrix-react-sdk/src/utils/pillify.tsx b/linked-dependencies/matrix-react-sdk/src/utils/pillify.tsx index f46892949e..22fcaec99a 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/pillify.tsx +++ b/linked-dependencies/matrix-react-sdk/src/utils/pillify.tsx @@ -17,11 +17,11 @@ limitations under the License. import React from "react"; import ReactDOM from "react-dom"; import { PushProcessor } from "matrix-js-sdk/src/pushprocessor"; -import { MatrixEvent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { MatrixClient, MatrixEvent, RuleId } from "matrix-js-sdk/src/matrix"; import { TooltipProvider } from "@vector-im/compound-web"; import SettingsStore from "../settings/SettingsStore"; -import { Pill, PillType, pillRoomNotifLen, pillRoomNotifPos } from "../components/views/elements/Pill"; +import { Pill, pillRoomNotifLen, pillRoomNotifPos, PillType } from "../components/views/elements/Pill"; import { parsePermalink } from "./permalinks/Permalinks"; import { PermalinkParts } from "./permalinks/PermalinkConstructor"; @@ -127,7 +127,9 @@ export function pillifyLinks( if (roomNotifTextNodes.length > 0) { const pushProcessor = new PushProcessor(matrixClient); - const atRoomRule = pushProcessor.getPushRuleById(".m.rule.roomnotif"); + const atRoomRule = pushProcessor.getPushRuleById( + mxEvent.getContent()["m.mentions"] !== undefined ? RuleId.IsRoomMention : RuleId.AtRoomNotification, + ); if (atRoomRule && pushProcessor.ruleMatchesEvent(atRoomRule, mxEvent)) { // Now replace all those nodes with Pills for (const roomNotifTextNode of roomNotifTextNodes) { diff --git a/linked-dependencies/matrix-react-sdk/src/utils/room/canInviteTo.ts b/linked-dependencies/matrix-react-sdk/src/utils/room/canInviteTo.ts index 55265e6cc8..bd306d930e 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/room/canInviteTo.ts +++ b/linked-dependencies/matrix-react-sdk/src/utils/room/canInviteTo.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { JoinRule, Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { shouldShowComponent } from "../../customisations/helpers/UIComponents"; import { UIComponent } from "../../settings/UIFeature"; @@ -29,5 +30,5 @@ export function canInviteTo(room: Room): boolean { const canInvite = !!room.canInvite(client.getSafeUserId()) || !!(room.isSpaceRoom() && room.getJoinRule() === JoinRule.Public); - return canInvite && room.getMyMembership() === "join" && shouldShowComponent(UIComponent.InviteUsers); + return canInvite && room.getMyMembership() === KnownMembership.Join && shouldShowComponent(UIComponent.InviteUsers); } diff --git a/linked-dependencies/matrix-react-sdk/src/utils/space.tsx b/linked-dependencies/matrix-react-sdk/src/utils/space.tsx index d6cfc5a4ff..4222ab14f3 100644 --- a/linked-dependencies/matrix-react-sdk/src/utils/space.tsx +++ b/linked-dependencies/matrix-react-sdk/src/utils/space.tsx @@ -16,6 +16,7 @@ limitations under the License. import React from "react"; import { Room, ICreateRoomStateEvent, RoomType, EventType, JoinRule } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { calculateRoomVia } from "./permalinks/Permalinks"; import Modal from "../Modal"; @@ -40,7 +41,7 @@ import { SdkContextClass } from "../contexts/SDKContext"; export const shouldShowSpaceSettings = (space: Room): boolean => { const userId = space.client.getUserId()!; return ( - space.getMyMembership() === "join" && + space.getMyMembership() === KnownMembership.Join && (space.currentState.maySendStateEvent(EventType.RoomAvatar, userId) || space.currentState.maySendStateEvent(EventType.RoomName, userId) || space.currentState.maySendStateEvent(EventType.RoomTopic, userId) || @@ -85,7 +86,7 @@ export const showCreateNewRoom = async (space: Room, type?: RoomType): Promise - ((space?.getMyMembership() === "join" && space.canInvite(space.client.getUserId()!)) || + ((space?.getMyMembership() === KnownMembership.Join && space.canInvite(space.client.getUserId()!)) || space.getJoinRule() === JoinRule.Public) && shouldShowComponent(UIComponent.InviteUsers); diff --git a/linked-dependencies/matrix-react-sdk/src/verification.ts b/linked-dependencies/matrix-react-sdk/src/verification.ts index 3b1938c5ca..64a9cf2618 100644 --- a/linked-dependencies/matrix-react-sdk/src/verification.ts +++ b/linked-dependencies/matrix-react-sdk/src/verification.ts @@ -15,7 +15,7 @@ limitations under the License. */ import { User, MatrixClient, RoomMember } from "matrix-js-sdk/src/matrix"; -import { verificationMethods as VerificationMethods } from "matrix-js-sdk/src/crypto"; +import { VerificationMethod } from "matrix-js-sdk/src/types"; import { CrossSigningKey, VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import dis from "./dispatcher/dispatcher"; @@ -61,7 +61,7 @@ export async function verifyDevice(matrixClient: MatrixClient, user: User, devic const verificationRequestPromise = matrixClient.legacyDeviceVerification( user.userId, device.deviceId, - VerificationMethods.SAS, + VerificationMethod.Sas, ); setRightPanel({ member: user, verificationRequestPromise }); } else if (action === "legacy") { diff --git a/linked-dependencies/matrix-react-sdk/src/voice-broadcast/models/VoiceBroadcastRecording.ts b/linked-dependencies/matrix-react-sdk/src/voice-broadcast/models/VoiceBroadcastRecording.ts index 81e07646a9..c36e3f75b3 100644 --- a/linked-dependencies/matrix-react-sdk/src/voice-broadcast/models/VoiceBroadcastRecording.ts +++ b/linked-dependencies/matrix-react-sdk/src/voice-broadcast/models/VoiceBroadcastRecording.ts @@ -26,6 +26,7 @@ import { RelationType, TypedEventEmitter, } from "matrix-js-sdk/src/matrix"; +import { AudioContent, EncryptedFile } from "matrix-js-sdk/src/types"; import { ChunkRecordedPayload, @@ -38,7 +39,6 @@ import { VoiceBroadcastRecorderEvent, } from ".."; import { uploadFile } from "../../ContentMessages"; -import { EncryptedFile } from "../../customisations/models/IMediaEventContent"; import { createVoiceMessageContent } from "../../utils/createVoiceMessageContent"; import { IDestroyable } from "../../utils/IDestroyable"; import dis from "../../dispatcher/dispatcher"; @@ -387,7 +387,7 @@ export class VoiceBroadcastRecording rel_type: RelationType.Reference, event_id: this.infoEventId, }; - content["io.element.voice_broadcast_chunk"] = { + (content)["io.element.voice_broadcast_chunk"] = { sequence, }; diff --git a/linked-dependencies/matrix-react-sdk/test/ContentMessages-test.ts b/linked-dependencies/matrix-react-sdk/test/ContentMessages-test.ts index a54ad29ab7..231ddc1b20 100644 --- a/linked-dependencies/matrix-react-sdk/test/ContentMessages-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/ContentMessages-test.ts @@ -15,7 +15,8 @@ limitations under the License. */ import { mocked } from "jest-mock"; -import { IImageInfo, ISendEventResponse, MatrixClient, RelationType, UploadResponse } from "matrix-js-sdk/src/matrix"; +import { ISendEventResponse, MatrixClient, RelationType, UploadResponse } from "matrix-js-sdk/src/matrix"; +import { ImageInfo } from "matrix-js-sdk/src/types"; import { defer } from "matrix-js-sdk/src/utils"; import encrypt, { IEncryptedFile } from "matrix-encrypt-attachment"; @@ -43,7 +44,7 @@ const createElement = document.createElement.bind(document); describe("ContentMessages", () => { const stickerUrl = "https://example.com/sticker"; const roomId = "!room:example.com"; - const imageInfo = {} as unknown as IImageInfo; + const imageInfo = {} as unknown as ImageInfo; const text = "test sticker"; let client: MatrixClient; let contentMessages: ContentMessages; diff --git a/linked-dependencies/matrix-react-sdk/test/DecryptionFailureTracker-test.js b/linked-dependencies/matrix-react-sdk/test/DecryptionFailureTracker-test.ts similarity index 61% rename from linked-dependencies/matrix-react-sdk/test/DecryptionFailureTracker-test.js rename to linked-dependencies/matrix-react-sdk/test/DecryptionFailureTracker-test.ts index 63b0489ee4..553d4f4d74 100644 --- a/linked-dependencies/matrix-react-sdk/test/DecryptionFailureTracker-test.js +++ b/linked-dependencies/matrix-react-sdk/test/DecryptionFailureTracker-test.ts @@ -14,36 +14,38 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { decryptExistingEvent, mkDecryptionFailureMatrixEvent } from "matrix-js-sdk/src/testing"; +import { DecryptionFailureCode } from "matrix-js-sdk/src/crypto-api"; import { DecryptionFailureTracker } from "../src/DecryptionFailureTracker"; class MockDecryptionError extends Error { - constructor(code) { + public readonly code: string; + + constructor(code?: string) { super(); this.code = code || "MOCK_DECRYPTION_ERROR"; } } -function createFailedDecryptionEvent() { - const event = new MatrixEvent({ - event_id: "event-id-" + Math.random().toString(16).slice(2), - content: { - algorithm: "m.megolm.v1.aes-sha2", - }, +async function createFailedDecryptionEvent() { + return await mkDecryptionFailureMatrixEvent({ + roomId: "!room:id", + sender: "@alice:example.com", + code: DecryptionFailureCode.UNKNOWN_ERROR, + msg: ":(", }); - event.setClearData(event.badEncryptedMessage(":(")); - return event; } describe("DecryptionFailureTracker", function () { - it("tracks a failed decryption for a visible event", function () { - const failedDecryptionEvent = createFailedDecryptionEvent(); + it("tracks a failed decryption for a visible event", async function () { + const failedDecryptionEvent = await createFailedDecryptionEvent(); let count = 0; + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => (count += total), + (total: number) => (count += total), () => "UnknownError", ); @@ -58,16 +60,18 @@ describe("DecryptionFailureTracker", function () { // Immediately track the newest failures tracker.trackFailures(); - expect(count).not.toBe(0, "should track a failure for an event that failed decryption"); + // should track a failure for an event that failed decryption + expect(count).not.toBe(0); }); - it("tracks a failed decryption with expected raw error for a visible event", function () { - const failedDecryptionEvent = createFailedDecryptionEvent(); + it("tracks a failed decryption with expected raw error for a visible event", async function () { + const failedDecryptionEvent = await createFailedDecryptionEvent(); let count = 0; let reportedRawCode = ""; + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total, errcode, rawCode) => { + (total: number, _errCode: string, rawCode: string) => { count += total; reportedRawCode = rawCode; }, @@ -85,16 +89,20 @@ describe("DecryptionFailureTracker", function () { // Immediately track the newest failures tracker.trackFailures(); - expect(count).not.toBe(0, "should track a failure for an event that failed decryption"); - expect(reportedRawCode).toBe("INBOUND_SESSION_MISMATCH_ROOM_ID", "Should add the rawCode to the event context"); + // should track a failure for an event that failed decryption + expect(count).not.toBe(0); + + // Should add the rawCode to the event context + expect(reportedRawCode).toBe("INBOUND_SESSION_MISMATCH_ROOM_ID"); }); - it("tracks a failed decryption for an event that becomes visible later", function () { - const failedDecryptionEvent = createFailedDecryptionEvent(); + it("tracks a failed decryption for an event that becomes visible later", async function () { + const failedDecryptionEvent = await createFailedDecryptionEvent(); let count = 0; + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => (count += total), + (total: number) => (count += total), () => "UnknownError", ); @@ -109,15 +117,17 @@ describe("DecryptionFailureTracker", function () { // Immediately track the newest failures tracker.trackFailures(); - expect(count).not.toBe(0, "should track a failure for an event that failed decryption"); + // should track a failure for an event that failed decryption + expect(count).not.toBe(0); }); - it("does not track a failed decryption for an event that never becomes visible", function () { - const failedDecryptionEvent = createFailedDecryptionEvent(); + it("does not track a failed decryption for an event that never becomes visible", async function () { + const failedDecryptionEvent = await createFailedDecryptionEvent(); let count = 0; + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => (count += total), + (total: number) => (count += total), () => "UnknownError", ); @@ -130,14 +140,17 @@ describe("DecryptionFailureTracker", function () { // Immediately track the newest failures tracker.trackFailures(); - expect(count).toBe(0, "should not track a failure for an event that never became visible"); + // should not track a failure for an event that never became visible + expect(count).toBe(0); }); - it("does not track a failed decryption where the event is subsequently successfully decrypted", () => { - const decryptedEvent = createFailedDecryptionEvent(); + it("does not track a failed decryption where the event is subsequently successfully decrypted", async () => { + const decryptedEvent = await createFailedDecryptionEvent(); + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => { - expect(true).toBe(false, "should not track an event that has since been decrypted correctly"); + (_total: number) => { + // should not track an event that has since been decrypted correctly + expect(true).toBe(false); }, () => "UnknownError", ); @@ -147,8 +160,11 @@ describe("DecryptionFailureTracker", function () { const err = new MockDecryptionError(); tracker.eventDecrypted(decryptedEvent, err); - // Indicate successful decryption: clear data can be anything where the msgtype is not m.bad.encrypted - decryptedEvent.setClearData({}); + // Indicate successful decryption. + await decryptExistingEvent(decryptedEvent, { + plainType: "m.room.message", + plainContent: { body: "success" }, + }); tracker.eventDecrypted(decryptedEvent, null); // Pretend "now" is Infinity @@ -161,11 +177,13 @@ describe("DecryptionFailureTracker", function () { it( "does not track a failed decryption where the event is subsequently successfully decrypted " + "and later becomes visible", - () => { - const decryptedEvent = createFailedDecryptionEvent(); + async () => { + const decryptedEvent = await createFailedDecryptionEvent(); + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => { - expect(true).toBe(false, "should not track an event that has since been decrypted correctly"); + (_total: number) => { + // should not track an event that has since been decrypted correctly + expect(true).toBe(false); }, () => "UnknownError", ); @@ -173,8 +191,11 @@ describe("DecryptionFailureTracker", function () { const err = new MockDecryptionError(); tracker.eventDecrypted(decryptedEvent, err); - // Indicate successful decryption: clear data can be anything where the msgtype is not m.bad.encrypted - decryptedEvent.setClearData({}); + // Indicate successful decryption. + await decryptExistingEvent(decryptedEvent, { + plainType: "m.room.message", + plainContent: { body: "success" }, + }); tracker.eventDecrypted(decryptedEvent, null); tracker.addVisibleEvent(decryptedEvent); @@ -187,13 +208,14 @@ describe("DecryptionFailureTracker", function () { }, ); - it("only tracks a single failure per event, despite multiple failed decryptions for multiple events", () => { - const decryptedEvent = createFailedDecryptionEvent(); - const decryptedEvent2 = createFailedDecryptionEvent(); + it("only tracks a single failure per event, despite multiple failed decryptions for multiple events", async () => { + const decryptedEvent = await createFailedDecryptionEvent(); + const decryptedEvent2 = await createFailedDecryptionEvent(); let count = 0; + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => (count += total), + (total: number) => (count += total), () => "UnknownError", ); @@ -220,15 +242,17 @@ describe("DecryptionFailureTracker", function () { tracker.trackFailures(); tracker.trackFailures(); - expect(count).toBe(2, count + " failures tracked, should only track a single failure per event"); + // should only track a single failure per event + expect(count).toBe(2); }); - it("should not track a failure for an event that was tracked previously", () => { - const decryptedEvent = createFailedDecryptionEvent(); + it("should not track a failure for an event that was tracked previously", async () => { + const decryptedEvent = await createFailedDecryptionEvent(); let count = 0; + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => (count += total), + (total: number) => (count += total), () => "UnknownError", ); @@ -248,18 +272,20 @@ describe("DecryptionFailureTracker", function () { tracker.trackFailures(); - expect(count).toBe(1, "should only track a single failure per event"); + // should only track a single failure per event + expect(count).toBe(1); }); - it.skip("should not track a failure for an event that was tracked in a previous session", () => { + it.skip("should not track a failure for an event that was tracked in a previous session", async () => { // This test uses localStorage, clear it beforehand localStorage.clear(); - const decryptedEvent = createFailedDecryptionEvent(); + const decryptedEvent = await createFailedDecryptionEvent(); let count = 0; + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total) => (count += total), + (total: number) => (count += total), () => "UnknownError", ); @@ -276,8 +302,9 @@ describe("DecryptionFailureTracker", function () { tracker.trackFailures(); // Simulate the browser refreshing by destroying tracker and creating a new tracker + // @ts-ignore access to private constructor const secondTracker = new DecryptionFailureTracker( - (total) => (count += total), + (total: number) => (count += total), () => "UnknownError", ); @@ -289,19 +316,22 @@ describe("DecryptionFailureTracker", function () { secondTracker.checkFailures(Infinity); secondTracker.trackFailures(); - expect(count).toBe(1, count + " failures tracked, should only track a single failure per event"); + // should only track a single failure per event + expect(count).toBe(1); }); - it("should count different error codes separately for multiple failures with different error codes", () => { - const counts = {}; + it("should count different error codes separately for multiple failures with different error codes", async () => { + const counts: Record = {}; + + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total, errorCode) => (counts[errorCode] = (counts[errorCode] || 0) + total), - (error) => (error === "UnknownError" ? "UnknownError" : "OlmKeysNotSentError"), + (total: number, errorCode: string) => (counts[errorCode] = (counts[errorCode] || 0) + total), + (error: string) => (error === "UnknownError" ? "UnknownError" : "OlmKeysNotSentError"), ); - const decryptedEvent1 = createFailedDecryptionEvent(); - const decryptedEvent2 = createFailedDecryptionEvent(); - const decryptedEvent3 = createFailedDecryptionEvent(); + const decryptedEvent1 = await createFailedDecryptionEvent(); + const decryptedEvent2 = await createFailedDecryptionEvent(); + const decryptedEvent3 = await createFailedDecryptionEvent(); const error1 = new MockDecryptionError("UnknownError"); const error2 = new MockDecryptionError("OlmKeysNotSentError"); @@ -322,19 +352,21 @@ describe("DecryptionFailureTracker", function () { tracker.trackFailures(); //expect(counts['UnknownError']).toBe(1, 'should track one UnknownError'); - expect(counts["OlmKeysNotSentError"]).toBe(2, "should track two OlmKeysNotSentError"); + expect(counts["OlmKeysNotSentError"]).toBe(2); }); - it("should aggregate error codes correctly", () => { - const counts = {}; + it("should aggregate error codes correctly", async () => { + const counts: Record = {}; + + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total, errorCode) => (counts[errorCode] = (counts[errorCode] || 0) + total), - (errorCode) => "OlmUnspecifiedError", + (total: number, errorCode: string) => (counts[errorCode] = (counts[errorCode] || 0) + total), + (_errorCode: string) => "OlmUnspecifiedError", ); - const decryptedEvent1 = createFailedDecryptionEvent(); - const decryptedEvent2 = createFailedDecryptionEvent(); - const decryptedEvent3 = createFailedDecryptionEvent(); + const decryptedEvent1 = await createFailedDecryptionEvent(); + const decryptedEvent2 = await createFailedDecryptionEvent(); + const decryptedEvent3 = await createFailedDecryptionEvent(); const error1 = new MockDecryptionError("ERROR_CODE_1"); const error2 = new MockDecryptionError("ERROR_CODE_2"); @@ -353,20 +385,19 @@ describe("DecryptionFailureTracker", function () { tracker.trackFailures(); - expect(counts["OlmUnspecifiedError"]).toBe( - 3, - "should track three OlmUnspecifiedError, got " + counts["OlmUnspecifiedError"], - ); + expect(counts["OlmUnspecifiedError"]).toBe(3); }); - it("should remap error codes correctly", () => { - const counts = {}; + it("should remap error codes correctly", async () => { + const counts: Record = {}; + + // @ts-ignore access to private constructor const tracker = new DecryptionFailureTracker( - (total, errorCode) => (counts[errorCode] = (counts[errorCode] || 0) + total), - (errorCode) => Array.from(errorCode).reverse().join(""), + (total: number, errorCode: string) => (counts[errorCode] = (counts[errorCode] || 0) + total), + (errorCode: string) => Array.from(errorCode).reverse().join(""), ); - const decryptedEvent = createFailedDecryptionEvent(); + const decryptedEvent = await createFailedDecryptionEvent(); const error = new MockDecryptionError("ERROR_CODE_1"); @@ -379,6 +410,7 @@ describe("DecryptionFailureTracker", function () { tracker.trackFailures(); - expect(counts["1_EDOC_RORRE"]).toBe(1, "should track remapped error code"); + // should track remapped error code + expect(counts["1_EDOC_RORRE"]).toBe(1); }); }); diff --git a/linked-dependencies/matrix-react-sdk/test/LegacyCallHandler-test.ts b/linked-dependencies/matrix-react-sdk/test/LegacyCallHandler-test.ts index 9e31baad2a..8e54ac0490 100644 --- a/linked-dependencies/matrix-react-sdk/test/LegacyCallHandler-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/LegacyCallHandler-test.ts @@ -23,6 +23,7 @@ import { RuleId, TweakName, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { CallEvent, CallState, CallType, MatrixCall } from "matrix-js-sdk/src/webrtc/call"; import EventEmitter from "events"; import { mocked } from "jest-mock"; @@ -102,7 +103,7 @@ function mkStubDM(roomId: string, userId: string) { name: "Member", rawDisplayName: "Member", roomId: roomId, - membership: "join", + membership: KnownMembership.Join, getAvatarUrl: () => "mxc://avatar.url/image.png", getMxcAvatarUrl: () => "mxc://avatar.url/image.png", }, @@ -111,7 +112,7 @@ function mkStubDM(roomId: string, userId: string) { name: "Member", rawDisplayName: "Member", roomId: roomId, - membership: "join", + membership: KnownMembership.Join, getAvatarUrl: () => "mxc://avatar.url/image.png", getMxcAvatarUrl: () => "mxc://avatar.url/image.png", }, @@ -120,7 +121,7 @@ function mkStubDM(roomId: string, userId: string) { name: "Bot user", rawDisplayName: "Bot user", roomId: roomId, - membership: "join", + membership: KnownMembership.Join, getAvatarUrl: () => "mxc://avatar.url/image.png", getMxcAvatarUrl: () => "mxc://avatar.url/image.png", }, diff --git a/linked-dependencies/matrix-react-sdk/test/MatrixClientPeg-test.ts b/linked-dependencies/matrix-react-sdk/test/MatrixClientPeg-test.ts index b94ec7cb01..2ed08e0a21 100644 --- a/linked-dependencies/matrix-react-sdk/test/MatrixClientPeg-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/MatrixClientPeg-test.ts @@ -17,6 +17,10 @@ limitations under the License. import { logger } from "matrix-js-sdk/src/logger"; import fetchMockJest from "fetch-mock-jest"; import EventEmitter from "events"; +import { + ProvideCryptoSetupExtensions, + SecretStorageKeyDescription, +} from "@matrix-org/react-sdk-module-api/lib/lifecycles/CryptoSetupExtensions"; import { advanceDateAndTime, stubClient } from "./test-utils"; import { IMatrixClientPeg, MatrixClientPeg as peg } from "../src/MatrixClientPeg"; @@ -25,6 +29,7 @@ import Modal from "../src/Modal"; import PlatformPeg from "../src/PlatformPeg"; import { SettingLevel } from "../src/settings/SettingLevel"; import { Features } from "../src/settings/Settings"; +import { ModuleRunner } from "../src/modules/ModuleRunner"; jest.useFakeTimers(); @@ -77,6 +82,78 @@ describe("MatrixClientPeg", () => { expect(peg.userRegisteredWithinLastHours(24)).toBe(false); }); + describe(".start extensions", () => { + let testPeg: IMatrixClientPeg; + + beforeEach(() => { + // instantiate a MatrixClientPegClass instance, with a new MatrixClient + testPeg = new PegClass(); + fetchMockJest.get("http://example.com/_matrix/client/versions", {}); + }); + + describe("cryptoSetup extension", () => { + it("should call default cryptoSetup.getDehydrationKeyCallback", async () => { + const mockCryptoSetup = { + SHOW_ENCRYPTION_SETUP_UI: true, + examineLoginResponse: jest.fn(), + persistCredentials: jest.fn(), + getSecretStorageKey: jest.fn(), + createSecretStorageKey: jest.fn(), + catchAccessSecretStorageError: jest.fn(), + setupEncryptionNeeded: jest.fn(), + getDehydrationKeyCallback: jest.fn().mockReturnValue(null), + } as ProvideCryptoSetupExtensions; + + // Ensure we have an instance before we set up spies + const instance = ModuleRunner.instance; + jest.spyOn(instance.extensions, "cryptoSetup", "get").mockReturnValue(mockCryptoSetup); + + testPeg.replaceUsingCreds({ + accessToken: "SEKRET", + homeserverUrl: "http://example.com", + userId: "@user:example.com", + deviceId: "TEST_DEVICE_ID", + }); + + expect(mockCryptoSetup.getDehydrationKeyCallback).toHaveBeenCalledTimes(1); + }); + + it("should call overridden cryptoSetup.getDehydrationKeyCallback", async () => { + const mockDehydrationKeyCallback = () => Uint8Array.from([0x11, 0x22, 0x33]); + + const mockCryptoSetup = { + SHOW_ENCRYPTION_SETUP_UI: true, + examineLoginResponse: jest.fn(), + persistCredentials: jest.fn(), + getSecretStorageKey: jest.fn(), + createSecretStorageKey: jest.fn(), + catchAccessSecretStorageError: jest.fn(), + setupEncryptionNeeded: jest.fn(), + getDehydrationKeyCallback: jest.fn().mockReturnValue(mockDehydrationKeyCallback), + } as ProvideCryptoSetupExtensions; + + // Ensure we have an instance before we set up spies + const instance = ModuleRunner.instance; + jest.spyOn(instance.extensions, "cryptoSetup", "get").mockReturnValue(mockCryptoSetup); + + testPeg.replaceUsingCreds({ + accessToken: "SEKRET", + homeserverUrl: "http://example.com", + userId: "@user:example.com", + deviceId: "TEST_DEVICE_ID", + }); + expect(mockCryptoSetup.getDehydrationKeyCallback).toHaveBeenCalledTimes(1); + + const client = testPeg.get(); + const dehydrationKey = await client?.cryptoCallbacks.getDehydrationKey!( + {} as SecretStorageKeyDescription, + (key: Uint8Array) => true, + ); + expect(dehydrationKey).toEqual(Uint8Array.from([0x11, 0x22, 0x33])); + }); + }); + }); + describe(".start", () => { let testPeg: IMatrixClientPeg; diff --git a/linked-dependencies/matrix-react-sdk/test/Reply-test.ts b/linked-dependencies/matrix-react-sdk/test/Reply-test.ts index ac64610ec7..b7ae3c9eef 100644 --- a/linked-dependencies/matrix-react-sdk/test/Reply-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/Reply-test.ts @@ -22,6 +22,7 @@ import { LocationAssetType, M_ASSET, M_POLL_END, + Room, } from "matrix-js-sdk/src/matrix"; import { @@ -31,7 +32,7 @@ import { stripHTMLReply, stripPlainReply, } from "../src/utils/Reply"; -import { makePollStartEvent, mkEvent } from "./test-utils"; +import { makePollStartEvent, mkEvent, stubClient } from "./test-utils"; import { RoomPermalinkCreator } from "../src/utils/permalinks/Permalinks"; function makeTestEvent(type: string, content: IContent): MatrixEvent { @@ -66,7 +67,7 @@ describe("Reply", () => { room: "!room1:server", content: {}, }); - event.makeRedacted(event); + event.makeRedacted(event, new Room(event.getRoomId()!, stubClient(), event.getSender()!)); expect(getParentEventId(event)).toBeUndefined(); }); @@ -182,7 +183,7 @@ But this is not room: "!room1:server", content: {}, }); - event.makeRedacted(event); + event.makeRedacted(event, new Room(event.getRoomId()!, stubClient(), event.getSender()!)); expect(shouldDisplayReply(event)).toBe(false); }); diff --git a/linked-dependencies/matrix-react-sdk/test/RoomNotifs-test.ts b/linked-dependencies/matrix-react-sdk/test/RoomNotifs-test.ts index 371ffea910..3526acf4bf 100644 --- a/linked-dependencies/matrix-react-sdk/test/RoomNotifs-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/RoomNotifs-test.ts @@ -25,6 +25,7 @@ import { MatrixEvent, PendingEventOrdering, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import type { MatrixClient } from "matrix-js-sdk/src/matrix"; import { mkEvent, mkRoom, mkRoomMember, muteRoom, stubClient, upsertRoomStateEvents } from "./test-utils"; @@ -277,7 +278,7 @@ describe("RoomNotifs test", () => { }); it("indicates the user has been invited to a channel", async () => { - room.updateMyMembership("invite"); + room.updateMyMembership(KnownMembership.Invite); const { level, symbol, count } = determineUnreadState(room); @@ -290,9 +291,15 @@ describe("RoomNotifs test", () => { jest.spyOn(SettingsStore, "getValue").mockImplementation((name) => { return name === "feature_ask_to_join"; }); - const roomMember = mkRoomMember(room.roomId, MatrixClientPeg.get()!.getSafeUserId(), "leave", true, { - membership: "knock", - }); + const roomMember = mkRoomMember( + room.roomId, + MatrixClientPeg.get()!.getSafeUserId(), + KnownMembership.Leave, + true, + { + membership: KnownMembership.Knock, + }, + ); jest.spyOn(room, "getMember").mockReturnValue(roomMember); const { level, symbol, count } = determineUnreadState(room); diff --git a/linked-dependencies/matrix-react-sdk/test/SlashCommands-test.tsx b/linked-dependencies/matrix-react-sdk/test/SlashCommands-test.tsx index ae90d2bbc4..6ef56aa7fd 100644 --- a/linked-dependencies/matrix-react-sdk/test/SlashCommands-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/SlashCommands-test.tsx @@ -15,6 +15,7 @@ limitations under the License. */ import { MatrixClient, Room, RoomMember } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { mocked } from "jest-mock"; import { Command, Commands, getCommand } from "../src/SlashCommands"; @@ -162,7 +163,7 @@ describe("SlashCommands", () => { it("should warn about self demotion", async () => { setCurrentRoom(); const member = new RoomMember(roomId, client.getSafeUserId()); - member.membership = "join"; + member.membership = KnownMembership.Join; member.powerLevel = 100; room.getMember = () => member; command.run(client, roomId, null, `${client.getUserId()} 0`); @@ -172,7 +173,7 @@ describe("SlashCommands", () => { it("should default to 50 if no powerlevel specified", async () => { setCurrentRoom(); const member = new RoomMember(roomId, "@user:server"); - member.membership = "join"; + member.membership = KnownMembership.Join; room.getMember = () => member; command.run(client, roomId, null, member.userId); expect(client.setPowerLevel).toHaveBeenCalledWith(roomId, member.userId, 50); @@ -191,7 +192,7 @@ describe("SlashCommands", () => { it("should warn about self demotion", async () => { setCurrentRoom(); const member = new RoomMember(roomId, client.getSafeUserId()); - member.membership = "join"; + member.membership = KnownMembership.Join; member.powerLevel = 100; room.getMember = () => member; command.run(client, roomId, null, client.getSafeUserId()); @@ -366,7 +367,7 @@ describe("SlashCommands", () => { describe("/join", () => { beforeEach(() => { jest.spyOn(dispatcher, "dispatch"); - command = findCommand("join")!; + command = findCommand(KnownMembership.Join)!; }); it("should return usage if no args", () => { diff --git a/linked-dependencies/matrix-react-sdk/test/TextForEvent-test.ts b/linked-dependencies/matrix-react-sdk/test/TextForEvent-test.ts index 4a8258879c..ff1e0a06bc 100644 --- a/linked-dependencies/matrix-react-sdk/test/TextForEvent-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/TextForEvent-test.ts @@ -23,6 +23,7 @@ import { Room, RoomMember, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { render } from "@testing-library/react"; import { ReactElement } from "react"; import { Mocked, mocked } from "jest-mock"; @@ -418,7 +419,7 @@ describe("TextForEvent", () => { }); it("returns correct message for redacted poll start", () => { - pollEvent.makeRedacted(pollEvent); + pollEvent.makeRedacted(pollEvent, new Room(pollEvent.getRoomId()!, mockClient, mockClient.getSafeUserId())); expect(textForEvent(pollEvent, mockClient)).toEqual("@a: Message deleted"); }); @@ -444,7 +445,10 @@ describe("TextForEvent", () => { }); it("returns correct message for redacted message", () => { - messageEvent.makeRedacted(messageEvent); + messageEvent.makeRedacted( + messageEvent, + new Room(messageEvent.getRoomId()!, mockClient, mockClient.getSafeUserId()), + ); expect(textForEvent(messageEvent, mockClient)).toEqual("@a: Message deleted"); }); @@ -504,12 +508,12 @@ describe("TextForEvent", () => { type: "m.room.member", sender: "@a:foo", content: { - membership: "join", + membership: KnownMembership.Join, avatar_url: "b", displayname: "Bob", }, prev_content: { - membership: "join", + membership: KnownMembership.Join, avatar_url: "a", displayname: "Andy", }, diff --git a/linked-dependencies/matrix-react-sdk/test/Unread-test.ts b/linked-dependencies/matrix-react-sdk/test/Unread-test.ts index 5caeeb7f34..8d4f319a39 100644 --- a/linked-dependencies/matrix-react-sdk/test/Unread-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/Unread-test.ts @@ -63,7 +63,7 @@ describe("Unread", () => { type: EventType.RoomMessage, sender: aliceId, }); - redactedEvent.makeRedacted(redactedEvent); + redactedEvent.makeRedacted(redactedEvent, new Room(redactedEvent.getRoomId()!, client, aliceId)); beforeEach(() => { jest.clearAllMocks(); @@ -408,7 +408,7 @@ describe("Unread", () => { content: {}, }); console.log("Event Id", redactedEvent.getId()); - redactedEvent.makeRedacted(redactedEvent); + redactedEvent.makeRedacted(redactedEvent, room); console.log("Event Id", redactedEvent.getId()); // Only for timeline events. room.addLiveEvents([redactedEvent]); diff --git a/linked-dependencies/matrix-react-sdk/test/__snapshots__/SlashCommands-test.tsx.snap b/linked-dependencies/matrix-react-sdk/test/__snapshots__/SlashCommands-test.tsx.snap index 08d3bdcc47..fdffb74ac3 100644 --- a/linked-dependencies/matrix-react-sdk/test/__snapshots__/SlashCommands-test.tsx.snap +++ b/linked-dependencies/matrix-react-sdk/test/__snapshots__/SlashCommands-test.tsx.snap @@ -18,7 +18,7 @@ exports[`SlashCommands /rainbow should make things rainbowy 1`] = ` { "body": "this is a test message", "format": "org.matrix.custom.html", - "formatted_body": "this is a test message", + "formatted_body": "this is a test message", "msgtype": "m.text", } `; @@ -27,7 +27,7 @@ exports[`SlashCommands /rainbowme should make things rainbowy 1`] = ` { "body": "this is a test message", "format": "org.matrix.custom.html", - "formatted_body": "this is a test message", + "formatted_body": "this is a test message", "msgtype": "m.emote", } `; diff --git a/linked-dependencies/matrix-react-sdk/test/accessibility/RovingTabIndex-test.tsx b/linked-dependencies/matrix-react-sdk/test/accessibility/RovingTabIndex-test.tsx index 4a2e67fece..c2d5fbf0a8 100644 --- a/linked-dependencies/matrix-react-sdk/test/accessibility/RovingTabIndex-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/accessibility/RovingTabIndex-test.tsx @@ -16,6 +16,7 @@ limitations under the License. import React, { HTMLAttributes } from "react"; import { render } from "@testing-library/react"; +import userEvent from "@testing-library/user-event"; import { IState, @@ -364,4 +365,61 @@ describe("RovingTabIndex", () => { }); }); }); + + describe("handles arrow keys", () => { + it("should handle up/down arrow keys work when handleUpDown=true", async () => { + const { container } = render( + + {({ onKeyDownHandler }) => ( +
+ {button1} + {button2} + {button3} +
+ )} +
, + ); + + container.querySelectorAll("button")[0].focus(); + checkTabIndexes(container.querySelectorAll("button"), [0, -1, -1]); + + await userEvent.keyboard("[ArrowDown]"); + checkTabIndexes(container.querySelectorAll("button"), [-1, 0, -1]); + + await userEvent.keyboard("[ArrowDown]"); + checkTabIndexes(container.querySelectorAll("button"), [-1, -1, 0]); + + await userEvent.keyboard("[ArrowUp]"); + checkTabIndexes(container.querySelectorAll("button"), [-1, 0, -1]); + + await userEvent.keyboard("[ArrowUp]"); + checkTabIndexes(container.querySelectorAll("button"), [0, -1, -1]); + + // Does not loop without + await userEvent.keyboard("[ArrowUp]"); + checkTabIndexes(container.querySelectorAll("button"), [0, -1, -1]); + }); + + it("should call scrollIntoView if specified", async () => { + const { container } = render( + + {({ onKeyDownHandler }) => ( +
+ {button1} + {button2} + {button3} +
+ )} +
, + ); + + container.querySelectorAll("button")[0].focus(); + checkTabIndexes(container.querySelectorAll("button"), [0, -1, -1]); + + const button = container.querySelectorAll("button")[1]; + const mock = jest.spyOn(button, "scrollIntoView"); + await userEvent.keyboard("[ArrowDown]"); + expect(mock).toHaveBeenCalled(); + }); + }); }); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/LoggedInView-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/LoggedInView-test.tsx index a8cf7ffb34..04c8b43811 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/LoggedInView-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/LoggedInView-test.tsx @@ -38,6 +38,7 @@ describe("", () => { getMediaHandler: jest.fn(), setPushRuleEnabled: jest.fn(), setPushRuleActions: jest.fn(), + getCrypto: jest.fn().mockReturnValue(undefined), }); const mediaHandler = new MediaHandler(mockClient); const mockSdkContext = new TestSdkContext(); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/MatrixChat-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/MatrixChat-test.tsx index 63eec01ae3..908c7a7c04 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/MatrixChat-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/MatrixChat-test.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React, { ComponentProps } from "react"; -import { fireEvent, render, RenderResult, screen, within } from "@testing-library/react"; +import { fireEvent, render, RenderResult, screen, waitFor, within } from "@testing-library/react"; import fetchMock from "fetch-mock-jest"; import { Mocked, mocked } from "jest-mock"; import { ClientEvent, MatrixClient, MatrixEvent, Room, SyncState } from "matrix-js-sdk/src/matrix"; @@ -26,6 +26,7 @@ import { logger } from "matrix-js-sdk/src/logger"; import { OidcError } from "matrix-js-sdk/src/oidc/error"; import { BearerTokenResponse } from "matrix-js-sdk/src/oidc/validate"; import { defer, sleep } from "matrix-js-sdk/src/utils"; +import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api"; import MatrixChat from "../../../src/components/structures/MatrixChat"; import * as StorageManager from "../../../src/utils/StorageManager"; @@ -59,6 +60,7 @@ import { SSO_HOMESERVER_URL_KEY, SSO_ID_SERVER_URL_KEY } from "../../../src/Base import SettingsStore from "../../../src/settings/SettingsStore"; import { SettingLevel } from "../../../src/settings/SettingLevel"; import { MatrixClientPeg as peg } from "../../../src/MatrixClientPeg"; +import DMRoomMap from "../../../src/utils/DMRoomMap"; jest.mock("matrix-js-sdk/src/oidc/authorize", () => ({ completeAuthorizationCodeGrant: jest.fn(), @@ -220,6 +222,9 @@ describe("", () => { jest.spyOn(StorageManager, "idbLoad").mockReset(); jest.spyOn(StorageManager, "idbSave").mockResolvedValue(undefined); jest.spyOn(defaultDispatcher, "dispatch").mockClear(); + jest.spyOn(defaultDispatcher, "fire").mockClear(); + + DMRoomMap.makeShared(mockClient); await clearAllModals(); }); @@ -227,6 +232,9 @@ describe("", () => { resetJsDomAfterEach(); afterEach(() => { + // @ts-ignore + DMRoomMap.setShared(null); + jest.restoreAllMocks(); // emit a loggedOut event so that all of the Store singletons forget about their references to the mock client @@ -239,6 +247,22 @@ describe("", () => { expect(container).toMatchSnapshot(); }); + it("should fire to focus the message composer", async () => { + getComponent(); + defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: "!room:server.org", focusNext: "composer" }); + await waitFor(() => { + expect(defaultDispatcher.fire).toHaveBeenCalledWith(Action.FocusSendMessageComposer); + }); + }); + + it("should fire to focus the threads panel", async () => { + getComponent(); + defaultDispatcher.dispatch({ action: Action.ViewRoom, room_id: "!room:server.org", focusNext: "threadsPanel" }); + await waitFor(() => { + expect(defaultDispatcher.fire).toHaveBeenCalledWith(Action.FocusThreadsPanel); + }); + }); + describe("when query params have a OIDC params", () => { const issuer = "https://auth.com/"; const homeserverUrl = "https://matrix.org"; @@ -925,6 +949,9 @@ describe("", () => { const mockCrypto = { getVerificationRequestsToDeviceInProgress: jest.fn().mockReturnValue([]), getUserDeviceInfo: jest.fn().mockResolvedValue(new Map()), + getUserVerificationStatus: jest + .fn() + .mockResolvedValue(new UserVerificationStatus(false, false, false)), }; loginClient.isCryptoEnabled.mockReturnValue(true); loginClient.getCrypto.mockReturnValue(mockCrypto as any); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/MatrixClientContextProvider-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/MatrixClientContextProvider-test.tsx new file mode 100644 index 0000000000..cadd0bc166 --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/MatrixClientContextProvider-test.tsx @@ -0,0 +1,117 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { act, render } from "@testing-library/react"; +import React, { useContext } from "react"; +import { CryptoEvent, MatrixClient } from "matrix-js-sdk/src/matrix"; +import { UserVerificationStatus } from "matrix-js-sdk/src/crypto-api"; + +import MatrixClientContext from "../../../src/contexts/MatrixClientContext"; +import { MatrixClientContextProvider } from "../../../src/components/structures/MatrixClientContextProvider"; +import { LocalDeviceVerificationStateContext } from "../../../src/contexts/LocalDeviceVerificationStateContext"; +import { + flushPromises, + getMockClientWithEventEmitter, + mockClientMethodsCrypto, + mockClientMethodsUser, +} from "../../test-utils"; + +describe("MatrixClientContextProvider", () => { + it("Should expose a matrix client context", () => { + const mockClient = getMockClientWithEventEmitter({ + ...mockClientMethodsUser(), + getCrypto: () => null, + }); + + let receivedClient: MatrixClient | undefined; + function ContextReceiver() { + receivedClient = useContext(MatrixClientContext); + return <>; + } + + render( + + + , + ); + + expect(receivedClient).toBe(mockClient); + }); + + describe("Should expose a verification status context", () => { + /** The most recent verification status received by our `ContextReceiver` */ + let receivedState: boolean | undefined; + + /** The mock client for use in the tests */ + let mockClient: MatrixClient; + + function ContextReceiver() { + receivedState = useContext(LocalDeviceVerificationStateContext); + return <>; + } + + function getComponent(mockClient: MatrixClient) { + return render( + + + , + ); + } + + beforeEach(() => { + receivedState = undefined; + mockClient = getMockClientWithEventEmitter({ + ...mockClientMethodsUser(), + ...mockClientMethodsCrypto(), + }); + }); + + it("returns false if device is unverified", async () => { + mockClient.getCrypto()!.getUserVerificationStatus = jest + .fn() + .mockResolvedValue(new UserVerificationStatus(false, false, false)); + getComponent(mockClient); + expect(receivedState).toBe(false); + }); + + it("returns true if device is verified", async () => { + mockClient.getCrypto()!.getUserVerificationStatus = jest + .fn() + .mockResolvedValue(new UserVerificationStatus(true, false, false)); + getComponent(mockClient); + await act(() => flushPromises()); + expect(receivedState).toBe(true); + }); + + it("updates when the trust status updates", async () => { + const getVerificationStatus = jest.fn().mockResolvedValue(new UserVerificationStatus(false, false, false)); + mockClient.getCrypto()!.getUserVerificationStatus = getVerificationStatus; + getComponent(mockClient); + + // starts out false + await act(() => flushPromises()); + expect(receivedState).toBe(false); + + // Now the state is updated + const verifiedStatus = new UserVerificationStatus(true, false, false); + getVerificationStatus.mockResolvedValue(verifiedStatus); + act(() => { + mockClient.emit(CryptoEvent.UserTrustStatusChanged, mockClient.getSafeUserId(), verifiedStatus); + }); + expect(receivedState).toBe(true); + }); + }); +}); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/MessagePanel-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/MessagePanel-test.tsx index 45fe3b4abe..3513cee91f 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/MessagePanel-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/MessagePanel-test.tsx @@ -18,6 +18,7 @@ limitations under the License. import React from "react"; import { EventEmitter } from "events"; import { MatrixEvent, Room, RoomMember, Thread, ReceiptType } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { render } from "@testing-library/react"; import { TooltipProvider } from "@vector-im/compound-web"; @@ -171,8 +172,8 @@ describe("MessagePanel", function () { user: "@user:id", target: bobMember, ts: ts0 + i * 1000, - mship: "join", - prevMship: "join", + mship: KnownMembership.Join, + prevMship: KnownMembership.Join, name: "A user", }), ); @@ -205,8 +206,8 @@ describe("MessagePanel", function () { user: "@user:id", target: bobMember, ts: ts0 + i * 1000, - mship: "join", - prevMship: "join", + mship: KnownMembership.Join, + prevMship: KnownMembership.Join, name: "A user", }), ); @@ -245,7 +246,7 @@ describe("MessagePanel", function () { user: alice, target: aliceMember, ts: ts0 + 1, - mship: "join", + mship: KnownMembership.Join, name: "Alice", }), mkEvent({ @@ -285,7 +286,7 @@ describe("MessagePanel", function () { skey: "@bob:example.org", target: bobMember, ts: ts0 + 5, - mship: "invite", + mship: KnownMembership.Invite, name: "Bob", }), ]; @@ -542,8 +543,8 @@ describe("MessagePanel", function () { user: "@user:id", target: bobMember, ts: Date.now(), - mship: "join", - prevMship: "join", + mship: KnownMembership.Join, + prevMship: KnownMembership.Join, name: "A user", }), ]; @@ -571,8 +572,8 @@ describe("MessagePanel", function () { user: "@user:id", target: bobMember, ts: Date.now(), - mship: "join", - prevMship: "join", + mship: KnownMembership.Join, + prevMship: KnownMembership.Join, name: "A user", }), ...events, @@ -695,8 +696,8 @@ describe("MessagePanel", function () { for (let i = 0; i < 100; i++) { events.push( TestUtilsMatrix.mkMembership({ - mship: "join", - prevMship: "join", + mship: KnownMembership.Join, + prevMship: KnownMembership.Join, room: "!room:id", user: "@user:id", event: true, @@ -716,8 +717,8 @@ describe("MessagePanel", function () { for (let i = 0; i < 100; i++) { events.push( TestUtilsMatrix.mkMembership({ - mship: "join", - prevMship: "join", + mship: KnownMembership.Join, + prevMship: KnownMembership.Join, room: "!room:id", user: "@user:id", event: true, diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/ReleaseAnnouncement-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/ReleaseAnnouncement-test.tsx new file mode 100644 index 0000000000..3477e54d4b --- /dev/null +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/ReleaseAnnouncement-test.tsx @@ -0,0 +1,48 @@ +/* + * + * Copyright 2024 The Matrix.org Foundation C.I.C. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ + +import React from "react"; +import { render, screen, waitFor } from "@testing-library/react"; + +import { ReleaseAnnouncement } from "../../../src/components/structures/ReleaseAnnouncement"; + +describe("ReleaseAnnouncement", () => { + function renderReleaseAnnouncement() { + return render( + +
content
+
, + ); + } + + test("render the release announcement and close it", async () => { + renderReleaseAnnouncement(); + + // The release announcement is displayed + expect(screen.queryByRole("dialog", { name: "header" })).toBeDefined(); + // Click on the close button in the release announcement + screen.getByRole("button", { name: "close" }).click(); + // The release announcement should be hidden after the close button is clicked + await waitFor(() => expect(screen.queryByRole("dialog", { name: "header" })).toBeNull()); + }); +}); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/RoomView-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/RoomView-test.tsx index 916e8a8225..d0d12d7105 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/RoomView-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/RoomView-test.tsx @@ -29,6 +29,7 @@ import { SearchResult, IEvent, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { MEGOLM_ALGORITHM } from "matrix-js-sdk/src/crypto/olmlib"; import { fireEvent, render, screen, RenderResult, waitForElementToBeRemoved, waitFor } from "@testing-library/react"; import userEvent from "@testing-library/user-event"; @@ -238,7 +239,7 @@ describe("RoomView", () => { }); it("updates url preview visibility on encryption state change", async () => { - room.getMyMembership = jest.fn().mockReturnValue("join"); + room.getMyMembership = jest.fn().mockReturnValue(KnownMembership.Join); // we should be starting unencrypted expect(cli.isCryptoEnabled()).toEqual(false); expect(cli.isRoomEncrypted(room.roomId)).toEqual(false); @@ -583,7 +584,7 @@ describe("RoomView", () => { it("allows to cancel a join request", async () => { jest.spyOn(MatrixClientPeg, "safeGet").mockReturnValue(client); jest.spyOn(client, "leave").mockResolvedValue({}); - jest.spyOn(room, "getMyMembership").mockReturnValue("knock"); + jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Knock); await mountRoomView(); fireEvent.click(screen.getByRole("button", { name: "Cancel request" })); @@ -594,7 +595,7 @@ describe("RoomView", () => { }); it("should close search results when edit is clicked", async () => { - room.getMyMembership = jest.fn().mockReturnValue("join"); + room.getMyMembership = jest.fn().mockReturnValue(KnownMembership.Join); const eventMapper = (obj: Partial) => new MatrixEvent(obj); @@ -655,7 +656,7 @@ describe("RoomView", () => { const room2 = new Room(`!${roomCount++}:example.org`, cli, "@alice:example.org"); rooms.set(room2.roomId, room2); - room.getMyMembership = jest.fn().mockReturnValue("join"); + room.getMyMembership = jest.fn().mockReturnValue(KnownMembership.Join); const eventMapper = (obj: Partial) => new MatrixEvent(obj); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/SpaceHierarchy-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/SpaceHierarchy-test.tsx index 3b851c5a61..653b24fc53 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/SpaceHierarchy-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/SpaceHierarchy-test.tsx @@ -17,7 +17,8 @@ limitations under the License. import React from "react"; import { mocked } from "jest-mock"; import { fireEvent, render, screen, waitFor, waitForElementToBeRemoved } from "@testing-library/react"; -import { MatrixClient, Room, HierarchyRoom } from "matrix-js-sdk/src/matrix"; +import { HierarchyRoom, JoinRule, MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { RoomHierarchy } from "matrix-js-sdk/src/room-hierarchy"; import { TooltipProvider } from "@vector-im/compound-web"; @@ -181,7 +182,7 @@ describe("SpaceHierarchy", () => { mocked(client.getRoom).mockImplementation( (roomId) => client.getRooms().find((room) => room.roomId === roomId) ?? null, ); - [room1, room2, space1, room3].forEach((r) => mocked(r.getMyMembership).mockReturnValue("leave")); + [room1, room2, space1, room3].forEach((r) => mocked(r.getMyMembership).mockReturnValue(KnownMembership.Leave)); const hierarchyRoot: HierarchyRoom = { room_id: root.roomId, @@ -209,6 +210,13 @@ describe("SpaceHierarchy", () => { type: "m.space.child", sender: "@other:server", }, + { + state_key: "!knock1:server", + content: { order: "4" }, + origin_server_ts: 111, + type: "m.space.child", + sender: "@other:server", + }, ], world_readable: true, guest_can_join: true, @@ -252,9 +260,25 @@ describe("SpaceHierarchy", () => { world_readable: true, guest_can_join: true, }; + const hierarchyKnockRoom1: HierarchyRoom = { + room_id: "!knock1:server", + name: "Knock room", + num_joined_members: 3, + children_state: [], + world_readable: true, + guest_can_join: true, + join_rule: JoinRule.Knock, + }; mocked(client.getRoomHierarchy).mockResolvedValue({ - rooms: [hierarchyRoot, hierarchyRoom1, hierarchyRoom2, hierarchySpace1, hierarchyRoom3], + rooms: [ + hierarchyRoot, + hierarchyRoom1, + hierarchyRoom2, + hierarchySpace1, + hierarchyRoom3, + hierarchyKnockRoom1, + ], }); const defaultProps = { @@ -292,5 +316,24 @@ describe("SpaceHierarchy", () => { expect(client.joinRoom).toHaveBeenCalledWith(space1.roomId, expect.any(Object)); expect(client.joinRoom).toHaveBeenCalledWith(room3.roomId, expect.any(Object)); }); + + it("should take user to view room for unjoined knockable rooms", async () => { + jest.spyOn(dispatcher, "dispatch"); + + const { getByText } = render(getComponent()); + // Wait for spinners to go away + await waitForElementToBeRemoved(screen.getAllByRole("progressbar")); + const button = getByText("Knock room")! + .closest("li")! + .querySelector(".mx_AccessibleButton_kind_primary_outline")!; + fireEvent.click(button); + + expect(defaultProps.showRoom).toHaveBeenCalledWith( + expect.anything(), + expect.anything(), + hierarchyKnockRoom1.room_id, + undefined, + ); + }); }); }); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/ThreadPanel-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/ThreadPanel-test.tsx index 9c8bed0af6..74a1d4023f 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/ThreadPanel-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/ThreadPanel-test.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import React from "react"; -import { render, screen, fireEvent, waitFor } from "@testing-library/react"; +import { render, screen, fireEvent, waitFor, getByRole } from "@testing-library/react"; import { mocked } from "jest-mock"; import { MatrixClient, @@ -34,8 +34,11 @@ import { _t } from "../../../src/languageHandler"; import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; import { RoomPermalinkCreator } from "../../../src/utils/permalinks/Permalinks"; import ResizeNotifier from "../../../src/utils/ResizeNotifier"; -import { getRoomContext, mockPlatformPeg, stubClient } from "../../test-utils"; +import { createTestClient, getRoomContext, mkRoom, mockPlatformPeg, stubClient } from "../../test-utils"; import { mkThread } from "../../test-utils/threads"; +import { IRoomState } from "../../../src/components/structures/RoomView"; +import defaultDispatcher from "../../../src/dispatcher/dispatcher"; +import { Action } from "../../../src/dispatcher/actions"; jest.mock("../../../src/utils/Feedback"); @@ -48,6 +51,7 @@ describe("ThreadPanel", () => { filterOption={ThreadFilterType.All} setFilterOption={() => undefined} />, + { wrapper: TooltipProvider }, ); expect(asFragment()).toMatchSnapshot(); }); @@ -64,6 +68,18 @@ describe("ThreadPanel", () => { expect(asFragment()).toMatchSnapshot(); }); + it("matches snapshot when no threads", () => { + const { asFragment } = render( + undefined} + />, + { wrapper: TooltipProvider }, + ); + expect(asFragment()).toMatchSnapshot(); + }); + it("expect that ThreadPanelHeader properly opens a context menu when clicked on the button", () => { const { container } = render( { ); expect(foundButton).toMatchSnapshot(); }); + + it("sends an unthreaded read receipt when the Mark All Threads Read button is clicked", async () => { + const mockClient = createTestClient(); + const mockEvent = {} as MatrixEvent; + const mockRoom = mkRoom(mockClient, "!roomId:example.org"); + mockRoom.getLastLiveEvent.mockReturnValue(mockEvent); + const roomContextObject = { + room: mockRoom, + } as unknown as IRoomState; + const { container } = render( + + + + undefined} + /> + + + , + ); + fireEvent.click(getByRole(container, "button", { name: "Mark all as read" })); + await waitFor(() => + expect(mockClient.sendReadReceipt).toHaveBeenCalledWith(mockEvent, expect.anything(), true), + ); + }); + + it("doesn't send a receipt if no room is in context", async () => { + const mockClient = createTestClient(); + const { container } = render( + + + undefined} + /> + + , + ); + fireEvent.click(getByRole(container, "button", { name: "Mark all as read" })); + await waitFor(() => expect(mockClient.sendReadReceipt).not.toHaveBeenCalled()); + }); + + it("focuses the close button on FocusThreadsPanel dispatch", () => { + const ROOM_ID = "!roomId:example.org"; + + stubClient(); + mockPlatformPeg(); + const mockClient = mocked(MatrixClientPeg.safeGet()); + + const room = new Room(ROOM_ID, mockClient, mockClient.getUserId() ?? "", { + pendingEventOrdering: PendingEventOrdering.Detached, + }); + + render( + + + + + , + ); + + // Unfocus it first so we know it's not just focused by coincidence + screen.getByTestId("base-card-close-button").blur(); + expect(screen.getByTestId("base-card-close-button")).not.toHaveFocus(); + + defaultDispatcher.dispatch({ action: Action.FocusThreadsPanel }, true); + + expect(screen.getByTestId("base-card-close-button")).toHaveFocus(); + }); }); describe("Filtering", () => { diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/TimelinePanel-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/TimelinePanel-test.tsx index a5312e43c5..afbe173940 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/TimelinePanel-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/TimelinePanel-test.tsx @@ -35,6 +35,7 @@ import { ThreadEvent, ThreadFilterType, } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import React, { createRef } from "react"; import { Mocked, mocked } from "jest-mock"; import { forEachRight } from "lodash"; @@ -988,8 +989,8 @@ describe("TimelinePanel", () => { events.forEach((event) => timelineSet.getLiveTimeline().addEvent(event, { toStartOfTimeline: true })); const roomMembership = mkMembership({ - mship: "join", - prevMship: "join", + mship: KnownMembership.Join, + prevMship: KnownMembership.Join, user: authorId, room: room.roomId, event: true, @@ -999,7 +1000,7 @@ describe("TimelinePanel", () => { events.push(roomMembership); const member = new RoomMember(room.roomId, authorId); - member.membership = "join"; + member.membership = KnownMembership.Join; const roomState = new RoomState(room.roomId); jest.spyOn(roomState, "getMember").mockReturnValue(member); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/ViewSource-test.tsx b/linked-dependencies/matrix-react-sdk/test/components/structures/ViewSource-test.tsx index 44c122e901..8f2559dff9 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/ViewSource-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/ViewSource-test.tsx @@ -15,7 +15,7 @@ limitations under the License. */ import { render } from "@testing-library/react"; -import { EventType, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { EventType, MatrixEvent, Room } from "matrix-js-sdk/src/matrix"; import React from "react"; import ViewSource from "../../../src/components/structures/ViewSource"; @@ -43,7 +43,7 @@ describe("ViewSource", () => { content: {}, state_key: undefined, }); - redactedMessageEvent.makeRedacted(redactionEvent); + redactedMessageEvent.makeRedacted(redactionEvent, new Room(ROOM_ID, stubClient(), SENDER)); }); beforeEach(stubClient); diff --git a/linked-dependencies/matrix-react-sdk/test/components/structures/__snapshots__/MatrixChat-test.tsx.snap b/linked-dependencies/matrix-react-sdk/test/components/structures/__snapshots__/MatrixChat-test.tsx.snap index 01a5c7818b..bf03f84a6e 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/structures/__snapshots__/MatrixChat-test.tsx.snap +++ b/linked-dependencies/matrix-react-sdk/test/components/structures/__snapshots__/MatrixChat-test.tsx.snap @@ -325,7 +325,7 @@ exports[` with an existing session onAction() room actions leave_r role="dialog" >

with an existing session onAction() room actions leave_r > Leave room

-
+
with an existing session onAction() room actions leave_r role="dialog" >

with an existing session onAction() room actions leave_r > Leave space

-
+
unsent messages should render warning w class="mx_RoomStatusBar_unsentBadge" >
unsent messages should render warning w class="mx_RoomStatusBar_unsentBadge" >
renders 1`] = ` class="mx_SpaceHierarchy_roomTile_avatar" > renders 1`] = ` class="mx_SpaceHierarchy_roomTile_avatar" > renders 1`] = `
+
  • +
    +
    +
    + + K + +
    +
    + Knock room +
    +
    + 3 members +
    +
    +
    +
    + View +
    + + +
    +
  • renders 1`] = ` class="mx_SpaceHierarchy_roomTile_avatar" > renders 1`] = ` class="mx_Checkbox mx_Checkbox_hasKind mx_Checkbox_kind_solid" >
  • , + ,
  • , - ,
  • { mockCrypto = mocked(mockClient.getCrypto()!); Object.assign(mockCrypto, { isKeyBackupTrusted: jest.fn(), + isDehydrationSupported: jest.fn(() => false), bootstrapCrossSigning: jest.fn(), bootstrapSecretStorage: jest.fn(), }); diff --git a/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/CreateKeyBackupDialog-test.tsx.snap b/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/CreateKeyBackupDialog-test.tsx.snap index ad249e578f..5b7de2c703 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/CreateKeyBackupDialog-test.tsx.snap +++ b/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/CreateKeyBackupDialog-test.tsx.snap @@ -121,7 +121,7 @@ exports[`CreateKeyBackupDialog should display the success dialog when the key ba role="dialog" >

    Success!

    -
    +

    diff --git a/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/ExportE2eKeysDialog-test.tsx.snap b/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/ExportE2eKeysDialog-test.tsx.snap index 348916ae35..8552ab310c 100644 --- a/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/ExportE2eKeysDialog-test.tsx.snap +++ b/linked-dependencies/matrix-react-sdk/test/components/views/dialogs/security/__snapshots__/ExportE2eKeysDialog-test.tsx.snap @@ -14,7 +14,7 @@ exports[`ExportE2eKeysDialog renders 1`] = ` role="dialog" >

    Export room keys

    -
    +
  • @user49:example.com
    Message #49
  • @user48:example.com
    Message #48
  • @user47:example.com
    Message #47
  • @user46:example.com
    Message #46
  • @user45:example.com
    Message #45
  • @user44:example.com
    Message #44
  • @user43:example.com
    Message #43
  • @user42:example.com
    Message #42
  • @user41:example.com
    Message #41
  • @user40:example.com
    Message #40
  • @user39:example.com
    Message #39
  • @user38:example.com
    Message #38
  • @user37:example.com
    Message #37
  • @user36:example.com
    Message #36
  • @user35:example.com
    Message #35
  • @user34:example.com
    Message #34
  • @user33:example.com
    Message #33
  • @user32:example.com
    Message #32
  • @user31:example.com
    Message #31
  • @user30:example.com
    Message #30
  • @user29:example.com
    Message #29
  • @user28:example.com
    Message #28
  • @user27:example.com
    Message #27
  • @user26:example.com
    Message #26
  • @user25:example.com
    Message #25
  • @user24:example.com
    Message #24
  • @user23:example.com
    Message #23
  • @user22:example.com
    Message #22
  • @user21:example.com
    Message #21
  • @user20:example.com
    Message #20
  • @user19:example.com
    Message #19
  • @user18:example.com
    Message #18
  • @user17:example.com
    Message #17
  • @user16:example.com
    Message #16
  • @user15:example.com
    Message #15
  • @user14:example.com
    Message #14
  • @user13:example.com
    Message #13
  • @user12:example.com
    Message #12
  • @user11:example.com
    Message #11
  • @user10:example.com
    Message #10
  • @user9:example.com
    Message #9
  • @user8:example.com
    Message #8
  • @user7:example.com
    Message #7
  • @user6:example.com
    Message #6
  • @user5:example.com
    Message #5
  • @user4:example.com
    Message #4
  • @user3:example.com
    Message #3
  • @user2:example.com
    Message #2
  • @user1:example.com
    Message #1
  • @user0:example.com
    Message #0
  • +
  • @user49:example.com
    Message #49
  • @user48:example.com
    Message #48
  • @user47:example.com
    Message #47
  • @user46:example.com
    Message #46
  • @user45:example.com
    Message #45
  • @user44:example.com
    Message #44
  • @user43:example.com
    Message #43
  • @user42:example.com
    Message #42
  • @user41:example.com
    Message #41
  • @user40:example.com
    Message #40
  • @user39:example.com
    Message #39
  • @user38:example.com
    Message #38
  • @user37:example.com
    Message #37
  • @user36:example.com
    Message #36
  • @user35:example.com
    Message #35
  • @user34:example.com
    Message #34
  • @user33:example.com
    Message #33
  • @user32:example.com
    Message #32
  • @user31:example.com
    Message #31
  • @user30:example.com
    Message #30
  • @user29:example.com
    Message #29
  • @user28:example.com
    Message #28
  • @user27:example.com
    Message #27
  • @user26:example.com
    Message #26
  • @user25:example.com
    Message #25
  • @user24:example.com
    Message #24
  • @user23:example.com
    Message #23
  • @user22:example.com
    Message #22
  • @user21:example.com
    Message #21
  • @user20:example.com
    Message #20
  • @user19:example.com
    Message #19
  • @user18:example.com
    Message #18
  • @user17:example.com
    Message #17
  • @user16:example.com
    Message #16
  • @user15:example.com
    Message #15
  • @user14:example.com
    Message #14
  • @user13:example.com
    Message #13
  • @user12:example.com
    Message #12
  • @user11:example.com
    Message #11
  • @user10:example.com
    Message #10
  • @user9:example.com
    Message #9
  • @user8:example.com
    Message #8
  • @user7:example.com
    Message #7
  • @user6:example.com
    Message #6
  • @user5:example.com
    Message #5
  • @user4:example.com
    Message #4
  • @user3:example.com
    Message #3
  • @user2:example.com
    Message #2
  • @user1:example.com
    Message #1
  • @user0:example.com
    Message #0
  • diff --git a/linked-dependencies/matrix-react-sdk/test/utils/local-room-test.ts b/linked-dependencies/matrix-react-sdk/test/utils/local-room-test.ts index 7aadef65a9..593a045d88 100644 --- a/linked-dependencies/matrix-react-sdk/test/utils/local-room-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/utils/local-room-test.ts @@ -16,6 +16,7 @@ limitations under the License. import { mocked } from "jest-mock"; import { MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { LocalRoom, LocalRoomState, LOCAL_ROOM_ID_PREFIX } from "../../src/models/LocalRoom"; import * as localRoomModule from "../../src/utils/local-room"; @@ -36,7 +37,7 @@ describe("local-room", () => { beforeEach(() => { client = createTestClient(); room1 = new Room("!room1:example.com", client, userId1); - room1.getMyMembership = () => "join"; + room1.getMyMembership = () => KnownMembership.Join; localRoom = new LocalRoom(LOCAL_ROOM_ID_PREFIX + "test", client, "@test:example.com"); mocked(client.getRoom).mockImplementation((roomId: string) => { if (roomId === localRoom.roomId) { diff --git a/linked-dependencies/matrix-react-sdk/test/utils/localRoom/isRoomReady-test.ts b/linked-dependencies/matrix-react-sdk/test/utils/localRoom/isRoomReady-test.ts index e317301e76..8f91553d6e 100644 --- a/linked-dependencies/matrix-react-sdk/test/utils/localRoom/isRoomReady-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/utils/localRoom/isRoomReady-test.ts @@ -16,6 +16,7 @@ limitations under the License. import { mocked } from "jest-mock"; import { EventType, MatrixClient, Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { LocalRoom, LOCAL_ROOM_ID_PREFIX } from "../../../src/models/LocalRoom"; import { DirectoryMember } from "../../../src/utils/direct-messages"; @@ -33,7 +34,7 @@ describe("isRoomReady", () => { beforeEach(() => { client = createTestClient(); room1 = new Room("!room1:example.com", client, userId1); - room1.getMyMembership = () => "join"; + room1.getMyMembership = () => KnownMembership.Join; localRoom = new LocalRoom(LOCAL_ROOM_ID_PREFIX + "test", client, "@test:example.com"); }); @@ -70,8 +71,8 @@ describe("isRoomReady", () => { describe("and all members have been invited or joined", () => { beforeEach(() => { room1.currentState.setStateEvents([ - makeMembershipEvent(room1.roomId, userId1, "join"), - makeMembershipEvent(room1.roomId, userId2, "invite"), + makeMembershipEvent(room1.roomId, userId1, KnownMembership.Join), + makeMembershipEvent(room1.roomId, userId2, KnownMembership.Invite), ]); }); diff --git a/linked-dependencies/matrix-react-sdk/test/utils/membership-test.ts b/linked-dependencies/matrix-react-sdk/test/utils/membership-test.ts index 3561625573..3a44263481 100644 --- a/linked-dependencies/matrix-react-sdk/test/utils/membership-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/utils/membership-test.ts @@ -15,6 +15,7 @@ limitations under the License. */ import { MatrixClient, MatrixEvent, Room, RoomMember, RoomState, RoomStateEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { mocked } from "jest-mock"; import { isKnockDenied, waitForMember } from "../../src/utils/membership"; @@ -31,16 +32,18 @@ describe("isKnockDenied", () => { }); it("checks that the user knock has been denied", () => { - const roomMember = mkRoomMember(room.roomId, userId, "leave", true, { membership: "knock" }); + const roomMember = mkRoomMember(room.roomId, userId, KnownMembership.Leave, true, { + membership: KnownMembership.Knock, + }); jest.spyOn(room, "getMember").mockReturnValue(roomMember); expect(isKnockDenied(room)).toBe(true); }); it.each([ - { membership: "leave", isKicked: false, prevMembership: "invite" }, - { membership: "leave", isKicked: true, prevMembership: "invite" }, - { membership: "leave", isKicked: false, prevMembership: "join" }, - { membership: "leave", isKicked: true, prevMembership: "join" }, + { membership: KnownMembership.Leave, isKicked: false, prevMembership: KnownMembership.Invite }, + { membership: KnownMembership.Leave, isKicked: true, prevMembership: KnownMembership.Invite }, + { membership: KnownMembership.Leave, isKicked: false, prevMembership: KnownMembership.Join }, + { membership: KnownMembership.Leave, isKicked: true, prevMembership: KnownMembership.Join }, ])("checks that the user knock has been not denied", ({ membership, isKicked, prevMembership }) => { const roomMember = mkRoomMember(room.roomId, userId, membership, isKicked, { membership: prevMembership }); jest.spyOn(room, "getMember").mockReturnValue(roomMember); diff --git a/linked-dependencies/matrix-react-sdk/test/utils/notifications-test.ts b/linked-dependencies/matrix-react-sdk/test/utils/notifications-test.ts index 30316dd5e6..6e67ca9b02 100644 --- a/linked-dependencies/matrix-react-sdk/test/utils/notifications-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/utils/notifications-test.ts @@ -26,6 +26,8 @@ import { clearRoomNotification, notificationLevelToIndicator, getThreadNotificationLevel, + getMarkedUnreadState, + setMarkedUnreadState, } from "../../src/utils/notifications"; import SettingsStore from "../../src/settings/SettingsStore"; import { getMockClientWithEventEmitter } from "../test-utils/client"; @@ -135,8 +137,8 @@ describe("notifications", () => { }); }); - it("sends a request even if everything has been read", () => { - clearRoomNotification(room, client); + it("sends a request even if everything has been read", async () => { + await clearRoomNotification(room, client); expect(sendReadReceiptSpy).toHaveBeenCalledWith(message, ReceiptType.Read, true); }); @@ -155,8 +157,8 @@ describe("notifications", () => { sendReceiptsSetting = false; }); - it("should send a private read receipt", () => { - clearRoomNotification(room, client); + it("should send a private read receipt", async () => { + await clearRoomNotification(room, client); expect(sendReadReceiptSpy).toHaveBeenCalledWith(message, ReceiptType.ReadPrivate, true); }); }); @@ -186,7 +188,7 @@ describe("notifications", () => { expect(sendReadReceiptSpy).not.toHaveBeenCalled(); }); - it("sends unthreaded receipt requests", () => { + it("sends unthreaded receipt requests", async () => { const message = mkMessage({ event: true, room: ROOM_ID, @@ -196,12 +198,12 @@ describe("notifications", () => { room.addLiveEvents([message]); room.setUnreadNotificationCount(NotificationCountType.Total, 1); - clearAllNotifications(client); + await clearAllNotifications(client); expect(sendReadReceiptSpy).toHaveBeenCalledWith(message, ReceiptType.Read, true); }); - it("sends private read receipts", () => { + it("sends private read receipts", async () => { const message = mkMessage({ event: true, room: ROOM_ID, @@ -213,12 +215,121 @@ describe("notifications", () => { jest.spyOn(SettingsStore, "getValue").mockReset().mockReturnValue(false); - clearAllNotifications(client); + await clearAllNotifications(client); expect(sendReadReceiptSpy).toHaveBeenCalledWith(message, ReceiptType.ReadPrivate, true); }); }); + describe("getMarkedUnreadState", () => { + let client: MatrixClient; + let room: Room; + + const ROOM_ID = "123"; + const USER_ID = "@bob:example.org"; + + beforeEach(() => { + stubClient(); + client = mocked(MatrixClientPeg.safeGet()); + room = new Room(ROOM_ID, client, USER_ID); + }); + + it("reads from stable prefix", async () => { + room.getAccountData = jest.fn().mockImplementation((eventType: string) => { + if (eventType === "m.marked_unread") { + return { getContent: jest.fn().mockReturnValue({ unread: true }) }; + } + return null; + }); + expect(getMarkedUnreadState(room)).toBe(true); + }); + + it("reads from unstable prefix", async () => { + room.getAccountData = jest.fn().mockImplementation((eventType: string) => { + if (eventType === "com.famedly.marked_unread") { + return { getContent: jest.fn().mockReturnValue({ unread: true }) }; + } + return null; + }); + expect(getMarkedUnreadState(room)).toBe(true); + }); + + it("returns undefined if neither prefix is present", async () => { + room.getAccountData = jest.fn().mockImplementation((eventType: string) => { + return null; + }); + expect(getMarkedUnreadState(room)).toBe(undefined); + }); + }); + + describe("setUnreadMarker", () => { + let client: MatrixClient; + let room: Room; + + const ROOM_ID = "123"; + const USER_ID = "@bob:example.org"; + + beforeEach(() => { + stubClient(); + client = mocked(MatrixClientPeg.safeGet()); + room = new Room(ROOM_ID, client, USER_ID); + }); + + // set true, no existing event + it("sets unread flag if event doesn't exist", async () => { + await setMarkedUnreadState(room, client, true); + expect(client.setRoomAccountData).toHaveBeenCalledWith(ROOM_ID, "com.famedly.marked_unread", { + unread: true, + }); + }); + + // set false, no existing event + it("does nothing when clearing if flag is false", async () => { + await setMarkedUnreadState(room, client, false); + expect(client.setRoomAccountData).not.toHaveBeenCalled(); + }); + + // set true, existing event = false + it("sets unread flag to if existing event is false", async () => { + room.getAccountData = jest + .fn() + .mockReturnValue({ getContent: jest.fn().mockReturnValue({ unread: false }) }); + await setMarkedUnreadState(room, client, true); + expect(client.setRoomAccountData).toHaveBeenCalledWith(ROOM_ID, "com.famedly.marked_unread", { + unread: true, + }); + }); + + // set false, existing event = false + it("does nothing if set false and existing event is false", async () => { + room.getAccountData = jest + .fn() + .mockReturnValue({ getContent: jest.fn().mockReturnValue({ unread: false }) }); + await setMarkedUnreadState(room, client, false); + expect(client.setRoomAccountData).not.toHaveBeenCalled(); + }); + + // set true, existing event = true + it("does nothing if setting true and existing event is true", async () => { + room.getAccountData = jest + .fn() + .mockReturnValue({ getContent: jest.fn().mockReturnValue({ unread: true }) }); + await setMarkedUnreadState(room, client, true); + expect(client.setRoomAccountData).not.toHaveBeenCalled(); + }); + + // set false, existing event = true + it("sets flag if setting false and existing event is true", async () => { + room.getAccountData = jest + .fn() + .mockReturnValue({ getContent: jest.fn().mockReturnValue({ unread: true }) }); + await setMarkedUnreadState(room, client, false); + expect(client.setRoomAccountData).toHaveBeenCalledWith(ROOM_ID, "com.famedly.marked_unread", { + unread: false, + }); + }); + }); + describe("notificationLevelToIndicator", () => { it("returns undefined if notification level is None", () => { expect(notificationLevelToIndicator(NotificationLevel.None)).toBeUndefined(); diff --git a/linked-dependencies/matrix-react-sdk/test/utils/permalinks/Permalinks-test.ts b/linked-dependencies/matrix-react-sdk/test/utils/permalinks/Permalinks-test.ts index 8e85aac02c..3c3bbbbec9 100644 --- a/linked-dependencies/matrix-react-sdk/test/utils/permalinks/Permalinks-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/utils/permalinks/Permalinks-test.ts @@ -15,6 +15,7 @@ limitations under the License. import { EventEmitter } from "events"; import { Room, RoomMember, EventType, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; import { PermalinkParts } from "../../../src/utils/permalinks/PermalinkConstructor"; @@ -45,7 +46,7 @@ describe("Permalinks", function () { members: RoomMember[], serverACLContent?: { deny?: string[]; allow?: string[] }, ): Room { - members.forEach((m) => (m.membership = "join")); + members.forEach((m) => (m.membership = KnownMembership.Join)); const powerLevelsUsers = members.reduce>((pl, member) => { if (Number.isFinite(member.powerLevel)) { pl[member.userId] = member.powerLevel; @@ -152,11 +153,11 @@ describe("Permalinks", function () { const creator = new RoomPermalinkCreator(room, null); creator.load(); expect(creator.serverCandidates![0]).toBe("pl_95"); - member95.membership = "left"; + member95.membership = KnownMembership.Leave; // @ts-ignore illegal private property creator.onRoomStateUpdate(); expect(creator.serverCandidates![0]).toBe("pl_75"); - member95.membership = "join"; + member95.membership = KnownMembership.Join; // @ts-ignore illegal private property creator.onRoomStateUpdate(); expect(creator.serverCandidates![0]).toBe("pl_95"); diff --git a/linked-dependencies/matrix-react-sdk/test/utils/pillify-test.tsx b/linked-dependencies/matrix-react-sdk/test/utils/pillify-test.tsx index c5a00a6828..4c393ba458 100644 --- a/linked-dependencies/matrix-react-sdk/test/utils/pillify-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/utils/pillify-test.tsx @@ -17,6 +17,7 @@ limitations under the License. import React from "react"; import { render } from "@testing-library/react"; import { MatrixEvent, ConditionKind, EventType, PushRuleActionName, Room, TweakName } from "matrix-js-sdk/src/matrix"; +import { mocked } from "jest-mock"; import { pillifyLinks } from "../../src/utils/pillify"; import { stubClient } from "../test-utils"; @@ -36,7 +37,9 @@ describe("pillify", () => { beforeEach(() => { stubClient(); const cli = MatrixClientPeg.safeGet(); - (cli.getRoom as jest.Mock).mockReturnValue(new Room(roomId, cli, cli.getUserId()!)); + const room = new Room(roomId, cli, cli.getUserId()!); + room.currentState.mayTriggerNotifOfType = jest.fn().mockReturnValue(true); + (cli.getRoom as jest.Mock).mockReturnValue(room); cli.pushRules!.global = { override: [ { @@ -58,6 +61,28 @@ describe("pillify", () => { }, ], }, + { + rule_id: ".m.rule.is_room_mention", + default: true, + enabled: true, + conditions: [ + { + kind: ConditionKind.EventPropertyIs, + key: "content.m\\.mentions.room", + value: true, + }, + { + kind: ConditionKind.SenderNotificationPermission, + key: "room", + }, + ], + actions: [ + PushRuleActionName.Notify, + { + set_tweak: TweakName.Highlight, + }, + ], + }, ], }; @@ -81,6 +106,29 @@ describe("pillify", () => { expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room"); }); + it("should pillify @room in an intentional mentions world", () => { + mocked(MatrixClientPeg.safeGet().supportsIntentionalMentions).mockReturnValue(true); + const { container } = render(
    @room
    ); + const containers: Element[] = []; + pillifyLinks( + MatrixClientPeg.safeGet(), + [container], + new MatrixEvent({ + room_id: roomId, + type: EventType.RoomMessage, + content: { + "body": "@room", + "m.mentions": { + room: true, + }, + }, + }), + containers, + ); + expect(containers).toHaveLength(1); + expect(container.querySelector(".mx_Pill.mx_AtRoomPill")?.textContent).toBe("!@room"); + }); + it("should not double up pillification on repeated calls", () => { const { container } = render(
    @room
    ); const containers: Element[] = []; diff --git a/linked-dependencies/matrix-react-sdk/test/utils/room/canInviteTo-test.ts b/linked-dependencies/matrix-react-sdk/test/utils/room/canInviteTo-test.ts index c35202912e..2ee0ca87af 100644 --- a/linked-dependencies/matrix-react-sdk/test/utils/room/canInviteTo-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/utils/room/canInviteTo-test.ts @@ -16,6 +16,7 @@ limitations under the License. import { mocked } from "jest-mock"; import { JoinRule, Room } from "matrix-js-sdk/src/matrix"; +import { KnownMembership } from "matrix-js-sdk/src/types"; import { shouldShowComponent } from "../../../src/customisations/helpers/UIComponents"; import { UIComponent } from "../../../src/settings/UIFeature"; @@ -39,7 +40,7 @@ describe("canInviteTo()", () => { ...mockClientMethodsUser(userId), }); const room = new Room(roomId, client, userId); - jest.spyOn(room, "getMyMembership").mockReturnValue("join"); + jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Join); jest.spyOn(room, "getJoinRule").mockReturnValue(JoinRule.Public); jest.spyOn(room, "canInvite").mockReturnValue(true); return room; @@ -54,7 +55,7 @@ describe("canInviteTo()", () => { it("should return false when current user membership is not joined", () => { const room = makeRoom(); - jest.spyOn(room, "getMyMembership").mockReturnValue("invite"); + jest.spyOn(room, "getMyMembership").mockReturnValue(KnownMembership.Invite); expect(canInviteTo(room)).toEqual(false); }); diff --git a/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastPlayback-test.tsx b/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastPlayback-test.tsx index 1c7e6b66c1..85f14fbfa2 100644 --- a/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastPlayback-test.tsx +++ b/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastPlayback-test.tsx @@ -454,7 +454,7 @@ describe("VoiceBroadcastPlayback", () => { describe("and the info event is deleted", () => { beforeEach(() => { - infoEvent.makeRedacted(new MatrixEvent({})); + infoEvent.makeRedacted(new MatrixEvent({}), room); }); it("should stop and destroy the playback", () => { diff --git a/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastRecording-test.ts b/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastRecording-test.ts index 896e1b303a..1298b1ff49 100644 --- a/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastRecording-test.ts +++ b/linked-dependencies/matrix-react-sdk/test/voice-broadcast/models/VoiceBroadcastRecording-test.ts @@ -29,9 +29,9 @@ import { Relations, SyncState, } from "matrix-js-sdk/src/matrix"; +import { EncryptedFile } from "matrix-js-sdk/src/types"; import { uploadFile } from "../../../src/ContentMessages"; -import { EncryptedFile } from "../../../src/customisations/models/IMediaEventContent"; import { createVoiceMessageContent } from "../../../src/utils/createVoiceMessageContent"; import { createVoiceBroadcastRecorder, diff --git a/linked-dependencies/matrix-react-sdk/yarn.lock b/linked-dependencies/matrix-react-sdk/yarn.lock index 067b410abe..ba6d734737 100644 --- a/linked-dependencies/matrix-react-sdk/yarn.lock +++ b/linked-dependencies/matrix-react-sdk/yarn.lock @@ -7,17 +7,17 @@ resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== -"@action-validator/cli@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@action-validator/cli/-/cli-0.5.4.tgz#44b41881f717753e4fec247aaf73a99c88481e32" - integrity sha512-Puj/f8E8OzPCmDDkVslU+hvTwxM+VL9GOqmuEpdwp4E2Ufsni0lJMNvkHMBc3Da13WwGG49ydOvGVTpMT5H+7A== +"@action-validator/cli@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@action-validator/cli/-/cli-0.6.0.tgz#02a29e322d3794903896183281eed2b55c685851" + integrity sha512-Z8TYOK4GqUIpI0UuspUJPB6dhr0niTumhwI5iiZVqFRXm4u05bZawnFKltpvoFUfJg9mHbbIBlleqsRJAgl53Q== dependencies: chalk "5.2.0" -"@action-validator/core@^0.5.3": - version "0.5.4" - resolved "https://registry.yarnpkg.com/@action-validator/core/-/core-0.5.4.tgz#160a6d9ac8919a1eed0a0b0a7780b82ef03686fe" - integrity sha512-uODXaU5sJw9CilmjVG9IUpc1ENivixQI7+DtebWgG80PMQBfZ/4b5PKXJ5ESJVlvafrHcuIjN0qou99zN2bDtw== +"@action-validator/core@^0.6.0": + version "0.6.0" + resolved "https://registry.yarnpkg.com/@action-validator/core/-/core-0.6.0.tgz#8fbaf45562a5377140815b79cc1ac9f610ff63e5" + integrity sha512-tPglwCr8Mm8SWzwnVewwFmqRx91F0WvMsM0BRAqH4CLalyGndm53Xvp+UcUSzswpk1wkjIDYI7RyEhWMLyPkig== "@adobe/css-tools@^4.3.2": version "4.3.3" @@ -25,12 +25,12 @@ integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ== "@ampproject/remapping@^2.2.0": - version "2.2.1" - resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" - integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== dependencies: - "@jridgewell/gen-mapping" "^0.3.0" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" "@axe-core/playwright@^4.8.1": version "4.8.5" @@ -40,11 +40,11 @@ axe-core "~4.8.4" "@babel/cli@^7.12.10": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.23.9.tgz#06b3e76376ee53f14ac8ac422c884950c69e1b9e" - integrity sha512-vB1UXmGDNEhcf1jNAHKT9IlYk1R+hehVTLFlCLHBi8gfuHQGP6uRjgXVYU0EVlI/qwAWpstqkBdf2aez3/z/5Q== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/cli/-/cli-7.24.1.tgz#2e11e071e32fe82850b4fe514f56b9c9e1c44911" + integrity sha512-HbmrtxyFUr34LwAlV9jS+sSIjUp4FpdtIMGwgufY3AsxrIfsh/HxlMTywsONAZsU0RMYbZtbZFpUCrSGs7o0EA== dependencies: - "@jridgewell/trace-mapping" "^0.3.17" + "@jridgewell/trace-mapping" "^0.3.25" commander "^4.0.1" convert-source-map "^2.0.0" fs-readdir-recursive "^1.1.0" @@ -55,7 +55,15 @@ "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.23.5": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.23.5", "@babel/code-frame@^7.24.1", "@babel/code-frame@^7.24.2": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" + integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== + dependencies: + "@babel/highlight" "^7.24.2" + picocolors "^1.0.0" + +"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.13": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== @@ -76,26 +84,26 @@ resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.21.7.tgz#61caffb60776e49a57ba61a88f02bedd8714f6bc" integrity sha512-KYMqFYTaenzMK4yUtf4EW9wc4N9ef80FsbMtkwool5zpwl4YrT1SdWYSTRcT94KO4hannogdS+LxY7L+arP3gA== -"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.3", "@babel/compat-data@^7.23.5": - version "7.23.5" - resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.23.5.tgz#ffb878728bb6bdcb6f4510aa51b1be9afb8cfd98" - integrity sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw== +"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.1.tgz#31c1f66435f2a9c329bb5716a6d6186c516c3742" + integrity sha512-Pc65opHDliVpRHuKfzI+gSA4zcgr65O4cl64fFJIWEEh8JoHIHh0Oez1Eo8Arz8zq/JhgKodQaxEwUPRtZylVA== "@babel/core@^7.0.0", "@babel/core@^7.12.10": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.23.9.tgz#b028820718000f267870822fec434820e9b1e4d1" - integrity sha512-5q0175NOjddqpvvzU+kDiSOAk4PfdO6FvwCWoQ6RO7rTzEe8vlo+4HVfcnAREhD4npMs0e9uZypjTwzZPCf/cw== + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.24.3.tgz#568864247ea10fbd4eff04dda1e05f9e2ea985c3" + integrity sha512-5FcvN1JHw2sHJChotgx8Ek0lyuh4kCKelgMTTqhYJJtloNvUfpAFMeNQUtdlIaktwrSV9LtCdqwk48wL2wBacQ== dependencies: "@ampproject/remapping" "^2.2.0" - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" + "@babel/code-frame" "^7.24.2" + "@babel/generator" "^7.24.1" "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-module-transforms" "^7.23.3" - "@babel/helpers" "^7.23.9" - "@babel/parser" "^7.23.9" - "@babel/template" "^7.23.9" - "@babel/traverse" "^7.23.9" - "@babel/types" "^7.23.9" + "@babel/helpers" "^7.24.1" + "@babel/parser" "^7.24.1" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" convert-source-map "^2.0.0" debug "^4.1.0" gensync "^1.0.0-beta.2" @@ -124,9 +132,9 @@ semver "^6.3.1" "@babel/eslint-parser@^7.12.10": - version "7.23.10" - resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.23.10.tgz#2d4164842d6db798873b40e0c4238827084667a2" - integrity sha512-3wSYDPZVnhseRnxRJH6ZVTNknBz76AEnyC+AYYhasjP3Yy23qz0ERR7Fcd2SHmYuSFJ2kY9gaaDd3vyqU09eSw== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/eslint-parser/-/eslint-parser-7.24.1.tgz#e27eee93ed1d271637165ef3a86e2b9332395c32" + integrity sha512-d5guuzMlPeDfZIbpQ8+g1NaCNuAGBBGNECh0HVqz1sjOeVLh2CEaifuOysCH18URW6R7pqXINvf5PaR/dC6jLQ== dependencies: "@nicolo-ribaudo/eslint-scope-5-internals" "5.1.1-v1" eslint-visitor-keys "^2.1.0" @@ -159,14 +167,14 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/generator@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" - integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== +"@babel/generator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.1.tgz#e67e06f68568a4ebf194d1c6014235344f0476d0" + integrity sha512-DfCRfZsBcrPEHUfuBMgbJ1Ut01Y/itOs+hY2nFLgqsqXd52/iSiVq5TITtUasIUgm+IIKdY2/1I7auiQOEeC9A== dependencies: - "@babel/types" "^7.23.6" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" + "@babel/types" "^7.24.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" jsesc "^2.5.1" "@babel/helper-annotate-as-pure@^7.18.6", "@babel/helper-annotate-as-pure@^7.22.5": @@ -220,17 +228,17 @@ "@babel/helper-split-export-declaration" "^7.18.6" semver "^6.3.0" -"@babel/helper-create-class-features-plugin@^7.22.15": - version "7.23.10" - resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.23.10.tgz#25d55fafbaea31fd0e723820bb6cc3df72edf7ea" - integrity sha512-2XpP2XhkXzgxecPNEEK8Vz8Asj9aRxt08oKOqtiZoqV2UGZ5T+EkyP9sXQ9nwMxBIG34a7jmasVqoMop7VdPUw== +"@babel/helper-create-class-features-plugin@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.1.tgz#db58bf57137b623b916e24874ab7188d93d7f68f" + integrity sha512-1yJa9dX9g//V6fDebXoEfEsxkZHk3Hcbm+zLhyu6qVgYFLvmTALTeV+jNU9e5RnYtioBrGEOdoI2joMSNQ/+aA== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-function-name" "^7.23.0" "@babel/helper-member-expression-to-functions" "^7.23.0" "@babel/helper-optimise-call-expression" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-replace-supers" "^7.24.1" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" semver "^6.3.1" @@ -244,10 +252,10 @@ regexpu-core "^5.3.1" semver "^6.3.1" -"@babel/helper-define-polyfill-provider@^0.5.0": - version "0.5.0" - resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.5.0.tgz#465805b7361f461e86c680f1de21eaf88c25901b" - integrity sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q== +"@babel/helper-define-polyfill-provider@^0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.1.tgz#fadc63f0c2ff3c8d02ed905dcea747c5b0fb74fd" + integrity sha512-o7SDgTJuvx5vLKD6SFvkydkSMBvahDKGiNJzG22IZYXhiqoe9efY7zocICBgzHV4IRg5wdgl2nEL/tulKIEIbA== dependencies: "@babel/helper-compilation-targets" "^7.22.6" "@babel/helper-plugin-utils" "^7.22.5" @@ -282,19 +290,19 @@ dependencies: "@babel/types" "^7.21.5" -"@babel/helper-member-expression-to-functions@^7.22.15", "@babel/helper-member-expression-to-functions@^7.23.0": +"@babel/helper-member-expression-to-functions@^7.23.0": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz#9263e88cc5e41d39ec18c9a3e0eced59a3e7d366" integrity sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA== dependencies: "@babel/types" "^7.23.0" -"@babel/helper-module-imports@^7.22.15": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz#16146307acdc40cc00c3b2c647713076464bdbf0" - integrity sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w== +"@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3": + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128" + integrity sha512-viKb0F9f2s0BCS22QSF308z/+1YWKV/76mwt61NBzS5izMzDPwdq1pTrzf+Li3npBWX9KdQbkeCt1jSAM7lZqg== dependencies: - "@babel/types" "^7.22.15" + "@babel/types" "^7.24.0" "@babel/helper-module-transforms@^7.22.20": version "7.22.20" @@ -332,7 +340,12 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.20.2", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": +"@babel/helper-plugin-utils@^7.0.0", "@babel/helper-plugin-utils@^7.10.4", "@babel/helper-plugin-utils@^7.12.13", "@babel/helper-plugin-utils@^7.14.5", "@babel/helper-plugin-utils@^7.18.6", "@babel/helper-plugin-utils@^7.22.5", "@babel/helper-plugin-utils@^7.24.0", "@babel/helper-plugin-utils@^7.8.0", "@babel/helper-plugin-utils@^7.8.3": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.0.tgz#945681931a52f15ce879fd5b86ce2dae6d3d7f2a" + integrity sha512-9cUznXMG0+FxRuJfvL82QlTqIzhVW9sL0KjMPHhAOOvpQGL8QtdxnBKILjBqxlHyliz0yCa1G903ZXI/FuHy2w== + +"@babel/helper-plugin-utils@^7.20.2": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz#dd7ee3735e8a313b9f7b05a773d892e88e6d7295" integrity sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg== @@ -358,13 +371,13 @@ "@babel/traverse" "^7.21.5" "@babel/types" "^7.21.5" -"@babel/helper-replace-supers@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz#e37d367123ca98fe455a9887734ed2e16eb7a793" - integrity sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw== +"@babel/helper-replace-supers@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-replace-supers/-/helper-replace-supers-7.24.1.tgz#7085bd19d4a0b7ed8f405c1ed73ccb70f323abc1" + integrity sha512-QCR1UqC9BzG5vZl8BMicmZ28RuUBnHhAMddD8yHFHDRH9lLTZ9uUPehX8ctVPT8l0TKblJidqcgUUKGVrePleQ== dependencies: "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-member-expression-to-functions" "^7.22.15" + "@babel/helper-member-expression-to-functions" "^7.23.0" "@babel/helper-optimise-call-expression" "^7.22.5" "@babel/helper-simple-access@^7.22.5": @@ -395,11 +408,16 @@ dependencies: "@babel/types" "^7.22.5" -"@babel/helper-string-parser@^7.22.5", "@babel/helper-string-parser@^7.23.4": +"@babel/helper-string-parser@^7.22.5": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== +"@babel/helper-string-parser@^7.23.4": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e" + integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ== + "@babel/helper-validator-identifier@^7.22.20": version "7.22.20" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" @@ -410,7 +428,7 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.21.0.tgz#8224c7e13ace4bafdc4004da2cf064ef42673180" integrity sha512-rmL/B8/f0mKS2baE9ZpyTcTavvEuWhTTW8amjzXNvYG4AwBsqTLikfXsEofsJEfKHf+HQVQbFOHy6o+4cnC/fQ== -"@babel/helper-validator-option@^7.22.15", "@babel/helper-validator-option@^7.23.5": +"@babel/helper-validator-option@^7.23.5": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307" integrity sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw== @@ -433,16 +451,16 @@ "@babel/traverse" "^7.22.15" "@babel/types" "^7.22.15" -"@babel/helpers@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.23.9.tgz#c3e20bbe7f7a7e10cb9b178384b4affdf5995c7d" - integrity sha512-87ICKgU5t5SzOT7sBMfCOZQ2rHjRU+Pcb9BoILMYz600W6DkVRLFBPwQ18gwUVvggqXivaUakpnxWQGbpywbBQ== +"@babel/helpers@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.24.1.tgz#183e44714b9eba36c3038e442516587b1e0a1a94" + integrity sha512-BpU09QqEe6ZCHuIHFphEFgvNSrubve1FtyMton26ekZ85gRGi6LrTF7zArARp2YvyFxloeiRmtSCq5sjh1WqIg== dependencies: - "@babel/template" "^7.23.9" - "@babel/traverse" "^7.23.9" - "@babel/types" "^7.23.9" + "@babel/template" "^7.24.0" + "@babel/traverse" "^7.24.1" + "@babel/types" "^7.24.0" -"@babel/highlight@^7.22.13", "@babel/highlight@^7.23.4": +"@babel/highlight@^7.22.13": version "7.23.4" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== @@ -451,34 +469,44 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.14.7", "@babel/parser@^7.18.5", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16", "@babel/parser@^7.23.3", "@babel/parser@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" - integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== +"@babel/highlight@^7.23.4", "@babel/highlight@^7.24.2": + version "7.24.2" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" + integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + picocolors "^1.0.0" -"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.23.3.tgz#5cd1c87ba9380d0afb78469292c954fee5d2411a" - integrity sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ== +"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.14.7", "@babel/parser@^7.18.5", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16", "@babel/parser@^7.23.3", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.1.tgz#1e416d3627393fab1cb5b0f2f1796a100ae9133a" + integrity sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg== + +"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.24.1.tgz#b645d9ba8c2bc5b7af50f0fe949f9edbeb07c8cf" + integrity sha512-y4HqEnkelJIOQGd+3g1bTeKsA5c6qM7eOn7VggGVbBc0y8MLSKHacwcIE2PplNlQSj0PqS9rrXL/nkPVK+kUNg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.23.3.tgz#f6652bb16b94f8f9c20c50941e16e9756898dc5d" - integrity sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ== +"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.1.tgz#da8261f2697f0f41b0855b91d3a20a1fbfd271d3" + integrity sha512-Hj791Ii4ci8HqnaKHAlLNs+zaLXb0EzSDhiAWp5VNlyvCNymYfacs64pxTxbH1znW/NcArSmwpmG9IKE/TUVVQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" - "@babel/plugin-transform-optional-chaining" "^7.23.3" + "@babel/plugin-transform-optional-chaining" "^7.24.1" -"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.23.7": - version "7.23.7" - resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.23.7.tgz#516462a95d10a9618f197d39ad291a9b47ae1d7b" - integrity sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw== +"@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.24.1.tgz#1181d9685984c91d657b8ddf14f0487a6bab2988" + integrity sha512-m9m/fXsXLiHfwdgydIFnpk+7jlVbnvlK5B2EKiPdLUb6WX654ZaaEWJUjk8TftRbZpK0XibovlLWX4KIZhV6jw== dependencies: "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-proposal-class-properties@^7.12.1": version "7.18.6" @@ -489,12 +517,12 @@ "@babel/helper-plugin-utils" "^7.18.6" "@babel/plugin-proposal-export-default-from@^7.12.1": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.23.3.tgz#6f511a676c540ccc8d17a8553dbba9230b0ddac0" - integrity sha512-Q23MpLZfSGZL1kU7fWqV262q65svLSCIP5kZ/JCW/rKTCm/FrLjpvEd2kfUYMVeHh4QhV/xzyoRAHWrAZJrE3Q== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-default-from/-/plugin-proposal-export-default-from-7.24.1.tgz#d242019488277c9a5a8035e5b70de54402644b89" + integrity sha512-+0hrgGGV3xyYIjOrD/bUZk/iUwOIGuoANfRfVg1cPhYBxF+TIXSEcc42DqzBICmWsnAQ+SfKedY0bj8QD+LuMg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-export-default-from" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-export-default-from" "^7.24.1" "@babel/plugin-proposal-numeric-separator@^7.12.7": version "7.18.6" @@ -555,12 +583,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-export-default-from@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.23.3.tgz#7e6d4bf595d5724230200fb2b7401d4734b15335" - integrity sha512-KeENO5ck1IeZ/l2lFZNy+mpobV3D2Zy5C1YFnWm+YuY5mQiAWc4yAp13dqgguwsBsFVLh4LPCEqCa5qW13N+hw== +"@babel/plugin-syntax-export-default-from@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-default-from/-/plugin-syntax-export-default-from-7.24.1.tgz#a92852e694910ae4295e6e51e87b83507ed5e6e8" + integrity sha512-cNXSxv9eTkGUtd0PsNMK8Yx5xeScxfpWOUAxE+ZPAXXEcAMOC3fk7LRdXq5fvpra2pLx2p1YtkAhpUbB2SwaRA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-export-namespace-from@^7.8.3": version "7.8.3" @@ -569,19 +597,19 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.3" -"@babel/plugin-syntax-import-assertions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.23.3.tgz#9c05a7f592982aff1a2768260ad84bcd3f0c77fc" - integrity sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw== +"@babel/plugin-syntax-import-assertions@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.1.tgz#db3aad724153a00eaac115a3fb898de544e34971" + integrity sha512-IuwnI5XnuF189t91XbxmXeCDz3qs6iDRO7GJ++wcfgeXNs/8FmIlKcpDSXNVyuLQxlwvskmI3Ct73wUODkJBlQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-syntax-import-attributes@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.23.3.tgz#992aee922cf04512461d7dae3ff6951b90a2dc06" - integrity sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA== +"@babel/plugin-syntax-import-attributes@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.24.1.tgz#c66b966c63b714c4eec508fcf5763b1f2d381093" + integrity sha512-zhQTMH0X2nVLnb04tz+s7AMuasX8U0FnpE+nHTOhSOINjWMnopoZTxtIKsd45n4GQ/HIZLyfIpoul8e2m0DnRA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-import-meta@^7.10.4", "@babel/plugin-syntax-import-meta@^7.8.3": version "7.10.4" @@ -597,12 +625,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.8.0" -"@babel/plugin-syntax-jsx@^7.22.5", "@babel/plugin-syntax-jsx@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.23.3.tgz#8f2e4f8a9b5f9aa16067e142c1ac9cd9f810f473" - integrity sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg== +"@babel/plugin-syntax-jsx@^7.23.3", "@babel/plugin-syntax-jsx@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.1.tgz#3f6ca04b8c841811dbc3c5c5f837934e0d626c10" + integrity sha512-2eCtxZXf+kbkMIsXS4poTvT4Yu5rXiRa+9xGVT56raghjmBTKMpFNc9R4IDiB4emao9eO22Ox7CxuJG7BgExqA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-jsx@^7.7.2": version "7.22.5" @@ -667,12 +695,12 @@ dependencies: "@babel/helper-plugin-utils" "^7.14.5" -"@babel/plugin-syntax-typescript@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.23.3.tgz#24f460c85dbbc983cd2b9c4994178bcc01df958f" - integrity sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ== +"@babel/plugin-syntax-typescript@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.24.1.tgz#b3bcc51f396d15f3591683f90239de143c076844" + integrity sha512-Yhnmvy5HZEnHUty6i++gcfH1/l68AHnItFHnaCv6hn9dNh0hQvvQJsxpi4BMBFN5DLeHBuucT/0DgzXif/OyRw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-typescript@^7.7.2": version "7.22.5" @@ -689,212 +717,212 @@ "@babel/helper-create-regexp-features-plugin" "^7.18.6" "@babel/helper-plugin-utils" "^7.18.6" -"@babel/plugin-transform-arrow-functions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.23.3.tgz#94c6dcfd731af90f27a79509f9ab7fb2120fc38b" - integrity sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ== +"@babel/plugin-transform-arrow-functions@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.1.tgz#2bf263617060c9cc45bcdbf492b8cc805082bf27" + integrity sha512-ngT/3NkRhsaep9ck9uj2Xhv9+xB1zShY3tM3g6om4xxCELwCDN4g4Aq5dRn48+0hasAql7s2hdBOysCfNpr4fw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-async-generator-functions@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.23.9.tgz#9adaeb66fc9634a586c5df139c6240d41ed801ce" - integrity sha512-8Q3veQEDGe14dTYuwagbRtwxQDnytyg1JFu4/HwEMETeofocrB0U0ejBJIXoeG/t2oXZ8kzCyI0ZZfbT80VFNQ== +"@babel/plugin-transform-async-generator-functions@^7.24.3": + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.24.3.tgz#8fa7ae481b100768cc9842c8617808c5352b8b89" + integrity sha512-Qe26CMYVjpQxJ8zxM1340JFNjZaF+ISWpr1Kt/jGo+ZTUzKkfw/pphEWbRCb+lmSM6k/TOgfYLvmbHkUQ0asIg== dependencies: "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-remap-async-to-generator" "^7.22.20" "@babel/plugin-syntax-async-generators" "^7.8.4" -"@babel/plugin-transform-async-to-generator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.23.3.tgz#d1f513c7a8a506d43f47df2bf25f9254b0b051fa" - integrity sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw== +"@babel/plugin-transform-async-to-generator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.1.tgz#0e220703b89f2216800ce7b1c53cb0cf521c37f4" + integrity sha512-AawPptitRXp1y0n4ilKcGbRYWfbbzFWz2NqNu7dacYDtFtz0CMjG64b3LQsb3KIgnf4/obcUL78hfaOS7iCUfw== dependencies: - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-module-imports" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-remap-async-to-generator" "^7.22.20" -"@babel/plugin-transform-block-scoped-functions@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.23.3.tgz#fe1177d715fb569663095e04f3598525d98e8c77" - integrity sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A== +"@babel/plugin-transform-block-scoped-functions@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.1.tgz#1c94799e20fcd5c4d4589523bbc57b7692979380" + integrity sha512-TWWC18OShZutrv9C6mye1xwtam+uNi2bnTOCBUd5sZxyHOiWbU6ztSROofIMrK84uweEZC219POICK/sTYwfgg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-block-scoping@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.4.tgz#b2d38589531c6c80fbe25e6b58e763622d2d3cf5" - integrity sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw== +"@babel/plugin-transform-block-scoping@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.1.tgz#27af183d7f6dad890531256c7a45019df768ac1f" + integrity sha512-h71T2QQvDgM2SmT29UYU6ozjMlAt7s7CSs5Hvy8f8cf/GM/Z4a2zMfN+fjVGaieeCrXR3EdQl6C4gQG+OgmbKw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-class-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.23.3.tgz#35c377db11ca92a785a718b6aa4e3ed1eb65dc48" - integrity sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg== +"@babel/plugin-transform-class-properties@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.24.1.tgz#bcbf1aef6ba6085cfddec9fc8d58871cf011fc29" + integrity sha512-OMLCXi0NqvJfORTaPQBwqLXHhb93wkBKZ4aNwMl6WtehO7ar+cmp+89iPEQPqxAnxsOKTaMcs3POz3rKayJ72g== dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-class-static-block@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.23.4.tgz#2a202c8787a8964dd11dfcedf994d36bfc844ab5" - integrity sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ== +"@babel/plugin-transform-class-static-block@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.1.tgz#4e37efcca1d9f2fcb908d1bae8b56b4b6e9e1cb6" + integrity sha512-FUHlKCn6J3ERiu8Dv+4eoz7w8+kFLSyeVG4vDAikwADGjUCoHw/JHokyGtr8OR4UjpwPVivyF+h8Q5iv/JmrtA== dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-class-static-block" "^7.14.5" -"@babel/plugin-transform-classes@^7.23.8": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.23.8.tgz#d08ae096c240347badd68cdf1b6d1624a6435d92" - integrity sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg== +"@babel/plugin-transform-classes@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.1.tgz#5bc8fc160ed96378184bc10042af47f50884dcb1" + integrity sha512-ZTIe3W7UejJd3/3R4p7ScyyOoafetUShSf4kCqV0O7F/RiHxVj/wRaRnQlrGwflvcehNA8M42HkAiEDYZu2F1Q== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-replace-supers" "^7.24.1" "@babel/helper-split-export-declaration" "^7.22.6" globals "^11.1.0" -"@babel/plugin-transform-computed-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.23.3.tgz#652e69561fcc9d2b50ba4f7ac7f60dcf65e86474" - integrity sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw== +"@babel/plugin-transform-computed-properties@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.1.tgz#bc7e787f8e021eccfb677af5f13c29a9934ed8a7" + integrity sha512-5pJGVIUfJpOS+pAqBQd+QMaTD2vCL/HcePooON6pDpHgRp4gNRmzyHTPIkXntwKsq3ayUFVfJaIKPw2pOkOcTw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/template" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/template" "^7.24.0" -"@babel/plugin-transform-destructuring@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.3.tgz#8c9ee68228b12ae3dff986e56ed1ba4f3c446311" - integrity sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw== +"@babel/plugin-transform-destructuring@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.1.tgz#b1e8243af4a0206841973786292b8c8dd8447345" + integrity sha512-ow8jciWqNxR3RYbSNVuF4U2Jx130nwnBnhRw6N6h1bOejNkABmcI5X5oz29K4alWX7vf1C+o6gtKXikzRKkVdw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-dotall-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.23.3.tgz#3f7af6054882ede89c378d0cf889b854a993da50" - integrity sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ== +"@babel/plugin-transform-dotall-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.1.tgz#d56913d2f12795cc9930801b84c6f8c47513ac13" + integrity sha512-p7uUxgSoZwZ2lPNMzUkqCts3xlp8n+o05ikjy7gbtFJSt9gdU88jAmtfmOxHM14noQXBxfgzf2yRWECiNVhTCw== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-duplicate-keys@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.23.3.tgz#664706ca0a5dfe8d066537f99032fc1dc8b720ce" - integrity sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA== +"@babel/plugin-transform-duplicate-keys@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.1.tgz#5347a797fe82b8d09749d10e9f5b83665adbca88" + integrity sha512-msyzuUnvsjsaSaocV6L7ErfNsa5nDWL1XKNnDePLgmz+WdU4w/J8+AxBMrWfi9m4IxfL5sZQKUPQKDQeeAT6lA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-dynamic-import@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.23.4.tgz#c7629e7254011ac3630d47d7f34ddd40ca535143" - integrity sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ== +"@babel/plugin-transform-dynamic-import@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.1.tgz#2a5a49959201970dd09a5fca856cb651e44439dd" + integrity sha512-av2gdSTyXcJVdI+8aFZsCAtR29xJt0S5tas+Ef8NvBNmD1a+N/3ecMLeMBgfcK+xzsjdLDT6oHt+DFPyeqUbDA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-dynamic-import" "^7.8.3" -"@babel/plugin-transform-exponentiation-operator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.23.3.tgz#ea0d978f6b9232ba4722f3dbecdd18f450babd18" - integrity sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ== +"@babel/plugin-transform-exponentiation-operator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.1.tgz#6650ebeb5bd5c012d5f5f90a26613a08162e8ba4" + integrity sha512-U1yX13dVBSwS23DEAqU+Z/PkwE9/m7QQy8Y9/+Tdb8UWYaGNDYwTLi19wqIAiROr8sXVum9A/rtiH5H0boUcTw== dependencies: "@babel/helper-builder-binary-assignment-operator-visitor" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-export-namespace-from@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.23.4.tgz#084c7b25e9a5c8271e987a08cf85807b80283191" - integrity sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ== +"@babel/plugin-transform-export-namespace-from@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.1.tgz#f033541fc036e3efb2dcb58eedafd4f6b8078acd" + integrity sha512-Ft38m/KFOyzKw2UaJFkWG9QnHPG/Q/2SkOrRk4pNBPg5IPZ+dOxcmkK5IyuBcxiNPyyYowPGUReyBvrvZs7IlQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" -"@babel/plugin-transform-for-of@^7.23.6": - version "7.23.6" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.23.6.tgz#81c37e24171b37b370ba6aaffa7ac86bcb46f94e" - integrity sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw== +"@babel/plugin-transform-for-of@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.1.tgz#67448446b67ab6c091360ce3717e7d3a59e202fd" + integrity sha512-OxBdcnF04bpdQdR3i4giHZNZQn7cm8RQKcSwA17wAAqEELo1ZOwp5FFgeptWUQXFyT9kwHo10aqqauYkRZPCAg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" -"@babel/plugin-transform-function-name@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.23.3.tgz#8f424fcd862bf84cb9a1a6b42bc2f47ed630f8dc" - integrity sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw== +"@babel/plugin-transform-function-name@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.1.tgz#8cba6f7730626cc4dfe4ca2fa516215a0592b361" + integrity sha512-BXmDZpPlh7jwicKArQASrj8n22/w6iymRnvHYYd2zO30DbE277JO20/7yXJT3QxDPtiQiOxQBbZH4TpivNXIxA== dependencies: - "@babel/helper-compilation-targets" "^7.22.15" + "@babel/helper-compilation-targets" "^7.23.6" "@babel/helper-function-name" "^7.23.0" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-json-strings@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.23.4.tgz#a871d9b6bd171976efad2e43e694c961ffa3714d" - integrity sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg== +"@babel/plugin-transform-json-strings@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.1.tgz#08e6369b62ab3e8a7b61089151b161180c8299f7" + integrity sha512-U7RMFmRvoasscrIFy5xA4gIp8iWnWubnKkKuUGJjsuOH7GfbMkB+XZzeslx2kLdEGdOJDamEmCqOks6e8nv8DQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-json-strings" "^7.8.3" -"@babel/plugin-transform-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.23.3.tgz#8214665f00506ead73de157eba233e7381f3beb4" - integrity sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ== +"@babel/plugin-transform-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.1.tgz#0a1982297af83e6b3c94972686067df588c5c096" + integrity sha512-zn9pwz8U7nCqOYIiBaOxoQOtYmMODXTJnkxG4AtX8fPmnCRYWBOHD0qcpwS9e2VDSp1zNJYpdnFMIKb8jmwu6g== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-logical-assignment-operators@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.23.4.tgz#e599f82c51d55fac725f62ce55d3a0886279ecb5" - integrity sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg== +"@babel/plugin-transform-logical-assignment-operators@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.1.tgz#719d8aded1aa94b8fb34e3a785ae8518e24cfa40" + integrity sha512-OhN6J4Bpz+hIBqItTeWJujDOfNP+unqv/NJgyhlpSqgBTPm37KkMmZV6SYcOj+pnDbdcl1qRGV/ZiIjX9Iy34w== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" -"@babel/plugin-transform-member-expression-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.23.3.tgz#e37b3f0502289f477ac0e776b05a833d853cabcc" - integrity sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag== +"@babel/plugin-transform-member-expression-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.1.tgz#896d23601c92f437af8b01371ad34beb75df4489" + integrity sha512-4ojai0KysTWXzHseJKa1XPNXKRbuUrhkOPY4rEGeR+7ChlJVKxFa3H3Bz+7tWaGKgJAXUWKOGmltN+u9B3+CVg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-modules-amd@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.23.3.tgz#e19b55436a1416829df0a1afc495deedfae17f7d" - integrity sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw== +"@babel/plugin-transform-modules-amd@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.1.tgz#b6d829ed15258536977e9c7cc6437814871ffa39" + integrity sha512-lAxNHi4HVtjnHd5Rxg3D5t99Xm6H7b04hUS7EHIXcUl2EV4yl1gWdqZrNzXnSrHveL9qMdbODlLF55mvgjAfaQ== dependencies: "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-modules-commonjs@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.3.tgz#661ae831b9577e52be57dd8356b734f9700b53b4" - integrity sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA== +"@babel/plugin-transform-modules-commonjs@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.1.tgz#e71ba1d0d69e049a22bf90b3867e263823d3f1b9" + integrity sha512-szog8fFTUxBfw0b98gEWPaEqF42ZUD/T3bkynW/wtgx2p/XCP55WEsb+VosKceRSd6njipdZvNogqdtI4Q0chw== dependencies: "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-simple-access" "^7.22.5" -"@babel/plugin-transform-modules-systemjs@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.23.9.tgz#105d3ed46e4a21d257f83a2f9e2ee4203ceda6be" - integrity sha512-KDlPRM6sLo4o1FkiSlXoAa8edLXFsKKIda779fbLrvmeuc3itnjCtaO6RrtoaANsIJANj+Vk1zqbZIMhkCAHVw== +"@babel/plugin-transform-modules-systemjs@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.24.1.tgz#2b9625a3d4e445babac9788daec39094e6b11e3e" + integrity sha512-mqQ3Zh9vFO1Tpmlt8QPnbwGHzNz3lpNEMxQb1kAemn/erstyqw1r9KeOlOfo3y6xAnFEcOv2tSyrXfmMk+/YZA== dependencies: "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-validator-identifier" "^7.22.20" -"@babel/plugin-transform-modules-umd@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.23.3.tgz#5d4395fccd071dfefe6585a4411aa7d6b7d769e9" - integrity sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg== +"@babel/plugin-transform-modules-umd@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.1.tgz#69220c66653a19cf2c0872b9c762b9a48b8bebef" + integrity sha512-tuA3lpPj+5ITfcCluy6nWonSL7RvaG0AOTeAuvXqEKS34lnLzXpDb0dcP6K8jD0zWZFNDVly90AGFJPnm4fOYg== dependencies: "@babel/helper-module-transforms" "^7.23.3" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-transform-named-capturing-groups-regex@^7.22.5": version "7.22.5" @@ -904,62 +932,61 @@ "@babel/helper-create-regexp-features-plugin" "^7.22.5" "@babel/helper-plugin-utils" "^7.22.5" -"@babel/plugin-transform-new-target@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.23.3.tgz#5491bb78ed6ac87e990957cea367eab781c4d980" - integrity sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ== +"@babel/plugin-transform-new-target@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.1.tgz#29c59988fa3d0157de1c871a28cd83096363cc34" + integrity sha512-/rurytBM34hYy0HKZQyA0nHbQgQNFm4Q/BOc9Hflxi2X3twRof7NaE5W46j4kQitm7SvACVRXsa6N/tSZxvPug== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-nullish-coalescing-operator@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.23.4.tgz#45556aad123fc6e52189ea749e33ce090637346e" - integrity sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA== +"@babel/plugin-transform-nullish-coalescing-operator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.1.tgz#0cd494bb97cb07d428bd651632cb9d4140513988" + integrity sha512-iQ+caew8wRrhCikO5DrUYx0mrmdhkaELgFa+7baMcVuhxIkN7oxt06CZ51D65ugIb1UWRQ8oQe+HXAVM6qHFjw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3" -"@babel/plugin-transform-numeric-separator@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.23.4.tgz#03d08e3691e405804ecdd19dd278a40cca531f29" - integrity sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q== +"@babel/plugin-transform-numeric-separator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.1.tgz#5bc019ce5b3435c1cadf37215e55e433d674d4e8" + integrity sha512-7GAsGlK4cNL2OExJH1DzmDeKnRv/LXq0eLUSvudrehVA5Rgg4bIrqEUW29FbKMBRT0ztSqisv7kjP+XIC4ZMNw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-numeric-separator" "^7.10.4" -"@babel/plugin-transform-object-rest-spread@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.23.4.tgz#2b9c2d26bf62710460bdc0d1730d4f1048361b83" - integrity sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g== +"@babel/plugin-transform-object-rest-spread@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.1.tgz#5a3ce73caf0e7871a02e1c31e8b473093af241ff" + integrity sha512-XjD5f0YqOtebto4HGISLNfiNMTTs6tbkFf2TOqJlYKYmbo+mN9Dnpl4SRoofiziuOWMIyq3sZEUqLo3hLITFEA== dependencies: - "@babel/compat-data" "^7.23.3" - "@babel/helper-compilation-targets" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-compilation-targets" "^7.23.6" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-object-rest-spread" "^7.8.3" - "@babel/plugin-transform-parameters" "^7.23.3" + "@babel/plugin-transform-parameters" "^7.24.1" -"@babel/plugin-transform-object-super@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.23.3.tgz#81fdb636dcb306dd2e4e8fd80db5b2362ed2ebcd" - integrity sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA== +"@babel/plugin-transform-object-super@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.1.tgz#e71d6ab13483cca89ed95a474f542bbfc20a0520" + integrity sha512-oKJqR3TeI5hSLRxudMjFQ9re9fBVUU0GICqM3J1mi8MqlhVr6hC/ZN4ttAyMuQR6EZZIY6h/exe5swqGNNIkWQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-replace-supers" "^7.22.20" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-replace-supers" "^7.24.1" -"@babel/plugin-transform-optional-catch-binding@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.23.4.tgz#318066de6dacce7d92fa244ae475aa8d91778017" - integrity sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A== +"@babel/plugin-transform-optional-catch-binding@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.1.tgz#92a3d0efe847ba722f1a4508669b23134669e2da" + integrity sha512-oBTH7oURV4Y+3EUrf6cWn1OHio3qG/PVwO5J03iSJmBg6m2EhKjkAu/xuaXaYwWW9miYtvbWv4LNf0AmR43LUA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-optional-catch-binding" "^7.8.3" -"@babel/plugin-transform-optional-chaining@^7.23.3", "@babel/plugin-transform-optional-chaining@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.23.4.tgz#6acf61203bdfc4de9d4e52e64490aeb3e52bd017" - integrity sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA== +"@babel/plugin-transform-optional-chaining@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.1.tgz#26e588acbedce1ab3519ac40cc748e380c5291e6" + integrity sha512-n03wmDt+987qXwAgcBlnUUivrZBPZ8z1plL0YvgQalLm+ZE5BMhGm94jhxXtA1wzv1Cu2aaOv1BM9vbVttrzSg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" "@babel/plugin-syntax-optional-chaining" "^7.8.3" @@ -970,44 +997,44 @@ dependencies: "@babel/helper-plugin-utils" "^7.20.2" -"@babel/plugin-transform-parameters@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.23.3.tgz#83ef5d1baf4b1072fa6e54b2b0999a7b2527e2af" - integrity sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw== +"@babel/plugin-transform-parameters@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.1.tgz#983c15d114da190506c75b616ceb0f817afcc510" + integrity sha512-8Jl6V24g+Uw5OGPeWNKrKqXPDw2YDjLc53ojwfMcKwlEoETKU9rU0mHUtcg9JntWI/QYzGAXNWEcVHZ+fR+XXg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-private-methods@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.23.3.tgz#b2d7a3c97e278bfe59137a978d53b2c2e038c0e4" - integrity sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g== +"@babel/plugin-transform-private-methods@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.24.1.tgz#a0faa1ae87eff077e1e47a5ec81c3aef383dc15a" + integrity sha512-tGvisebwBO5em4PaYNqt4fkw56K2VALsAbAakY0FjTYqJp7gfdrgr7YX76Or8/cpik0W6+tj3rZ0uHU9Oil4tw== dependencies: - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-private-property-in-object@^7.23.4": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.23.4.tgz#3ec711d05d6608fd173d9b8de39872d8dbf68bf5" - integrity sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A== +"@babel/plugin-transform-private-property-in-object@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.1.tgz#756443d400274f8fb7896742962cc1b9f25c1f6a" + integrity sha512-pTHxDVa0BpUbvAgX3Gat+7cSciXqUcY9j2VZKTbSB6+VQGpNgNO9ailxTGHSXlqOnX1Hcx1Enme2+yv7VqP9bg== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-syntax-private-property-in-object" "^7.14.5" -"@babel/plugin-transform-property-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.23.3.tgz#54518f14ac4755d22b92162e4a852d308a560875" - integrity sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw== +"@babel/plugin-transform-property-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.1.tgz#d6a9aeab96f03749f4eebeb0b6ea8e90ec958825" + integrity sha512-LetvD7CrHmEx0G442gOomRr66d7q8HzzGGr4PMHGr+5YIm6++Yke+jxj246rpvsbyhJwCLxcTn6zW1P1BSenqA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-react-display-name@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.23.3.tgz#70529f034dd1e561045ad3c8152a267f0d7b6200" - integrity sha512-GnvhtVfA2OAtzdX58FJxU19rhoGeQzyVndw3GgtdECQvQFXPEZIOVULHVZGAYmOgmqjXpVpfocAbSjh99V/Fqw== +"@babel/plugin-transform-react-display-name@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.1.tgz#554e3e1a25d181f040cf698b93fd289a03bfdcdb" + integrity sha512-mvoQg2f9p2qlpDQRBC7M3c3XTr0k7cp/0+kFKKO/7Gtu0LSw16eKB+Fabe2bDT/UpsyasTBBkAnbdsLrkD5XMw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-transform-react-jsx-development@^7.22.5": version "7.22.5" @@ -1016,149 +1043,149 @@ dependencies: "@babel/plugin-transform-react-jsx" "^7.22.5" -"@babel/plugin-transform-react-jsx@^7.22.15", "@babel/plugin-transform-react-jsx@^7.22.5": - version "7.22.15" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz#7e6266d88705d7c49f11c98db8b9464531289cd6" - integrity sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA== +"@babel/plugin-transform-react-jsx@^7.22.5", "@babel/plugin-transform-react-jsx@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.23.4.tgz#393f99185110cea87184ea47bcb4a7b0c2e39312" + integrity sha512-5xOpoPguCZCRbo/JeHlloSkTA8Bld1J/E1/kLfD1nsuiW1m8tduTA1ERCgIZokDflX/IBzKcqR3l7VlRgiIfHA== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" "@babel/helper-module-imports" "^7.22.15" "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-jsx" "^7.22.5" - "@babel/types" "^7.22.15" + "@babel/plugin-syntax-jsx" "^7.23.3" + "@babel/types" "^7.23.4" -"@babel/plugin-transform-react-pure-annotations@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.23.3.tgz#fabedbdb8ee40edf5da96f3ecfc6958e3783b93c" - integrity sha512-qMFdSS+TUhB7Q/3HVPnEdYJDQIk57jkntAwSuz9xfSE4n+3I+vHYCli3HoHawN1Z3RfCz/y1zXA/JXjG6cVImQ== +"@babel/plugin-transform-react-pure-annotations@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.24.1.tgz#c86bce22a53956331210d268e49a0ff06e392470" + integrity sha512-+pWEAaDJvSm9aFvJNpLiM2+ktl2Sn2U5DdyiWdZBxmLc6+xGt88dvFqsHiAiDS+8WqUwbDfkKz9jRxK3M0k+kA== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-regenerator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.23.3.tgz#141afd4a2057298602069fce7f2dc5173e6c561c" - integrity sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ== +"@babel/plugin-transform-regenerator@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.1.tgz#625b7545bae52363bdc1fbbdc7252b5046409c8c" + integrity sha512-sJwZBCzIBE4t+5Q4IGLaaun5ExVMRY0lYwos/jNecjMrVCygCdph3IKv0tkP5Fc87e/1+bebAmEAGBfnRD+cnw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" regenerator-transform "^0.15.2" -"@babel/plugin-transform-reserved-words@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.23.3.tgz#4130dcee12bd3dd5705c587947eb715da12efac8" - integrity sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg== +"@babel/plugin-transform-reserved-words@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.1.tgz#8de729f5ecbaaf5cf83b67de13bad38a21be57c1" + integrity sha512-JAclqStUfIwKN15HrsQADFgeZt+wexNQ0uLhuqvqAUFoqPMjEcFCYZBhq0LUdz6dZK/mD+rErhW71fbx8RYElg== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/plugin-transform-runtime@^7.12.10": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.23.9.tgz#2c64d0680fc8e09e1dfe8fd5c646fe72abd82004" - integrity sha512-A7clW3a0aSjm3ONU9o2HAILSegJCYlEZmOhmBRReVtIpY/Z/p7yIZ+wR41Z+UipwdGuqwtID/V/dOdZXjwi9gQ== - dependencies: - "@babel/helper-module-imports" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - babel-plugin-polyfill-corejs2 "^0.4.8" - babel-plugin-polyfill-corejs3 "^0.9.0" - babel-plugin-polyfill-regenerator "^0.5.5" + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.24.3.tgz#dc58ad4a31810a890550365cc922e1ff5acb5d7f" + integrity sha512-J0BuRPNlNqlMTRJ72eVptpt9VcInbxO6iP3jaxr+1NPhC0UkKL+6oeX6VXMEYdADnuqmMmsBspt4d5w8Y/TCbQ== + dependencies: + "@babel/helper-module-imports" "^7.24.3" + "@babel/helper-plugin-utils" "^7.24.0" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.1" + babel-plugin-polyfill-regenerator "^0.6.1" semver "^6.3.1" -"@babel/plugin-transform-shorthand-properties@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.23.3.tgz#97d82a39b0e0c24f8a981568a8ed851745f59210" - integrity sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg== +"@babel/plugin-transform-shorthand-properties@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.1.tgz#ba9a09144cf55d35ec6b93a32253becad8ee5b55" + integrity sha512-LyjVB1nsJ6gTTUKRjRWx9C1s9hE7dLfP/knKdrfeH9UPtAGjYGgxIbFfx7xyLIEWs7Xe1Gnf8EWiUqfjLhInZA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-spread@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.23.3.tgz#41d17aacb12bde55168403c6f2d6bdca563d362c" - integrity sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg== +"@babel/plugin-transform-spread@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.1.tgz#a1acf9152cbf690e4da0ba10790b3ac7d2b2b391" + integrity sha512-KjmcIM+fxgY+KxPVbjelJC6hrH1CgtPmTvdXAfn3/a9CnWGSTY7nH4zm5+cjmWJybdcPSsD0++QssDsjcpe47g== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-skip-transparent-expression-wrappers" "^7.22.5" -"@babel/plugin-transform-sticky-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.23.3.tgz#dec45588ab4a723cb579c609b294a3d1bd22ff04" - integrity sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg== +"@babel/plugin-transform-sticky-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.1.tgz#f03e672912c6e203ed8d6e0271d9c2113dc031b9" + integrity sha512-9v0f1bRXgPVcPrngOQvLXeGNNVLc8UjMVfebo9ka0WF3/7+aVUHmaJVT3sa0XCzEFioPfPHZiOcYG9qOsH63cw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-template-literals@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.23.3.tgz#5f0f028eb14e50b5d0f76be57f90045757539d07" - integrity sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg== +"@babel/plugin-transform-template-literals@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.1.tgz#15e2166873a30d8617e3e2ccadb86643d327aab7" + integrity sha512-WRkhROsNzriarqECASCNu/nojeXCDTE/F2HmRgOzi7NGvyfYGq1NEjKBK3ckLfRgGc6/lPAqP0vDOSw3YtG34g== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-typeof-symbol@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.23.3.tgz#9dfab97acc87495c0c449014eb9c547d8966bca4" - integrity sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ== +"@babel/plugin-transform-typeof-symbol@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.1.tgz#6831f78647080dec044f7e9f68003d99424f94c7" + integrity sha512-CBfU4l/A+KruSUoW+vTQthwcAdwuqbpRNB8HQKlZABwHRhsdHZ9fezp4Sn18PeAlYxTNiLMlx4xUBV3AWfg1BA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-typescript@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.23.3.tgz#ce806e6cb485d468c48c4f717696719678ab0138" - integrity sha512-ogV0yWnq38CFwH20l2Afz0dfKuZBx9o/Y2Rmh5vuSS0YD1hswgEgTfyTzuSrT2q9btmHRSqYoSfwFUVaC1M1Jw== +"@babel/plugin-transform-typescript@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.24.1.tgz#5c05e28bb76c7dfe7d6c5bed9951324fd2d3ab07" + integrity sha512-liYSESjX2fZ7JyBFkYG78nfvHlMKE6IpNdTVnxmlYUR+j5ZLsitFbaAE+eJSK2zPPkNWNw4mXL51rQ8WrvdK0w== dependencies: "@babel/helper-annotate-as-pure" "^7.22.5" - "@babel/helper-create-class-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/plugin-syntax-typescript" "^7.23.3" + "@babel/helper-create-class-features-plugin" "^7.24.1" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/plugin-syntax-typescript" "^7.24.1" -"@babel/plugin-transform-unicode-escapes@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.23.3.tgz#1f66d16cab01fab98d784867d24f70c1ca65b925" - integrity sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q== +"@babel/plugin-transform-unicode-escapes@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.1.tgz#fb3fa16676549ac7c7449db9b342614985c2a3a4" + integrity sha512-RlkVIcWT4TLI96zM660S877E7beKlQw7Ig+wqkKBiWfj0zH5Q4h50q6er4wzZKRNSYpfo6ILJ+hrJAGSX2qcNw== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-unicode-property-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.23.3.tgz#19e234129e5ffa7205010feec0d94c251083d7ad" - integrity sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA== +"@babel/plugin-transform-unicode-property-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.1.tgz#56704fd4d99da81e5e9f0c0c93cabd91dbc4889e" + integrity sha512-Ss4VvlfYV5huWApFsF8/Sq0oXnGO+jB+rijFEFugTd3cwSObUSnUi88djgR5528Csl0uKlrI331kRqe56Ov2Ng== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-unicode-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.23.3.tgz#26897708d8f42654ca4ce1b73e96140fbad879dc" - integrity sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw== +"@babel/plugin-transform-unicode-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.1.tgz#57c3c191d68f998ac46b708380c1ce4d13536385" + integrity sha512-2A/94wgZgxfTsiLaQ2E36XAOdcZmGAaEEgVmxQWwZXWkGhvoHbaqXcKnU8zny4ycpu3vNqg0L/PcCiYtHtA13g== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" -"@babel/plugin-transform-unicode-sets-regex@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.23.3.tgz#4fb6f0a719c2c5859d11f6b55a050cc987f3799e" - integrity sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw== +"@babel/plugin-transform-unicode-sets-regex@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.24.1.tgz#c1ea175b02afcffc9cf57a9c4658326625165b7f" + integrity sha512-fqj4WuzzS+ukpgerpAoOnMfQXwUHFxXUZUE84oL2Kao2N8uSlvcpnAidKASgsNgzZHBsHWvcm8s9FPWUhAb8fA== dependencies: "@babel/helper-create-regexp-features-plugin" "^7.22.15" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/preset-env@^7.12.11": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.23.9.tgz#beace3b7994560ed6bf78e4ae2073dff45387669" - integrity sha512-3kBGTNBBk9DQiPoXYS0g0BYlwTQYUTifqgKTjxUwEUkduRT2QOa0FPGBJ+NROQhGyYO5BuTJwGvBnqKDykac6A== + version "7.24.3" + resolved "https://registry.yarnpkg.com/@babel/preset-env/-/preset-env-7.24.3.tgz#f3f138c844ffeeac372597b29c51b5259e8323a3" + integrity sha512-fSk430k5c2ff8536JcPvPWK4tZDwehWLGlBp0wrsBUjZVdeQV6lePbwKWZaZfK2vnh/1kQX1PzAJWsnBmVgGJA== dependencies: - "@babel/compat-data" "^7.23.5" + "@babel/compat-data" "^7.24.1" "@babel/helper-compilation-targets" "^7.23.6" - "@babel/helper-plugin-utils" "^7.22.5" + "@babel/helper-plugin-utils" "^7.24.0" "@babel/helper-validator-option" "^7.23.5" - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.23.3" - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.23.3" - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.23.7" + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression" "^7.24.1" + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.24.1" + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly" "^7.24.1" "@babel/plugin-proposal-private-property-in-object" "7.21.0-placeholder-for-preset-env.2" "@babel/plugin-syntax-async-generators" "^7.8.4" "@babel/plugin-syntax-class-properties" "^7.12.13" "@babel/plugin-syntax-class-static-block" "^7.14.5" "@babel/plugin-syntax-dynamic-import" "^7.8.3" "@babel/plugin-syntax-export-namespace-from" "^7.8.3" - "@babel/plugin-syntax-import-assertions" "^7.23.3" - "@babel/plugin-syntax-import-attributes" "^7.23.3" + "@babel/plugin-syntax-import-assertions" "^7.24.1" + "@babel/plugin-syntax-import-attributes" "^7.24.1" "@babel/plugin-syntax-import-meta" "^7.10.4" "@babel/plugin-syntax-json-strings" "^7.8.3" "@babel/plugin-syntax-logical-assignment-operators" "^7.10.4" @@ -1170,58 +1197,58 @@ "@babel/plugin-syntax-private-property-in-object" "^7.14.5" "@babel/plugin-syntax-top-level-await" "^7.14.5" "@babel/plugin-syntax-unicode-sets-regex" "^7.18.6" - "@babel/plugin-transform-arrow-functions" "^7.23.3" - "@babel/plugin-transform-async-generator-functions" "^7.23.9" - "@babel/plugin-transform-async-to-generator" "^7.23.3" - "@babel/plugin-transform-block-scoped-functions" "^7.23.3" - "@babel/plugin-transform-block-scoping" "^7.23.4" - "@babel/plugin-transform-class-properties" "^7.23.3" - "@babel/plugin-transform-class-static-block" "^7.23.4" - "@babel/plugin-transform-classes" "^7.23.8" - "@babel/plugin-transform-computed-properties" "^7.23.3" - "@babel/plugin-transform-destructuring" "^7.23.3" - "@babel/plugin-transform-dotall-regex" "^7.23.3" - "@babel/plugin-transform-duplicate-keys" "^7.23.3" - "@babel/plugin-transform-dynamic-import" "^7.23.4" - "@babel/plugin-transform-exponentiation-operator" "^7.23.3" - "@babel/plugin-transform-export-namespace-from" "^7.23.4" - "@babel/plugin-transform-for-of" "^7.23.6" - "@babel/plugin-transform-function-name" "^7.23.3" - "@babel/plugin-transform-json-strings" "^7.23.4" - "@babel/plugin-transform-literals" "^7.23.3" - "@babel/plugin-transform-logical-assignment-operators" "^7.23.4" - "@babel/plugin-transform-member-expression-literals" "^7.23.3" - "@babel/plugin-transform-modules-amd" "^7.23.3" - "@babel/plugin-transform-modules-commonjs" "^7.23.3" - "@babel/plugin-transform-modules-systemjs" "^7.23.9" - "@babel/plugin-transform-modules-umd" "^7.23.3" + "@babel/plugin-transform-arrow-functions" "^7.24.1" + "@babel/plugin-transform-async-generator-functions" "^7.24.3" + "@babel/plugin-transform-async-to-generator" "^7.24.1" + "@babel/plugin-transform-block-scoped-functions" "^7.24.1" + "@babel/plugin-transform-block-scoping" "^7.24.1" + "@babel/plugin-transform-class-properties" "^7.24.1" + "@babel/plugin-transform-class-static-block" "^7.24.1" + "@babel/plugin-transform-classes" "^7.24.1" + "@babel/plugin-transform-computed-properties" "^7.24.1" + "@babel/plugin-transform-destructuring" "^7.24.1" + "@babel/plugin-transform-dotall-regex" "^7.24.1" + "@babel/plugin-transform-duplicate-keys" "^7.24.1" + "@babel/plugin-transform-dynamic-import" "^7.24.1" + "@babel/plugin-transform-exponentiation-operator" "^7.24.1" + "@babel/plugin-transform-export-namespace-from" "^7.24.1" + "@babel/plugin-transform-for-of" "^7.24.1" + "@babel/plugin-transform-function-name" "^7.24.1" + "@babel/plugin-transform-json-strings" "^7.24.1" + "@babel/plugin-transform-literals" "^7.24.1" + "@babel/plugin-transform-logical-assignment-operators" "^7.24.1" + "@babel/plugin-transform-member-expression-literals" "^7.24.1" + "@babel/plugin-transform-modules-amd" "^7.24.1" + "@babel/plugin-transform-modules-commonjs" "^7.24.1" + "@babel/plugin-transform-modules-systemjs" "^7.24.1" + "@babel/plugin-transform-modules-umd" "^7.24.1" "@babel/plugin-transform-named-capturing-groups-regex" "^7.22.5" - "@babel/plugin-transform-new-target" "^7.23.3" - "@babel/plugin-transform-nullish-coalescing-operator" "^7.23.4" - "@babel/plugin-transform-numeric-separator" "^7.23.4" - "@babel/plugin-transform-object-rest-spread" "^7.23.4" - "@babel/plugin-transform-object-super" "^7.23.3" - "@babel/plugin-transform-optional-catch-binding" "^7.23.4" - "@babel/plugin-transform-optional-chaining" "^7.23.4" - "@babel/plugin-transform-parameters" "^7.23.3" - "@babel/plugin-transform-private-methods" "^7.23.3" - "@babel/plugin-transform-private-property-in-object" "^7.23.4" - "@babel/plugin-transform-property-literals" "^7.23.3" - "@babel/plugin-transform-regenerator" "^7.23.3" - "@babel/plugin-transform-reserved-words" "^7.23.3" - "@babel/plugin-transform-shorthand-properties" "^7.23.3" - "@babel/plugin-transform-spread" "^7.23.3" - "@babel/plugin-transform-sticky-regex" "^7.23.3" - "@babel/plugin-transform-template-literals" "^7.23.3" - "@babel/plugin-transform-typeof-symbol" "^7.23.3" - "@babel/plugin-transform-unicode-escapes" "^7.23.3" - "@babel/plugin-transform-unicode-property-regex" "^7.23.3" - "@babel/plugin-transform-unicode-regex" "^7.23.3" - "@babel/plugin-transform-unicode-sets-regex" "^7.23.3" + "@babel/plugin-transform-new-target" "^7.24.1" + "@babel/plugin-transform-nullish-coalescing-operator" "^7.24.1" + "@babel/plugin-transform-numeric-separator" "^7.24.1" + "@babel/plugin-transform-object-rest-spread" "^7.24.1" + "@babel/plugin-transform-object-super" "^7.24.1" + "@babel/plugin-transform-optional-catch-binding" "^7.24.1" + "@babel/plugin-transform-optional-chaining" "^7.24.1" + "@babel/plugin-transform-parameters" "^7.24.1" + "@babel/plugin-transform-private-methods" "^7.24.1" + "@babel/plugin-transform-private-property-in-object" "^7.24.1" + "@babel/plugin-transform-property-literals" "^7.24.1" + "@babel/plugin-transform-regenerator" "^7.24.1" + "@babel/plugin-transform-reserved-words" "^7.24.1" + "@babel/plugin-transform-shorthand-properties" "^7.24.1" + "@babel/plugin-transform-spread" "^7.24.1" + "@babel/plugin-transform-sticky-regex" "^7.24.1" + "@babel/plugin-transform-template-literals" "^7.24.1" + "@babel/plugin-transform-typeof-symbol" "^7.24.1" + "@babel/plugin-transform-unicode-escapes" "^7.24.1" + "@babel/plugin-transform-unicode-property-regex" "^7.24.1" + "@babel/plugin-transform-unicode-regex" "^7.24.1" + "@babel/plugin-transform-unicode-sets-regex" "^7.24.1" "@babel/preset-modules" "0.1.6-no-external-plugins" - babel-plugin-polyfill-corejs2 "^0.4.8" - babel-plugin-polyfill-corejs3 "^0.9.0" - babel-plugin-polyfill-regenerator "^0.5.5" + babel-plugin-polyfill-corejs2 "^0.4.10" + babel-plugin-polyfill-corejs3 "^0.10.4" + babel-plugin-polyfill-regenerator "^0.6.1" core-js-compat "^3.31.0" semver "^6.3.1" @@ -1235,27 +1262,27 @@ esutils "^2.0.2" "@babel/preset-react@^7.12.10": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.23.3.tgz#f73ca07e7590f977db07eb54dbe46538cc015709" - integrity sha512-tbkHOS9axH6Ysf2OUEqoSZ6T3Fa2SrNH6WTWSPBboxKzdxNc9qOICeLXkNG0ZEwbQ1HY8liwOce4aN/Ceyuq6w== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/preset-react/-/preset-react-7.24.1.tgz#2450c2ac5cc498ef6101a6ca5474de251e33aa95" + integrity sha512-eFa8up2/8cZXLIpkafhaADTXSnl7IsUFCYenRWrARBz0/qZwcT0RBXpys0LJU4+WfPoF2ZG6ew6s2V6izMCwRA== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.15" - "@babel/plugin-transform-react-display-name" "^7.23.3" - "@babel/plugin-transform-react-jsx" "^7.22.15" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-transform-react-display-name" "^7.24.1" + "@babel/plugin-transform-react-jsx" "^7.23.4" "@babel/plugin-transform-react-jsx-development" "^7.22.5" - "@babel/plugin-transform-react-pure-annotations" "^7.23.3" + "@babel/plugin-transform-react-pure-annotations" "^7.24.1" "@babel/preset-typescript@^7.12.7": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.23.3.tgz#14534b34ed5b6d435aa05f1ae1c5e7adcc01d913" - integrity sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/preset-typescript/-/preset-typescript-7.24.1.tgz#89bdf13a3149a17b3b2a2c9c62547f06db8845ec" + integrity sha512-1DBaMmRDpuYQBPWD8Pf/WEwCrtgRHxsZnP4mIy9G/X+hFfbI47Q2G4t1Paakld84+qsk2fSsUPMKg71jkoOOaQ== dependencies: - "@babel/helper-plugin-utils" "^7.22.5" - "@babel/helper-validator-option" "^7.22.15" - "@babel/plugin-syntax-jsx" "^7.23.3" - "@babel/plugin-transform-modules-commonjs" "^7.23.3" - "@babel/plugin-transform-typescript" "^7.23.3" + "@babel/helper-plugin-utils" "^7.24.0" + "@babel/helper-validator-option" "^7.23.5" + "@babel/plugin-syntax-jsx" "^7.24.1" + "@babel/plugin-transform-modules-commonjs" "^7.24.1" + "@babel/plugin-transform-typescript" "^7.24.1" "@babel/register@^7.12.10": version "7.23.7" @@ -1274,9 +1301,9 @@ integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA== "@babel/runtime@^7.0.0", "@babel/runtime@^7.12.13", "@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.17.9", "@babel/runtime@^7.23.2", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" - integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.1.tgz#431f9a794d173b53720e69a6464abc6f0e2a5c57" + integrity sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ== dependencies: regenerator-runtime "^0.14.0" @@ -1289,14 +1316,14 @@ "@babel/parser" "^7.20.7" "@babel/types" "^7.20.7" -"@babel/template@^7.22.15", "@babel/template@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" - integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== +"@babel/template@^7.22.15", "@babel/template@^7.24.0": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" + integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== dependencies: "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.23.9" - "@babel/types" "^7.23.9" + "@babel/parser" "^7.24.0" + "@babel/types" "^7.24.0" "@babel/template@^7.3.3": version "7.22.15" @@ -1323,19 +1350,19 @@ debug "^4.1.0" globals "^11.1.0" -"@babel/traverse@^7.23.9": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" - integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== +"@babel/traverse@^7.24.1": + version "7.24.1" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.1.tgz#d65c36ac9dd17282175d1e4a3c49d5b7988f530c" + integrity sha512-xuU6o9m68KeqZbQuDt2TcKSxUw/mrsvavlEqQ1leZ/B+C9tk6E4sRWy97WaXgvq5E+nU3cXMxv3WKOCanVMCmQ== dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/generator" "^7.23.6" + "@babel/code-frame" "^7.24.1" + "@babel/generator" "^7.24.1" "@babel/helper-environment-visitor" "^7.22.20" "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.9" - "@babel/types" "^7.23.9" + "@babel/parser" "^7.24.1" + "@babel/types" "^7.24.0" debug "^4.3.1" globals "^11.1.0" @@ -1348,10 +1375,10 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9", "@babel/types@^7.4.4": - version "7.23.9" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" - integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== +"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.23.4", "@babel/types@^7.24.0", "@babel/types@^7.4.4": + version "7.24.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf" + integrity sha512-+j7a5c253RfKh8iABBhywc8NSfP5LURe7Uh4qpsh6jc+aLJguvmIUBdjSdEMQv2bENrCR5MfRdjGo7vzS/ob7w== dependencies: "@babel/helper-string-parser" "^7.23.4" "@babel/helper-validator-identifier" "^7.22.20" @@ -1387,25 +1414,30 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" -"@csstools/css-parser-algorithms@^2.5.0": - version "2.5.0" - resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.5.0.tgz#0c03cd5418a9f404a05ff2ffcb1b69d04e8ec532" - integrity sha512-abypo6m9re3clXA00eu5syw+oaPHbJTPapu9C4pzNsJ4hdZDzushT50Zhu+iIYXgEe1CxnRMn7ngsbV+MLrlpQ== +"@csstools/css-parser-algorithms@^2.6.1": + version "2.6.1" + resolved "https://registry.yarnpkg.com/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.6.1.tgz#c45440d1efa2954006748a01697072dae5881bcd" + integrity sha512-ubEkAaTfVZa+WwGhs5jbo5Xfqpeaybr/RvWzvFxRs4jfq16wH8l8Ty/QEEpINxll4xhuGfdMbipRyz5QZh9+FA== -"@csstools/css-tokenizer@^2.2.3": - version "2.2.3" - resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-2.2.3.tgz#b099d543ea57b64f495915a095ead583866c50c6" - integrity sha512-pp//EvZ9dUmGuGtG1p+n17gTHEOqu9jO+FiCUjNN3BDmyhdA2Jq9QsVeR7K8/2QCK17HSsioPlTW9ZkzoWb3Lg== +"@csstools/css-tokenizer@^2.2.4": + version "2.2.4" + resolved "https://registry.yarnpkg.com/@csstools/css-tokenizer/-/css-tokenizer-2.2.4.tgz#a4b8718ed7fcd2dcd555de16b31ca59ad4b96a06" + integrity sha512-PuWRAewQLbDhGeTvFuq2oClaSCKPIBmHyIobCV39JHRYN0byDcUWJl5baPeNUcqrjtdMNqFooE0FGl31I3JOqw== -"@csstools/media-query-list-parser@^2.1.7": - version "2.1.7" - resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.7.tgz#a4836e3dbd693081a30b32ce9c2a781e1be16788" - integrity sha512-lHPKJDkPUECsyAvD60joYfDmp8UERYxHGkFfyLJFTVK/ERJe0sVlIFLXU5XFxdjNDTerp5L4KeaKG+Z5S94qxQ== +"@csstools/media-query-list-parser@^2.1.9": + version "2.1.9" + resolved "https://registry.yarnpkg.com/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.9.tgz#feb4b7268f998956eb3ded69507869e73d005dda" + integrity sha512-qqGuFfbn4rUmyOB0u8CVISIp5FfJ5GAR3mBrZ9/TKndHakdnm6pY0L/fbLcpPnrzwCyyTEZl1nUcXAYHEWneTA== -"@csstools/selector-specificity@^3.0.1": - version "3.0.1" - resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-3.0.1.tgz#d84597fbc0f897240c12fc0a31e492b036c70e40" - integrity sha512-NPljRHkq4a14YzZ3YD406uaxh7s0g6eAq3L9aLOWywoqe8PkYamAvtsh7KNX6c++ihDrJ0RiU+/z7rGnhlZ5ww== +"@csstools/selector-specificity@^3.0.2": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-3.0.3.tgz#208a3929ee614967a1fc8cd6cb758d9fcbf0caae" + integrity sha512-KEPNw4+WW5AVEIyzC80rTbWEUatTW2lXpN8+8ILC8PiPeWPjwUzrPZDIOZ2wwqDmeqOYTdSGyL3+vE5GC3FB3Q== + +"@dual-bundle/import-meta-resolve@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@dual-bundle/import-meta-resolve/-/import-meta-resolve-4.0.0.tgz#df79b7ea62c55094dc129880387864cdf41eca7c" + integrity sha512-ZKXyJeFAzcpKM2kk8ipoGIPUqx9BX52omTGnfwjJvxOCaZTM2wtDK7zN0aIgPRbT9XYAlha0HtmZ+XKteuh0Gw== "@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": version "4.4.0" @@ -1439,12 +1471,12 @@ minimatch "^3.1.2" strip-json-comments "^3.1.1" -"@eslint/js@8.56.0": - version "8.56.0" - resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" - integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== +"@eslint/js@8.57.0": + version "8.57.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.57.0.tgz#a5417ae8427873f1dd08b70b3574b453e67b5f7f" + integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== -"@floating-ui/core@^1.6.0": +"@floating-ui/core@^1.0.0": version "1.6.0" resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.0.tgz#fa41b87812a16bf123122bf945946bae3fdf7fc1" integrity sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g== @@ -1452,32 +1484,41 @@ "@floating-ui/utils" "^0.2.1" "@floating-ui/dom@^1.6.1": - version "1.6.1" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.1.tgz#d552e8444f77f2d88534372369b3771dc3a2fa5d" - integrity sha512-iA8qE43/H5iGozC3W0YSnVSW42Vh522yyM1gj+BqRwVsTNOyr231PsXDaV04yT39PsO0QL2QpbI/M0ZaLUQgRQ== + version "1.6.3" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.3.tgz#954e46c1dd3ad48e49db9ada7218b0985cee75ef" + integrity sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw== dependencies: - "@floating-ui/core" "^1.6.0" - "@floating-ui/utils" "^0.2.1" + "@floating-ui/core" "^1.0.0" + "@floating-ui/utils" "^0.2.0" -"@floating-ui/react-dom@^2.0.0": +"@floating-ui/react-dom@^2.0.0", "@floating-ui/react-dom@^2.0.8": version "2.0.8" resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.0.8.tgz#afc24f9756d1b433e1fe0d047c24bd4d9cefaa5d" integrity sha512-HOdqOt3R3OGeTKidaLvJKcgg75S6tibQ3Tif4eyd91QnIJWr0NLvoXFpJA/j8HqkFSL68GDca9AuyWEHlhyClw== dependencies: "@floating-ui/dom" "^1.6.1" -"@floating-ui/utils@^0.2.1": +"@floating-ui/react@^0.26.9": + version "0.26.10" + resolved "https://registry.yarnpkg.com/@floating-ui/react/-/react-0.26.10.tgz#d4a4878bcfaed70963ec0eaa67a71bead5924ee5" + integrity sha512-sh6f9gVvWQdEzLObrWbJ97c0clJObiALsFe0LiR/kb3tDRKwEhObASEH2QyfdoO/ZBPzwxa9j+nYFo+sqgbioA== + dependencies: + "@floating-ui/react-dom" "^2.0.0" + "@floating-ui/utils" "^0.2.0" + tabbable "^6.0.0" + +"@floating-ui/utils@^0.2.0", "@floating-ui/utils@^0.2.1": version "0.2.1" resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.1.tgz#16308cea045f0fc777b6ff20a9f25474dd8293d2" integrity sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q== -"@humanwhocodes/config-array@^0.11.13": - version "0.11.13" - resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" - integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== +"@humanwhocodes/config-array@^0.11.14": + version "0.11.14" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.14.tgz#d78e481a039f7566ecc9660b4ea7fe6b1fec442b" + integrity sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg== dependencies: - "@humanwhocodes/object-schema" "^2.0.1" - debug "^4.1.1" + "@humanwhocodes/object-schema" "^2.0.2" + debug "^4.3.1" minimatch "^3.0.5" "@humanwhocodes/module-importer@^1.0.1": @@ -1485,10 +1526,10 @@ resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== -"@humanwhocodes/object-schema@^2.0.1": - version "2.0.1" - resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" - integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== +"@humanwhocodes/object-schema@^2.0.2": + version "2.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz#d9fae00a2d5cb40f92cfe64b47ad749fbc38f917" + integrity sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw== "@isaacs/cliui@^8.0.2": version "8.0.2" @@ -1710,24 +1751,29 @@ "@types/yargs" "^17.0.8" chalk "^4.0.0" -"@jridgewell/gen-mapping@^0.3.0", "@jridgewell/gen-mapping@^0.3.2": - version "0.3.3" - resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" - integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== +"@jridgewell/gen-mapping@^0.3.2", "@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== dependencies: - "@jridgewell/set-array" "^1.0.1" + "@jridgewell/set-array" "^1.2.1" "@jridgewell/sourcemap-codec" "^1.4.10" - "@jridgewell/trace-mapping" "^0.3.9" + "@jridgewell/trace-mapping" "^0.3.24" -"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": +"@jridgewell/resolve-uri@^3.0.3": version "3.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721" integrity sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA== -"@jridgewell/set-array@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" - integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== "@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14": version "1.4.15" @@ -1750,10 +1796,10 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" -"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.9": - version "0.3.22" - resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c" - integrity sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw== +"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== dependencies: "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" @@ -1803,10 +1849,10 @@ resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== -"@matrix-org/analytics-events@^0.10.0": - version "0.10.0" - resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.10.0.tgz#d4d8b7859a516e888050d616ebbb0da539a15b1e" - integrity sha512-qzi7szEWxcl3nW2LDfq+SvFH/of/B/lwhfFUelhihGfr5TBPwgqM95Euc9GeYMZkU8Xm/2f5hYfA0ZleD6RKaA== +"@matrix-org/analytics-events@^0.19.0": + version "0.19.0" + resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.19.0.tgz#e20e4df54530ed1c755ab728e9c22891e376f9e2" + integrity sha512-wN/hbpTpOxz2u3zHbsJgVMi88oKmK1yqeSZuif3yNW68XQnV2cc0XGUEpl0fgLOl6fj1bZOtxbDg5rCLbqf4CQ== "@matrix-org/emojibase-bindings@^1.1.2": version "1.1.3" @@ -1816,10 +1862,10 @@ emojibase "^15.0.0" emojibase-data "^15.0.0" -"@matrix-org/matrix-sdk-crypto-wasm@^4.6.0": - version "4.6.0" - resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-4.6.0.tgz#35224214c7638abbe2bc91fb4fa4fb022a1a2bf0" - integrity sha512-v9PFWzSTWMlZKbyk3PPsZjUtOEQ7FIz5USD3lFRUWiS4pv0FOKR125VOUnR5Z/kAty57JXCHDAexCln3zE2Fww== +"@matrix-org/matrix-sdk-crypto-wasm@^4.9.0": + version "4.9.0" + resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-4.9.0.tgz#9dfed83e33f760650596c4e5c520e5e4c53355d2" + integrity sha512-/bgA4QfE7qkK6GFr9hnhjAvRSebGrmEJxukU0ukbudZcYvbzymoBBM8j3HeULXZT8kbw8WH6z63txYTMCBSDOA== "@matrix-org/matrix-wysiwyg@2.17.0": version "2.17.0" @@ -1831,17 +1877,17 @@ resolved "https://registry.yarnpkg.com/@matrix-org/olm/-/olm-3.2.15.tgz#55f3c1b70a21bbee3f9195cecd6846b1083451ec" integrity sha512-S7lOrndAK9/8qOtaTq/WhttJC/o4GAzdfK0MUPpo8ApzsJEC0QjtwrkC3KBXdFP1cD1MXi/mlKR7aaoVMKgs6Q== -"@matrix-org/react-sdk-module-api@^2.3.0": - version "2.3.0" - resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-2.3.0.tgz#85be5cfc73be0494c13d4dc9050cb70c58d7a08b" - integrity sha512-x/ie44yaXNtE5AKcmQiW5yINVEIJ7IjjEc35vj6j52fM8tZ9XbJx9PANKSWsdd0NJp3OqyaeHftmN6ESfx4YoQ== +"@matrix-org/react-sdk-module-api@^2.4.0": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@matrix-org/react-sdk-module-api/-/react-sdk-module-api-2.4.0.tgz#5e4552acbe728141f42c1d54d75dcb4efea9301c" + integrity sha512-cPb+YaqllfJkRX0ofcG/0YdHxCvcMAvUbdNMO2olpGL8vwbBP6mHdhbZ87z9pgsRIVOqfFuLUE3WeW0hxWrklQ== dependencies: "@babel/runtime" "^7.17.9" "@matrix-org/spec@^1.7.0": - version "1.8.0" - resolved "https://registry.yarnpkg.com/@matrix-org/spec/-/spec-1.8.0.tgz#5d46f0ddcdff01934a63aa1f070f0ce960326acc" - integrity sha512-QKPIfrJDz5kKiaFluSfFLqAHu1fyMpYAc7sLWSyxj2flPAbajyy4zM7kfyF5yh5iGrunVLXi1iDSXYoM5/a4ZQ== + version "1.9.0" + resolved "https://registry.yarnpkg.com/@matrix-org/spec/-/spec-1.9.0.tgz#ac43accc9b081ad443b11acd2d8d1f2919bd0e2f" + integrity sha512-BgPTYFhvjc10XWIEsqKsQOu5cR2BxMqpOhJ/IA/iiUeVOh4M5BjBR+ILZFGr8WV7TgH+h8rFdCy2kbaumRHkVg== "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": version "2.1.8-no-fsevents.3" @@ -1893,15 +1939,15 @@ tslib "^2.0.0" "@peculiar/webcrypto@^1.4.3": - version "1.4.5" - resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.4.5.tgz#424bed6b0d133b772f5cbffd143d0468a90f40a0" - integrity sha512-oDk93QCDGdxFRM8382Zdminzs44dg3M2+E5Np+JWkpqLDyJC9DviMh8F8mEJkYuUcUOGA5jHO5AJJ10MFWdbZw== + version "1.4.6" + resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.4.6.tgz#607af294c4f205efeeb172aa32cb20024fe4aecf" + integrity sha512-YBcMfqNSwn3SujUJvAaySy5tlYbYm6tVt9SKoXu8BaTdKGROiJDgPR3TXpZdAKUfklzm3lRapJEAltiMQtBgZg== dependencies: "@peculiar/asn1-schema" "^2.3.8" "@peculiar/json-schema" "^1.1.12" pvtsutils "^1.3.5" tslib "^2.6.2" - webcrypto-core "^1.7.8" + webcrypto-core "^1.7.9" "@pkgjs/parseargs@^0.11.0": version "0.11.0" @@ -1909,11 +1955,11 @@ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@playwright/test@^1.40.1": - version "1.41.2" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.41.2.tgz#bd9db40177f8fd442e16e14e0389d23751cdfc54" - integrity sha512-qQB9h7KbibJzrDpkXkYvsmiDJK14FULCCZgEcoe2AvFAS64oCirWTwzTlAYEbKaRxWs5TFesE1Na6izMv3HfGg== + version "1.42.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.42.1.tgz#9eff7417bcaa770e9e9a00439e078284b301f31c" + integrity sha512-Gq9rmS54mjBL/7/MvBaNOBwbfnh7beHvS6oS4srqXFcQHpQCV1+c8JXWE8VLPyRDhgS3H8x8A7hztqI9VnwrAQ== dependencies: - playwright "1.41.2" + playwright "1.42.1" "@radix-ui/primitive@1.0.1": version "1.0.1" @@ -2247,76 +2293,76 @@ dependencies: "@babel/runtime" "^7.13.10" -"@sentry-internal/feedback@7.102.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.102.0.tgz#c3c7f5cfe9726b6d4d1917bd5bd01238154f8ee7" - integrity sha512-GxHdzbOF4tg6TtyQzFqb/8c/p07n68qZC5KYwzs7AuW5ey0IPmdC58pOh3Kk52JA0P69/RZy39+r1p1Swr6C+Q== +"@sentry-internal/feedback@7.109.0": + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-7.109.0.tgz#4657d7f36a1de3be466f42735d295e212b7eca11" + integrity sha512-EL7N++poxvJP9rYvh6vSu24tsKkOveNCcCj4IM7+irWPjsuD2GLYYlhp/A/Mtt9l7iqO4plvtiQU5HGk7smcTQ== dependencies: - "@sentry/core" "7.102.0" - "@sentry/types" "7.102.0" - "@sentry/utils" "7.102.0" + "@sentry/core" "7.109.0" + "@sentry/types" "7.109.0" + "@sentry/utils" "7.109.0" -"@sentry-internal/replay-canvas@7.102.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.102.0.tgz#2bed235bbcb22eea71c39650096d21a3ed32f466" - integrity sha512-rgNO4PdFv0AYflBsCNbSIwpQuOOJQTqyu8i8U0PupjveNjkm0CUJhber/ZOcaGmbyjdvwikGwgWY2O0Oj0USCA== +"@sentry-internal/replay-canvas@7.109.0": + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-7.109.0.tgz#9a00857994a9487428296feed4a9ddf2d62bab84" + integrity sha512-Lh/K60kmloR6lkPUcQP0iamw7B/MdEUEx/ImAx4tUSMrLj+IoUEcq/ECgnnVyQkJq59+8nPEKrVLt7x6PUPEjw== dependencies: - "@sentry/core" "7.102.0" - "@sentry/replay" "7.102.0" - "@sentry/types" "7.102.0" - "@sentry/utils" "7.102.0" + "@sentry/core" "7.109.0" + "@sentry/replay" "7.109.0" + "@sentry/types" "7.109.0" + "@sentry/utils" "7.109.0" -"@sentry-internal/tracing@7.102.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.102.0.tgz#24cf662e1eb5623f6d5197e78c66d7b257560eb8" - integrity sha512-BlE33HWL1IzkGa0W+pwTiyu01MUIfYf+WnO9UC8qkDW3jxVvg2zhoSjXSxikT+KPCOgoZpQHspaTzwjnI1LCvw== +"@sentry-internal/tracing@7.109.0": + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/tracing/-/tracing-7.109.0.tgz#3effaa132c41a65378fa98146aea61228d528953" + integrity sha512-PzK/joC5tCuh2R/PRh+7dp+uuZl7pTsBIjPhVZHMTtb9+ls65WkdZJ1/uKXPouyz8NOo9Xok7aEvEo9seongyw== dependencies: - "@sentry/core" "7.102.0" - "@sentry/types" "7.102.0" - "@sentry/utils" "7.102.0" + "@sentry/core" "7.109.0" + "@sentry/types" "7.109.0" + "@sentry/utils" "7.109.0" "@sentry/browser@^7.0.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.102.0.tgz#335f51d01aabf8c4d2abc871855f9c2d19f8f70d" - integrity sha512-hIggcMnojIbWhbmlRfkykHmy6n7pjug0AHfF19HRUQxAx9KJfMH5YdWvohov0Hb9fS+jdvqgE+/4AWbEeXQrHw== - dependencies: - "@sentry-internal/feedback" "7.102.0" - "@sentry-internal/replay-canvas" "7.102.0" - "@sentry-internal/tracing" "7.102.0" - "@sentry/core" "7.102.0" - "@sentry/replay" "7.102.0" - "@sentry/types" "7.102.0" - "@sentry/utils" "7.102.0" - -"@sentry/core@7.102.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.102.0.tgz#da5e04a5fe97ed91464944dac40b813e6f8aa453" - integrity sha512-GO9eLOSBK1waW4AD0wDXAreaNqXFQ1MPQZrkKcN+GJYEFhJK1+u+MSV7vO5Fs/rIfaTZIZ2jtEkxSSAOucE8EQ== - dependencies: - "@sentry/types" "7.102.0" - "@sentry/utils" "7.102.0" - -"@sentry/replay@7.102.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.102.0.tgz#209b7adb68e89772824218ecab498d3a6fbc2c42" - integrity sha512-sUIBN4ZY0J5/dQS3KOe5VLykm856KZkTrhV8kmBEylzQhw1BBc8i2ehTILy5ZYh9Ra8uXPTAmtwpvYf/dRDfAg== - dependencies: - "@sentry-internal/tracing" "7.102.0" - "@sentry/core" "7.102.0" - "@sentry/types" "7.102.0" - "@sentry/utils" "7.102.0" - -"@sentry/types@7.102.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.102.0.tgz#b31e9faa54036053ab82c09c3c855035a4889c59" - integrity sha512-FPfFBP0x3LkPARw1/6cWySLq1djIo8ao3Qo2KNBeE9CHdq8bsS1a8zzjJLuWG4Ww+wieLP8/lY3WTgrCz4jowg== - -"@sentry/utils@7.102.0": - version "7.102.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.102.0.tgz#66325f2567986cc3fd12fbdb980fb8ada170342b" - integrity sha512-cp5KCRe0slOVMwG4iP2Z4UajQkjryRTiFskZ5H7Q3X9R5voM8+DAhiDcIW88GL9NxqyUrAJOjmKdeLK2vM+bdA== - dependencies: - "@sentry/types" "7.102.0" + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-7.109.0.tgz#13b2623f43047f292cf7d6070128a7501e008693" + integrity sha512-yx+OFG+Ab9qUDDgV9ZDv8M9O9Mqr0fjKta/LMlWALYLjzkMvxsPlRPFj7oMBlHqOTVLDeg7lFYmsA8wyWQ8Z8g== + dependencies: + "@sentry-internal/feedback" "7.109.0" + "@sentry-internal/replay-canvas" "7.109.0" + "@sentry-internal/tracing" "7.109.0" + "@sentry/core" "7.109.0" + "@sentry/replay" "7.109.0" + "@sentry/types" "7.109.0" + "@sentry/utils" "7.109.0" + +"@sentry/core@7.109.0": + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-7.109.0.tgz#7a02f4af4a676950f6555f552a2a232d4458fcd5" + integrity sha512-xwD4U0IlvvlE/x/g/W1I8b4Cfb16SsCMmiEuBf6XxvAa3OfWBxKoqLifb3GyrbxMC4LbIIZCN/SvLlnGJPgszA== + dependencies: + "@sentry/types" "7.109.0" + "@sentry/utils" "7.109.0" + +"@sentry/replay@7.109.0": + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry/replay/-/replay-7.109.0.tgz#f50fb0140c81fce660c44cc93c35988898b8348b" + integrity sha512-hCDjbTNO7ErW/XsaBXlyHFsUhneyBUdTec1Swf98TFEfVqNsTs6q338aUcaR8dGRLbLrJ9YU9D1qKq++v5h2CA== + dependencies: + "@sentry-internal/tracing" "7.109.0" + "@sentry/core" "7.109.0" + "@sentry/types" "7.109.0" + "@sentry/utils" "7.109.0" + +"@sentry/types@7.109.0": + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-7.109.0.tgz#d8778358114ed05be734661cc9e1e261f4494947" + integrity sha512-egCBnDv3YpVFoNzRLdP0soVrxVLCQ+rovREKJ1sw3rA2/MFH9WJ+DZZexsX89yeAFzy1IFsCp7/dEqudusml6g== + +"@sentry/utils@7.109.0": + version "7.109.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-7.109.0.tgz#7078e1400197abc1b0c436679bef980639500a86" + integrity sha512-3RjxMOLMBwZ5VSiH84+o/3NY2An4Zldjz0EbfEQNRY9yffRiCPJSQiCJID8EoylCFOh/PAhPimBhqbtWJxX6iw== + dependencies: + "@sentry/types" "7.109.0" "@sinclair/typebox@^0.27.8": version "0.27.8" @@ -2641,9 +2687,9 @@ integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ== "@types/lodash@^4.14.168": - version "4.14.202" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8" - integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ== + version "4.17.0" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.0.tgz#d774355e41f372d5350a4d0714abb48194a489c3" + integrity sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA== "@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.2": version "0.1.4" @@ -2690,9 +2736,9 @@ undici-types "~5.26.4" "@types/node@18": - version "18.19.17" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.17.tgz#a581a9fb4b2cfdbc61f008804f4436b2d5c40354" - integrity sha512-SzyGKgwPzuWp2SHhlpXKzCX0pIOfcI4V2eF37nNBJOhwlegQ83omtVQ1XxZpDE06V/d6AQvfQdPfnw0tRC//Ng== + version "18.19.29" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.29.tgz#e7e9d796c1e195be7e7daf82b4abc50d017fb9db" + integrity sha512-5pAX7ggTmWZdhUrhRWLPf+5oM7F80bcKVCBbr0zwEkTNzTJL2CWQjznpFgHYy6GrzkYi2Yjy7DHKoynFxqPV8g== dependencies: undici-types "~5.26.4" @@ -2806,9 +2852,9 @@ integrity sha512-/wdoPq1QqkSj9/QOeKkFquEuPzQbHTWAMPH/PaUMB+JuR31lXhlWXRZ52IpfDYVlDOUBvX09uBrPwxGT1hjNBg== "@types/semver@^7.5.0": - version "7.5.6" - resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" - integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== + version "7.5.8" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.8.tgz#8268a8c57a3e4abd25c165ecd36237db7948a55e" + integrity sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ== "@types/send@*": version "0.17.4" @@ -2865,15 +2911,15 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^7.0.0": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.0.2.tgz#c13a34057be425167cc4a765158c46fdf2fd981d" - integrity sha512-/XtVZJtbaphtdrWjr+CJclaCVGPtOdBpFEnvtNf/jRV0IiEemRrL0qABex/nEt8isYcnFacm3nPHYQwL+Wb7qg== + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.5.0.tgz#1dc52fe48454d5b54be2d5f089680452f1628a5a" + integrity sha512-HpqNTH8Du34nLxbKgVMGljZMG0rJd2O9ecvr2QLYp+7512ty1j42KnsFwspPXg1Vh8an9YImf6CokUBltisZFQ== dependencies: "@eslint-community/regexpp" "^4.5.1" - "@typescript-eslint/scope-manager" "7.0.2" - "@typescript-eslint/type-utils" "7.0.2" - "@typescript-eslint/utils" "7.0.2" - "@typescript-eslint/visitor-keys" "7.0.2" + "@typescript-eslint/scope-manager" "7.5.0" + "@typescript-eslint/type-utils" "7.5.0" + "@typescript-eslint/utils" "7.5.0" + "@typescript-eslint/visitor-keys" "7.5.0" debug "^4.3.4" graphemer "^1.4.0" ignore "^5.2.4" @@ -2882,14 +2928,14 @@ ts-api-utils "^1.0.1" "@typescript-eslint/parser@^7.0.0": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.0.2.tgz#95c31233d343db1ca1df8df7811b5b87ca7b1a68" - integrity sha512-GdwfDglCxSmU+QTS9vhz2Sop46ebNCXpPPvsByK7hu0rFGRHL+AusKQJ7SoN+LbLh6APFpQwHKmDSwN35Z700Q== - dependencies: - "@typescript-eslint/scope-manager" "7.0.2" - "@typescript-eslint/types" "7.0.2" - "@typescript-eslint/typescript-estree" "7.0.2" - "@typescript-eslint/visitor-keys" "7.0.2" + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.5.0.tgz#1eeff36309ac2253c905dd4a88b4b71b72a358ed" + integrity sha512-cj+XGhNujfD2/wzR1tabNsidnYRaFfEkcULdcIyVBYcXjBvBKOes+mpMBP7hMpOyk+gBcfXsrg4NBGAStQyxjQ== + dependencies: + "@typescript-eslint/scope-manager" "7.5.0" + "@typescript-eslint/types" "7.5.0" + "@typescript-eslint/typescript-estree" "7.5.0" + "@typescript-eslint/visitor-keys" "7.5.0" debug "^4.3.4" "@typescript-eslint/scope-manager@5.62.0": @@ -2900,21 +2946,21 @@ "@typescript-eslint/types" "5.62.0" "@typescript-eslint/visitor-keys" "5.62.0" -"@typescript-eslint/scope-manager@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.0.2.tgz#6ec4cc03752758ddd1fdaae6fbd0ed9a2ca4fe63" - integrity sha512-l6sa2jF3h+qgN2qUMjVR3uCNGjWw4ahGfzIYsCtFrQJCjhbrDPdiihYT8FnnqFwsWX+20hK592yX9I2rxKTP4g== +"@typescript-eslint/scope-manager@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.5.0.tgz#70f0a7361430ab1043a5f97386da2a0d8b2f4d56" + integrity sha512-Z1r7uJY0MDeUlql9XJ6kRVgk/sP11sr3HKXn268HZyqL7i4cEfrdFuSSY/0tUqT37l5zT0tJOsuDP16kio85iA== dependencies: - "@typescript-eslint/types" "7.0.2" - "@typescript-eslint/visitor-keys" "7.0.2" + "@typescript-eslint/types" "7.5.0" + "@typescript-eslint/visitor-keys" "7.5.0" -"@typescript-eslint/type-utils@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.0.2.tgz#a7fc0adff0c202562721357e7478207d380a757b" - integrity sha512-IKKDcFsKAYlk8Rs4wiFfEwJTQlHcdn8CLwLaxwd6zb8HNiMcQIFX9sWax2k4Cjj7l7mGS5N1zl7RCHOVwHq2VQ== +"@typescript-eslint/type-utils@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.5.0.tgz#a8faa403232da3a3901655387c7082111f692cf9" + integrity sha512-A021Rj33+G8mx2Dqh0nMO9GyjjIBK3MqgVgZ2qlKf6CJy51wY/lkkFqq3TqqnH34XyAHUkq27IjlUkWlQRpLHw== dependencies: - "@typescript-eslint/typescript-estree" "7.0.2" - "@typescript-eslint/utils" "7.0.2" + "@typescript-eslint/typescript-estree" "7.5.0" + "@typescript-eslint/utils" "7.5.0" debug "^4.3.4" ts-api-utils "^1.0.1" @@ -2923,10 +2969,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.62.0.tgz#258607e60effa309f067608931c3df6fed41fd2f" integrity sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ== -"@typescript-eslint/types@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.0.2.tgz#b6edd108648028194eb213887d8d43ab5750351c" - integrity sha512-ZzcCQHj4JaXFjdOql6adYV4B/oFOFjPOC9XYwCaZFRvqN8Llfvv4gSxrkQkd2u4Ci62i2c6W6gkDwQJDaRc4nA== +"@typescript-eslint/types@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.5.0.tgz#0a284bcdef3cb850ec9fd57992df9f29d6bde1bc" + integrity sha512-tv5B4IHeAdhR7uS4+bf8Ov3k793VEVHd45viRRkehIUZxm0WF82VPiLgHzA/Xl4TGPg1ZD49vfxBKFPecD5/mg== "@typescript-eslint/typescript-estree@5.62.0": version "5.62.0" @@ -2941,13 +2987,13 @@ semver "^7.3.7" tsutils "^3.21.0" -"@typescript-eslint/typescript-estree@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.0.2.tgz#3c6dc8a3b9799f4ef7eca0d224ded01974e4cb39" - integrity sha512-3AMc8khTcELFWcKcPc0xiLviEvvfzATpdPj/DXuOGIdQIIFybf4DMT1vKRbuAEOFMwhWt7NFLXRkbjsvKZQyvw== +"@typescript-eslint/typescript-estree@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.5.0.tgz#aa5031c511874420f6b5edd90f8e4021525ee776" + integrity sha512-YklQQfe0Rv2PZEueLTUffiQGKQneiIEKKnfIqPIOxgM9lKSZFCjT5Ad4VqRKj/U4+kQE3fa8YQpskViL7WjdPQ== dependencies: - "@typescript-eslint/types" "7.0.2" - "@typescript-eslint/visitor-keys" "7.0.2" + "@typescript-eslint/types" "7.5.0" + "@typescript-eslint/visitor-keys" "7.5.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -2955,17 +3001,17 @@ semver "^7.5.4" ts-api-utils "^1.0.1" -"@typescript-eslint/utils@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.0.2.tgz#8756123054cd934c8ba7db6a6cffbc654b10b5c4" - integrity sha512-PZPIONBIB/X684bhT1XlrkjNZJIEevwkKDsdwfiu1WeqBxYEEdIgVDgm8/bbKHVu+6YOpeRqcfImTdImx/4Bsw== +"@typescript-eslint/utils@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.5.0.tgz#bbd963647fbbe9ffea033f42c0fb7e89bb19c858" + integrity sha512-3vZl9u0R+/FLQcpy2EHyRGNqAS/ofJ3Ji8aebilfJe+fobK8+LbIFmrHciLVDxjDoONmufDcnVSF38KwMEOjzw== dependencies: "@eslint-community/eslint-utils" "^4.4.0" "@types/json-schema" "^7.0.12" "@types/semver" "^7.5.0" - "@typescript-eslint/scope-manager" "7.0.2" - "@typescript-eslint/types" "7.0.2" - "@typescript-eslint/typescript-estree" "7.0.2" + "@typescript-eslint/scope-manager" "7.5.0" + "@typescript-eslint/types" "7.5.0" + "@typescript-eslint/typescript-estree" "7.5.0" semver "^7.5.4" "@typescript-eslint/utils@^5.10.0": @@ -2990,12 +3036,12 @@ "@typescript-eslint/types" "5.62.0" eslint-visitor-keys "^3.3.0" -"@typescript-eslint/visitor-keys@7.0.2": - version "7.0.2" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.0.2.tgz#2899b716053ad7094962beb895d11396fc12afc7" - integrity sha512-8Y+YiBmqPighbm5xA2k4wKTxRzx9EkBu7Rlw+WHqMvRJ3RPz/BMBO9b2ru0LUNmXg120PHUXD5+SWFy2R8DqlQ== +"@typescript-eslint/visitor-keys@7.5.0": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.5.0.tgz#8abcac66f93ef20b093e87a400c2d21e3a6d55ee" + integrity sha512-mcuHM/QircmA6O7fy6nn2w/3ditQkj+SgtOc8DW3uQ10Yfj42amm2i+6F2K4YAOPNNTmE6iM1ynM6lrSwdendA== dependencies: - "@typescript-eslint/types" "7.0.2" + "@typescript-eslint/types" "7.5.0" eslint-visitor-keys "^3.4.1" "@ungap/structured-clone@^1.2.0": @@ -3010,11 +3056,13 @@ dependencies: svg2vectordrawable "^2.9.1" -"@vector-im/compound-web@^3.1.1": - version "3.1.1" - resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-3.1.1.tgz#4f3267e8c860475eb69de37e375950dc77a649a8" - integrity sha512-s+YQsMi5DotbHy47zP9Mrz19a4Vb0HF76JoHAita7QJkSqx+w/p1NECH4WTUnklbe8W3T5kVwSuwEx9eV8c2ZA== +"@vector-im/compound-web@^3.3.1": + version "3.3.1" + resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-3.3.1.tgz#f5d69255fa62472626e0ed71b7176b09f21cbcaf" + integrity sha512-V9CQfaMyKdsWxC1D4Wz08Xh0ge3SnaOBf5SSIp1+uwoJTPyfEFHKgqbZl536SHBvVBc9M9IYg+3+lPB8xkFRFA== dependencies: + "@floating-ui/react" "^0.26.9" + "@floating-ui/react-dom" "^2.0.8" "@radix-ui/react-context-menu" "^2.1.5" "@radix-ui/react-dropdown-menu" "^2.0.6" "@radix-ui/react-form" "^0.0.3" @@ -3217,15 +3265,7 @@ aria-query@^5.0.0, aria-query@^5.3.0: dependencies: dequal "^2.0.3" -array-buffer-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" - integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== - dependencies: - call-bind "^1.0.2" - is-array-buffer "^3.0.1" - -array-buffer-byte-length@^1.0.1: +array-buffer-byte-length@^1.0.0, 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== @@ -3254,6 +3294,18 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +array.prototype.findlast@^1.2.4: + version "1.2.5" + resolved "https://registry.yarnpkg.com/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz#3e4fbcb30a15a7f5bf64cf2faae22d139c2e4904" + integrity sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-errors "^1.3.0" + es-object-atoms "^1.0.0" + es-shim-unscopables "^1.0.2" + array.prototype.findlastindex@^1.2.3: version "1.2.3" resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" @@ -3275,7 +3327,7 @@ array.prototype.flat@^1.3.1, array.prototype.flat@^1.3.2: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.flatmap@^1.3.1, array.prototype.flatmap@^1.3.2: +array.prototype.flatmap@^1.3.2: version "1.3.2" resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== @@ -3285,29 +3337,26 @@ array.prototype.flatmap@^1.3.1, array.prototype.flatmap@^1.3.2: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.tosorted@^1.1.1: +array.prototype.toreversed@^1.1.2: version "1.1.2" - resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.2.tgz#620eff7442503d66c799d95503f82b475745cefd" - integrity sha512-HuQCHOlk1Weat5jzStICBCd83NxiIMwqDg/dHEsoefabn/hJRj5pVdWcPUSpRrwhwxZOsQassMpgN/xRYFBMIg== + resolved "https://registry.yarnpkg.com/array.prototype.toreversed/-/array.prototype.toreversed-1.1.2.tgz#b989a6bf35c4c5051e1dc0325151bf8088954eba" + integrity sha512-wwDCoT4Ck4Cz7sLtgUmzR5UV3YF5mFHUlbChCzZBQZ+0m2cl/DH3tKgvphv1nKgFsJ48oCSg6p91q2Vm0I/ZMA== dependencies: call-bind "^1.0.2" define-properties "^1.2.0" es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" - get-intrinsic "^1.2.1" -arraybuffer.prototype.slice@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" - integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== +array.prototype.tosorted@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.3.tgz#c8c89348337e51b8a3c48a9227f9ce93ceedcba8" + integrity sha512-/DdH4TiTmOKzyQbp/eadcCVexiCb36xJg7HshYOYJnNZFDj33GEv0P7GxsynpShhq4OLYJzbGcBDkLsDt7MnNg== dependencies: - array-buffer-byte-length "^1.0.0" - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" - is-array-buffer "^3.0.2" - is-shared-array-buffer "^1.0.2" + call-bind "^1.0.5" + define-properties "^1.2.1" + es-abstract "^1.22.3" + es-errors "^1.1.0" + es-shim-unscopables "^1.0.2" arraybuffer.prototype.slice@^1.0.3: version "1.0.3" @@ -3354,12 +3403,7 @@ asynckit@^0.4.0: resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== -available-typed-arrays@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" - integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== - -available-typed-arrays@^1.0.6: +available-typed-arrays@^1.0.5, available-typed-arrays@^1.0.6, available-typed-arrays@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz#a5cc375d6a03c2efc87a553f3e0b1522def14846" integrity sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ== @@ -3371,16 +3415,21 @@ await-lock@^2.1.0: resolved "https://registry.yarnpkg.com/await-lock/-/await-lock-2.2.2.tgz#a95a9b269bfd2f69d22b17a321686f551152bcef" integrity sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw== -axe-core@4.8.4, axe-core@~4.8.4: - version "4.8.4" - resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.4.tgz#90db39a2b316f963f00196434d964e6e23648643" - integrity sha512-CZLSKisu/bhJ2awW4kJndluz2HLZYIHh5Uy1+ZwDRkJi69811xgIXXfdU9HSLX0Th+ILrHj8qfL/5wzamsFtQg== +axe-core@4.9.0: + version "4.9.0" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.9.0.tgz#b18971494551ab39d4ff5f7d4c6411bd20cc7c2a" + integrity sha512-H5orY+M2Fr56DWmMFpMrq5Ge93qjNdPVqzBv5gWK3aD1OvjBEJlEzxf09z93dGVQeI0LiW+aCMIx1QtShC/zUw== axe-core@=4.7.0: version "4.7.0" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.7.0.tgz#34ba5a48a8b564f67e103f0aa5768d76e15bbbbf" integrity sha512-M0JtH+hlOL5pLQwHOLNYZaXuhqmvS8oExsqB1SBYgA4Dk7u/xx+YdGHXaK5pyUfed5mYXdlYiphWq3G8cRi5JQ== +axe-core@~4.8.4: + version "4.8.4" + resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.8.4.tgz#90db39a2b316f963f00196434d964e6e23648643" + integrity sha512-CZLSKisu/bhJ2awW4kJndluz2HLZYIHh5Uy1+ZwDRkJi69811xgIXXfdU9HSLX0Th+ILrHj8qfL/5wzamsFtQg== + axobject-query@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" @@ -3422,29 +3471,29 @@ babel-plugin-jest-hoist@^29.6.3: "@types/babel__core" "^7.1.14" "@types/babel__traverse" "^7.0.6" -babel-plugin-polyfill-corejs2@^0.4.8: - version "0.4.8" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.8.tgz#dbcc3c8ca758a290d47c3c6a490d59429b0d2269" - integrity sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg== +babel-plugin-polyfill-corejs2@^0.4.10: + version "0.4.10" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.10.tgz#276f41710b03a64f6467433cab72cbc2653c38b1" + integrity sha512-rpIuu//y5OX6jVU+a5BCn1R5RSZYWAl2Nar76iwaOdycqb6JPxediskWFMMl7stfwNJR4b7eiQvh5fB5TEQJTQ== dependencies: "@babel/compat-data" "^7.22.6" - "@babel/helper-define-polyfill-provider" "^0.5.0" + "@babel/helper-define-polyfill-provider" "^0.6.1" semver "^6.3.1" -babel-plugin-polyfill-corejs3@^0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.9.0.tgz#9eea32349d94556c2ad3ab9b82ebb27d4bf04a81" - integrity sha512-7nZPG1uzK2Ymhy/NbaOWTg3uibM2BmGASS4vHS4szRZAIR8R6GwA/xAujpdrXU5iyklrimWnLWU+BLF9suPTqg== +babel-plugin-polyfill-corejs3@^0.10.1, babel-plugin-polyfill-corejs3@^0.10.4: + version "0.10.4" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.4.tgz#789ac82405ad664c20476d0233b485281deb9c77" + integrity sha512-25J6I8NGfa5YkCDogHRID3fVCadIR8/pGl1/spvCkzb6lVn6SR3ojpx9nOn9iEBcUsjY24AmdKm5khcfKdylcg== dependencies: - "@babel/helper-define-polyfill-provider" "^0.5.0" - core-js-compat "^3.34.0" + "@babel/helper-define-polyfill-provider" "^0.6.1" + core-js-compat "^3.36.1" -babel-plugin-polyfill-regenerator@^0.5.5: - version "0.5.5" - resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.5.5.tgz#8b0c8fc6434239e5d7b8a9d1f832bb2b0310f06a" - integrity sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg== +babel-plugin-polyfill-regenerator@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.1.tgz#4f08ef4c62c7a7f66a35ed4c0d75e30506acc6be" + integrity sha512-JfTApdE++cgcTWjsiCQlLyFBMbTUft9ja17saCc93lgV33h4tuCVj7tlvu//qpLwaG+3yEz7/KhahGrUMkVq9g== dependencies: - "@babel/helper-define-polyfill-provider" "^0.5.0" + "@babel/helper-define-polyfill-provider" "^0.6.1" babel-preset-current-node-syntax@^1.0.0: version "1.0.1" @@ -3498,9 +3547,9 @@ big.js@^5.2.2: integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== binary-extensions@^2.0.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" - integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== blob-polyfill@^7.0.0: version "7.0.20220408" @@ -3512,13 +3561,13 @@ blurhash@^2.0.3: resolved "https://registry.yarnpkg.com/blurhash/-/blurhash-2.0.5.tgz#efde729fc14a2f03571a6aa91b49cba80d1abe4b" integrity sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w== -body-parser@1.20.1: - version "1.20.1" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.1.tgz#b1812a8912c195cd371a3ee5e66faa2338a5c668" - integrity sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw== +body-parser@1.20.2: + version "1.20.2" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.2.tgz#6feb0e21c4724d06de7ff38da36dad4f57a747fd" + integrity sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA== dependencies: bytes "3.1.2" - content-type "~1.0.4" + content-type "~1.0.5" debug "2.6.9" depd "2.0.0" destroy "1.2.0" @@ -3526,7 +3575,7 @@ body-parser@1.20.1: iconv-lite "0.4.24" on-finished "2.4.1" qs "6.11.0" - raw-body "2.5.1" + raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" @@ -3567,13 +3616,13 @@ browserslist@^4.21.3: node-releases "^2.0.8" update-browserslist-db "^1.0.10" -browserslist@^4.22.2: - version "4.22.3" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.22.3.tgz#299d11b7e947a6b843981392721169e27d60c5a6" - integrity sha512-UAp55yfwNv0klWNapjs/ktHoguxuQNGnOzxYmfnXIS+8AsRDZkSDxg7R1AX3GKzn078SBI5dzwzj/Yx0Or0e3A== +browserslist@^4.22.2, browserslist@^4.22.3, browserslist@^4.23.0: + version "4.23.0" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.0.tgz#8f3acc2bbe73af7213399430890f86c63a5674ab" + integrity sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ== dependencies: - caniuse-lite "^1.0.30001580" - electron-to-chromium "^1.4.648" + caniuse-lite "^1.0.30001587" + electron-to-chromium "^1.4.668" node-releases "^2.0.14" update-browserslist-db "^1.0.13" @@ -3606,16 +3655,7 @@ bytes@3.1.2: resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.2.tgz#8b0beeb98605adf1b128fa4386403c009e0221a5" integrity sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg== -call-bind@^1.0.0, call-bind@^1.0.2, call-bind@^1.0.4, call-bind@^1.0.5: - version "1.0.5" - resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" - integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== - dependencies: - function-bind "^1.1.2" - get-intrinsic "^1.2.1" - set-function-length "^1.1.1" - -call-bind@^1.0.6, call-bind@^1.0.7: +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== @@ -3646,10 +3686,10 @@ caniuse-lite@^1.0.30001449: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001486.tgz#56a08885228edf62cbe1ac8980f2b5dae159997e" integrity sha512-uv7/gXuHi10Whlj0pp5q/tsK/32J2QSqVRKQhs2j8VsDCjgyruAh/eEXHF822VqO9yT6iZKw3nRwZRSPBE9OQg== -caniuse-lite@^1.0.30001580: - version "1.0.30001583" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001583.tgz#abb2970cc370801dc7e27bf290509dc132cfa390" - integrity sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q== +caniuse-lite@^1.0.30001587: + version "1.0.30001605" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001605.tgz#ca12d7330dd8bcb784557eb9aa64f0037870d9d6" + integrity sha512-nXwGlFWo34uliI9z3n6Qc0wZaf7zaZWA1CPZ169La5mV3I/gem7bst0vr5XQH5TJXZIMfDeZyOrZnSlVzKxxHQ== chalk@5.2.0: version "5.2.0" @@ -3692,9 +3732,9 @@ charenc@0.0.2: integrity sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA== chokidar@^3.4.0: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== dependencies: anymatch "~3.1.2" braces "~3.0.2" @@ -3857,7 +3897,7 @@ content-disposition@0.5.4: dependencies: safe-buffer "5.2.1" -content-type@^1.0.4, content-type@~1.0.4: +content-type@^1.0.4, content-type@~1.0.4, content-type@~1.0.5: version "1.0.5" resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== @@ -3877,17 +3917,24 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ== -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== -core-js-compat@^3.31.0, core-js-compat@^3.34.0: - version "3.35.1" - resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.35.1.tgz#215247d7edb9e830efa4218ff719beb2803555e2" - integrity sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw== +core-js-compat@^3.31.0, core-js-compat@^3.36.1: + version "3.36.1" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.1.tgz#1818695d72c99c25d621dca94e6883e190cea3c8" + integrity sha512-Dk997v9ZCt3X/npqzyGdTlq6t7lDBhZwGvV94PKzDArjp7BTRm7WlDAXYd/OWdeFHO8OChQYRJNJvUCqCbrtKA== dependencies: - browserslist "^4.22.2" + browserslist "^4.23.0" + +core-js-compat@^3.34.0: + version "3.36.0" + resolved "https://registry.yarnpkg.com/core-js-compat/-/core-js-compat-3.36.0.tgz#087679119bc2fdbdefad0d45d8e5d307d45ba190" + integrity sha512-iV9Pd/PsgjNWBXeq8XRtWVSgz2tKAfhfvBs7qxYty+RlRd+OCksaWmOnc4JKrTc1cToXL1N0s3l/vwlxPtdElw== + dependencies: + browserslist "^4.22.3" core-js@^3.0.0: version "3.30.0" @@ -4064,6 +4111,33 @@ data-urls@^3.0.2: whatwg-mimetype "^3.0.0" whatwg-url "^11.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== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +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== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + is-data-view "^1.0.1" + +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== + dependencies: + call-bind "^1.0.6" + es-errors "^1.3.0" + is-data-view "^1.0.1" + date-names@^0.1.11: version "0.1.13" resolved "https://registry.yarnpkg.com/date-names/-/date-names-0.1.13.tgz#c4358f6f77c8056e2f5ea68fdbb05f0bf1e53bd0" @@ -4139,16 +4213,7 @@ deepmerge@^4.2.2: resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a" integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== -define-data-property@^1.0.1, define-data-property@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" - integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== - dependencies: - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - -define-data-property@^1.1.2: +define-data-property@^1.0.1, define-data-property@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== @@ -4342,10 +4407,10 @@ electron-to-chromium@^1.4.284: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.385.tgz#1afd8d6280d510145148777b899ff481c65531ff" integrity sha512-L9zlje9bIw0h+CwPQumiuVlfMcV4boxRjFIWDcLfFqTZNbkwOExBzfmswytHawObQX4OUhtNv8gIiB21kOurIg== -electron-to-chromium@^1.4.648: - version "1.4.655" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.655.tgz#112410db0d7f9c2b4ed8baa3b1b548522a6f89d4" - integrity sha512-2yszojF7vIZ68adIOvzV4bku8OZad9w5H9xF3ZAMZjPuOjBarlflUkjN6DggdV+L71WZuKUfKUhov/34+G5QHg== +electron-to-chromium@^1.4.668: + version "1.4.724" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.724.tgz#e0a86fe4d3d0e05a4d7b032549d79608078f830d" + integrity sha512-RTRvkmRkGhNBPPpdrgtDKvmOEYTrPlXDfc0J/Nfq5s29tEahAwhiX4mmhNzj6febWMleulxVYPh7QwCSL/EldA== emittery@^0.13.1: version "0.13.1" @@ -4424,7 +4489,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -es-abstract@^1.17.5, es-abstract@^1.22.3: +es-abstract@^1.17.5: version "1.22.4" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.4.tgz#26eb2e7538c3271141f5754d31aabfdb215f27bf" integrity sha512-vZYJlk2u6qHYxBOTjAeg7qUxHdNfih64Uu2J8QqWgXZ2cri0ZpJAkzDUK/q593+mvKwlxyaxr6F1Q+3LKoQRgg== @@ -4511,50 +4576,104 @@ es-abstract@^1.18.3: unbox-primitive "^1.0.2" which-typed-array "^1.1.9" -es-abstract@^1.22.1: - version "1.22.3" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" - integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== +es-abstract@^1.22.1, es-abstract@^1.22.3: + version "1.22.5" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.5.tgz#1417df4e97cc55f09bf7e58d1e614bc61cb8df46" + integrity sha512-oW69R+4q2wG+Hc3KZePPZxOiisRIqfKBVo/HLx94QcJeWGU/8sZhCvc829rd1kS366vlJbzBfXf9yWwf0+Ko7w== dependencies: - array-buffer-byte-length "^1.0.0" - arraybuffer.prototype.slice "^1.0.2" - available-typed-arrays "^1.0.5" - call-bind "^1.0.5" - es-set-tostringtag "^2.0.1" + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + es-define-property "^1.0.0" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" es-to-primitive "^1.2.1" function.prototype.name "^1.1.6" - get-intrinsic "^1.2.2" - get-symbol-description "^1.0.0" + get-intrinsic "^1.2.4" + get-symbol-description "^1.0.2" globalthis "^1.0.3" gopd "^1.0.1" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" has-symbols "^1.0.3" - hasown "^2.0.0" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" + hasown "^2.0.1" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" is-callable "^1.2.7" - is-negative-zero "^2.0.2" + is-negative-zero "^2.0.3" is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" + is-shared-array-buffer "^1.0.3" is-string "^1.0.7" - is-typed-array "^1.1.12" + is-typed-array "^1.1.13" is-weakref "^1.0.2" object-inspect "^1.13.1" object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.5.1" - safe-array-concat "^1.0.1" - safe-regex-test "^1.0.0" + object.assign "^4.1.5" + regexp.prototype.flags "^1.5.2" + safe-array-concat "^1.1.0" + safe-regex-test "^1.0.3" string.prototype.trim "^1.2.8" string.prototype.trimend "^1.0.7" string.prototype.trimstart "^1.0.7" - typed-array-buffer "^1.0.0" - typed-array-byte-length "^1.0.0" - typed-array-byte-offset "^1.0.0" - typed-array-length "^1.0.4" + 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.5" unbox-primitive "^1.0.2" - which-typed-array "^1.1.13" + which-typed-array "^1.1.14" + +es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2: + version "1.23.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.2.tgz#693312f3940f967b8dd3eebacb590b01712622e0" + integrity sha512-60s3Xv2T2p1ICykc7c+DNDPLDMm9t4QxCOUU0K9JxiLjM3C1zB9YVdN7tjxrFd4+AkZ8CdX1ovUga4P2+1e+/w== + dependencies: + array-buffer-byte-length "^1.0.1" + arraybuffer.prototype.slice "^1.0.3" + 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" + 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" + has-property-descriptors "^1.0.2" + has-proto "^1.0.3" + has-symbols "^1.0.3" + hasown "^2.0.2" + internal-slot "^1.0.7" + is-array-buffer "^3.0.4" + 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" + 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" + string.prototype.trimstart "^1.0.7" + 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.5" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.15" es-define-property@^1.0.0: version "1.0.0" @@ -4563,7 +4682,7 @@ es-define-property@^1.0.0: dependencies: get-intrinsic "^1.2.4" -es-errors@^1.2.1, es-errors@^1.3.0: +es-errors@^1.1.0, es-errors@^1.2.1, 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== @@ -4583,7 +4702,7 @@ es-get-iterator@^1.1.3: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: +es-iterator-helpers@^1.0.15: version "1.0.15" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.15.tgz#bd81d275ac766431d19305923707c3efd9f1ae40" integrity sha512-GhoY8uYqd6iwUl2kgjTm4CZAf6oo5mHK7BPqx3rKgx893YSsy0LGHV6gfqqQvZt/8xM8xeOnfXBCfqclMKkJ5g== @@ -4603,16 +4722,34 @@ es-iterator-helpers@^1.0.12, es-iterator-helpers@^1.0.15: iterator.prototype "^1.1.2" safe-array-concat "^1.0.1" -es-set-tostringtag@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz#11f7cc9f63376930a5f20be4915834f4bc74f9c9" - integrity sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q== +es-iterator-helpers@^1.0.17: + version "1.0.18" + resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.18.tgz#4d3424f46b24df38d064af6fbbc89274e29ea69d" + integrity sha512-scxAJaewsahbqTYrGKJihhViaM6DDZDDoucfvzNbK0pOren1g/daDQ3IAhzn+1G14rBG7w+i5N+qul60++zlKA== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-errors "^1.3.0" + es-set-tostringtag "^2.0.3" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + globalthis "^1.0.3" + 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.2" + safe-array-concat "^1.1.2" + +es-object-atoms@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-object-atoms/-/es-object-atoms-1.0.0.tgz#ddb55cd47ac2e240701260bc2a8e31ecb643d941" + integrity sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw== dependencies: - get-intrinsic "^1.2.2" - has-tostringtag "^1.0.0" - hasown "^2.0.0" + es-errors "^1.3.0" -es-set-tostringtag@^2.0.2: +es-set-tostringtag@^2.0.1, es-set-tostringtag@^2.0.2, 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== @@ -4621,7 +4758,7 @@ es-set-tostringtag@^2.0.2: has-tostringtag "^1.0.2" hasown "^2.0.1" -es-shim-unscopables@^1.0.0: +es-shim-unscopables@^1.0.0, es-shim-unscopables@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz#1f6942e71ecc7835ed1c8a83006d8771a63a3763" integrity sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw== @@ -4638,9 +4775,9 @@ es-to-primitive@^1.2.1: is-symbol "^1.0.2" escalade@^3.1.1: - version "3.1.1" - resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" - integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + version "3.1.2" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.2.tgz#54076e9ab29ea5bf3d8f1ed62acffbb88272df27" + integrity sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA== escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" @@ -4767,26 +4904,28 @@ eslint-plugin-react-hooks@^4.3.0: integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g== eslint-plugin-react@^7.28.0: - version "7.33.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608" - integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw== + version "7.34.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.1.tgz#6806b70c97796f5bbfb235a5d3379ece5f4da997" + integrity sha512-N97CxlouPT1AHt8Jn0mhhN2RrADlUAsk1/atcT2KyA/l9Q/E6ll7OIGwNumFmWfZ9skV3XXccYS19h80rHtgkw== dependencies: - array-includes "^3.1.6" - array.prototype.flatmap "^1.3.1" - array.prototype.tosorted "^1.1.1" + array-includes "^3.1.7" + array.prototype.findlast "^1.2.4" + array.prototype.flatmap "^1.3.2" + array.prototype.toreversed "^1.1.2" + array.prototype.tosorted "^1.1.3" doctrine "^2.1.0" - es-iterator-helpers "^1.0.12" + es-iterator-helpers "^1.0.17" estraverse "^5.3.0" jsx-ast-utils "^2.4.1 || ^3.0.0" minimatch "^3.1.2" - object.entries "^1.1.6" - object.fromentries "^2.0.6" - object.hasown "^1.1.2" - object.values "^1.1.6" + object.entries "^1.1.7" + object.fromentries "^2.0.7" + object.hasown "^1.1.3" + object.values "^1.1.7" prop-types "^15.8.1" - resolve "^2.0.0-next.4" + resolve "^2.0.0-next.5" semver "^6.3.1" - string.prototype.matchall "^4.0.8" + string.prototype.matchall "^4.0.10" eslint-plugin-unicorn@^51.0.0: version "51.0.1" @@ -4841,16 +4980,16 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4 resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== -eslint@8.56.0: - version "8.56.0" - resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" - integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== +eslint@8.57.0: + version "8.57.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.57.0.tgz#c786a6fd0e0b68941aaf624596fb987089195668" + integrity sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ== dependencies: "@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/regexpp" "^4.6.1" "@eslint/eslintrc" "^2.1.4" - "@eslint/js" "8.56.0" - "@humanwhocodes/config-array" "^0.11.13" + "@eslint/js" "8.57.0" + "@humanwhocodes/config-array" "^0.11.14" "@humanwhocodes/module-importer" "^1.0.1" "@nodelib/fs.walk" "^1.2.8" "@ungap/structured-clone" "^1.2.0" @@ -4977,16 +5116,16 @@ expect@^29.0.0, expect@^29.7.0: jest-util "^29.7.0" express@^4.18.2: - version "4.18.2" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59" - integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ== + version "4.19.2" + resolved "https://registry.yarnpkg.com/express/-/express-4.19.2.tgz#e25437827a3aa7f2a827bc8171bbbb664a356465" + integrity sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.1" + body-parser "1.20.2" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.5.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" @@ -5115,10 +5254,10 @@ file-saver@^2.0.5: resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== -filesize@10.1.0: - version "10.1.0" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.0.tgz#846f5cd8d16e073c5d6767651a8264f6149183cd" - integrity sha512-GTLKYyBSDz3nPhlLVPjPWZCnhkd9TrrRArNcy8Z+J2cqScB7h2McAzR6NBX6nYOoWafql0roY8hrocxnZBv9CQ== +filesize@10.1.1: + version "10.1.1" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.1.tgz#eb98ce885aa73741199748e70e5b7339cc22c5ff" + integrity sha512-L0cdwZrKlwZQkMSFnCflJ6J2Y+5egO/p3vgRSDQGxQt++QbUZe5gMbRO6kg6gzwQDPvq2Fk9AmoxUNfZ5gdqaQ== fill-range@^7.0.1: version "7.0.1" @@ -5181,13 +5320,12 @@ flat-cache@^3.0.4: rimraf "^3.0.2" flat-cache@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.0.tgz#d12437636f83bb8a12b8f300c36fd1614e1c7224" - integrity sha512-EryKbCE/wxpxKniQlyas6PY1I9vwtF3uCBweX+N8KYTCn3Y12RTGtQAJ/bd5pl7kxUAc8v/R3Ake/N17OZiFqA== + version "4.0.1" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-4.0.1.tgz#0ece39fcb14ee012f4b0410bd33dd9c1f011127c" + integrity sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw== dependencies: flatted "^3.2.9" keyv "^4.5.4" - rimraf "^5.0.5" flatted@^3.1.0: version "3.2.7" @@ -5195,9 +5333,9 @@ flatted@^3.1.0: integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== flatted@^3.2.9: - version "3.2.9" - resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.9.tgz#7eb4c67ca1ba34232ca9d2d93e9886e611ad7daf" - integrity sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ== + version "3.3.1" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.3.1.tgz#21db470729a6734d4997002f439cb308987f567a" + integrity sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw== focus-lock@^1.3.2: version "1.3.3" @@ -5309,17 +5447,7 @@ 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.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: - version "1.2.2" - resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" - integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== - dependencies: - function-bind "^1.1.2" - has-proto "^1.0.1" - has-symbols "^1.0.3" - hasown "^2.0.0" - -get-intrinsic@^1.2.3, get-intrinsic@^1.2.4: +get-intrinsic@^1.1.3, get-intrinsic@^1.2.0, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, 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== @@ -5345,15 +5473,7 @@ get-stream@^6.0.0, get-stream@^6.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-6.0.1.tgz#a262d8eef67aced57c2852ad6167526a43cbf7b7" integrity sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg== -get-symbol-description@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" - integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" - -get-symbol-description@^1.0.2: +get-symbol-description@^1.0.0, 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== @@ -5392,15 +5512,15 @@ glob-to-regexp@^0.4.0, glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^10.3.7: - version "10.3.10" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.10.tgz#0351ebb809fd187fe421ab96af83d3a70715df4b" - integrity sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g== + version "10.3.12" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.12.tgz#3a65c363c2e9998d220338e88a5f6ac97302960b" + integrity sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg== dependencies: foreground-child "^3.1.0" - jackspeak "^2.3.5" + jackspeak "^2.3.6" minimatch "^9.0.1" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" - path-scurry "^1.10.1" + minipass "^7.0.4" + path-scurry "^1.10.2" glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: version "7.2.3" @@ -5498,38 +5618,24 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== -has-property-descriptors@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz#52ba30b6c5ec87fd89fa574bc1c39125c6f65340" - integrity sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg== - dependencies: - get-intrinsic "^1.2.2" - -has-property-descriptors@^1.0.1, has-property-descriptors@^1.0.2: +has-property-descriptors@^1.0.0, has-property-descriptors@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== dependencies: es-define-property "^1.0.0" -has-proto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" - integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== +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-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-tostringtag@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" - integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== - dependencies: - has-symbols "^1.0.2" - -has-tostringtag@^1.0.1, has-tostringtag@^1.0.2: +has-tostringtag@^1.0.0, has-tostringtag@^1.0.1, 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== @@ -5541,17 +5647,10 @@ has@^1.0.3: resolved "https://registry.yarnpkg.com/has/-/has-1.0.4.tgz#2eb2860e000011dae4f1406a86fe80e530fb2ec6" integrity sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ== -hasown@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" - integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== - dependencies: - function-bind "^1.1.2" - -hasown@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.1.tgz#26f48f039de2c0f8d3356c223fb8d50253519faa" - integrity sha512-1/th4MHjnwncwXsIW6QMzlvYL9kG5e/CpVvLRZe4XPa8TOUNbCELqmvhDmnkNsAjwaG4+I8gJJL0JBvTTLO9qA== +hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== dependencies: function-bind "^1.1.2" @@ -5580,9 +5679,9 @@ html-encoding-sniffer@^3.0.0: whatwg-encoding "^2.0.0" html-entities@^2.0.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.4.0.tgz#edd0cee70402584c8c76cc2c0556db09d1f45061" - integrity sha512-igBTJcNNNhvZFRtm8uA6xMY6xYleeDwn3PeBCkDz7tHttv4F2hsDI2aPgNERWzvRcNYHNT3ymRaQzllmXj4YsQ== + version "2.5.2" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.5.2.tgz#201a3cf95d3a15be7099521620d19dfb4f65359f" + integrity sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA== html-escaper@^2.0.0: version "2.0.2" @@ -5656,7 +5755,7 @@ ieee754@^1.1.12: resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== -ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.0: +ignore@^5.2.0, ignore@^5.2.4, ignore@^5.3.1: version "5.3.1" resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== @@ -5715,7 +5814,7 @@ ini@^1.3.5: resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== -internal-slot@^1.0.4, internal-slot@^1.0.5: +internal-slot@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== @@ -5724,7 +5823,7 @@ internal-slot@^1.0.4, internal-slot@^1.0.5: hasown "^2.0.0" side-channel "^1.0.4" -internal-slot@^1.0.7: +internal-slot@^1.0.5, 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== @@ -5758,16 +5857,7 @@ is-arguments@^1.1.1: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" - integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.0" - is-typed-array "^1.1.10" - -is-array-buffer@^3.0.4: +is-array-buffer@^3.0.2, 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== @@ -5840,6 +5930,13 @@ is-core-module@^2.13.0, is-core-module@^2.13.1: dependencies: hasown "^2.0.0" +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== + dependencies: + 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" @@ -5890,15 +5987,20 @@ is-ip@^3.1.0: dependencies: ip-regex "^4.0.0" -is-map@^2.0.1, is-map@^2.0.2: +is-map@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.2.tgz#00922db8c9bf73e81b7a335827bc2a43f2b91127" integrity sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg== -is-negative-zero@^2.0.2: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" - integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== +is-map@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/is-map/-/is-map-2.0.3.tgz#ede96b7fe1e270b3c4465e3a465658764926d62e" + integrity sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw== + +is-negative-zero@^2.0.2, 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" @@ -5942,17 +6044,22 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -is-set@^2.0.1, is-set@^2.0.2: +is-set@^2.0.2: version "2.0.2" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.2.tgz#90755fa4c2562dc1c5d4024760d6119b94ca18ec" integrity sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g== -is-shared-array-buffer@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" - integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== +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== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" is-stream@^2.0.0: version "2.0.1" @@ -5983,24 +6090,17 @@ is-symbol@^1.0.2, is-symbol@^1.0.3: dependencies: has-symbols "^1.0.2" -is-typed-array@^1.1.10, is-typed-array@^1.1.12, is-typed-array@^1.1.9: - version "1.1.12" - resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" - integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== - dependencies: - which-typed-array "^1.1.11" - -is-typed-array@^1.1.13: +is-typed-array@^1.1.10, 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== dependencies: which-typed-array "^1.1.14" -is-weakmap@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/is-weakmap/-/is-weakmap-2.0.1.tgz#5008b59bdc43b698201d18f62b37b2ca243e8cf2" - integrity sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA== +is-weakmap@^2.0.2: + version "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" @@ -6009,13 +6109,13 @@ is-weakref@^1.0.2: dependencies: call-bind "^1.0.2" -is-weakset@^2.0.1: - version "2.0.2" - resolved "https://registry.yarnpkg.com/is-weakset/-/is-weakset-2.0.2.tgz#4569d67a747a1ce5a994dfd4ef6dcea76e7c0a1d" - integrity sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg== +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== dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.1.1" + call-bind "^1.0.7" + get-intrinsic "^1.2.4" isarray@^2.0.5: version "2.0.5" @@ -6101,7 +6201,7 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jackspeak@^2.3.5: +jackspeak@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== @@ -6644,9 +6744,9 @@ jwt-decode@4.0.0, jwt-decode@^4.0.0: integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== katex@^0.16.0: - version "0.16.9" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.9.tgz#bc62d8f7abfea6e181250f85a56e4ef292dcb1fa" - integrity sha512-fsSYjWS0EEOwvy81j3vRA8TEAhQhKiqO+FQaKWp0m39qwOzHVBgAUBIXWj1pB+O2W3fIpNa6Y9KSKCVbfPhyAQ== + version "0.16.10" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185" + integrity sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA== dependencies: commander "^8.3.0" @@ -6677,6 +6777,11 @@ known-css-properties@^0.29.0: resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.29.0.tgz#e8ba024fb03886f23cb882e806929f32d814158f" integrity sha512-Ne7wqW7/9Cz54PDt4I3tcV+hAyat8ypyOGzYRJQfdxnnjeWsTxt1cy8pjvvKeI5kfXuyvULyeeAvwvvtAX3ayQ== +known-css-properties@^0.30.0: + version "0.30.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.30.0.tgz#34dd1f39c805c65a6dfa6ea76206b20dc523dd96" + integrity sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ== + language-subtag-registry@^0.3.20: version "0.3.22" resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.22.tgz#2e1500861b2e457eba7e7ae86877cbd08fa1fd1d" @@ -6807,6 +6912,11 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +lru-cache@^10.2.0: + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -6821,11 +6931,6 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" -"lru-cache@^9.1.1 || ^10.0.0": - version "10.2.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" - integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== - lz-string@^1.4.4, lz-string@^1.5.0: version "1.5.0" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941" @@ -6910,13 +7015,13 @@ matrix-events-sdk@0.0.1: resolved "https://registry.yarnpkg.com/matrix-events-sdk/-/matrix-events-sdk-0.0.1.tgz#c8c38911e2cb29023b0bbac8d6f32e0de2c957dd" integrity sha512-1QEOsXO+bhyCroIe2/A5OwaxHvBm7EsSQ46DEDn8RBIfQwN5HWBpFvyWWR4QY0KHPPnnJdI99wgRiAl7Ad5qaA== -matrix-js-sdk@31.5.0: - version "31.5.0" - resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-31.5.0.tgz#42ddb6b7a914c2e403cb85d6c59e023f1166f224" - integrity sha512-d8Y/Vt6PdX8leSOQ06yoArJ1xMwCzxSb1H2GzW9mtOgXnHpeYvrAuPrYr32k5hfdUAJp0xPibSqDP+/+2kCnpg== +matrix-js-sdk@32.1.0: + version "32.1.0" + resolved "https://registry.yarnpkg.com/matrix-js-sdk/-/matrix-js-sdk-32.1.0.tgz#b5cb79cc838c450d44d01de1ac58b6cda63b20b9" + integrity sha512-+jRCQKOBuMvAz3nWsf5NGWpttByeC/gw1It1gCZLQsWix6jN1bkHiqwk6OOvcGj4I5ML2bOEbYEr46bcqFUouQ== dependencies: "@babel/runtime" "^7.12.5" - "@matrix-org/matrix-sdk-crypto-wasm" "^4.6.0" + "@matrix-org/matrix-sdk-crypto-wasm" "^4.9.0" another-json "^0.2.0" bs58 "^5.0.0" content-type "^1.0.4" @@ -6988,10 +7093,10 @@ memoize-one@^6.0.0: resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-6.0.0.tgz#b2591b871ed82948aee4727dc6abceeeac8c1045" integrity sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw== -meow@^13.1.0: - version "13.1.0" - resolved "https://registry.yarnpkg.com/meow/-/meow-13.1.0.tgz#62995b0e8c3951739fe6e0a4becdd4d0df23eb37" - integrity sha512-o5R/R3Tzxq0PJ3v3qcQJtSvSE9nKOLSAaDuuoMzDVuGTwHdccMWcYomh9Xolng2tjT6O/Y83d+0coVGof6tqmA== +meow@^13.2.0: + version "13.2.0" + resolved "https://registry.yarnpkg.com/meow/-/meow-13.2.0.tgz#6b7d63f913f984063b3cc261b6e8800c4cd3474f" + integrity sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA== merge-descriptors@1.0.1: version "1.0.1" @@ -7048,7 +7153,7 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== -minimatch@9.0.3, minimatch@^9.0.1: +minimatch@9.0.3: version "9.0.3" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== @@ -7062,12 +7167,19 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" +minimatch@^9.0.1: + version "9.0.4" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" + integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + dependencies: + brace-expansion "^2.0.1" + minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8, minimist@~1.2.5: version "1.2.8" resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0": +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: version "7.0.4" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.0.4.tgz#dbce03740f50a4786ba994c1fb908844d27b038c" integrity sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ== @@ -7208,7 +7320,7 @@ 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.12.3, object-inspect@^1.13.1, object-inspect@^1.9.0: +object-inspect@^1.12.3, object-inspect@^1.13.1: version "1.13.1" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== @@ -7236,23 +7348,24 @@ object.assign@^4.1.4, object.assign@^4.1.5: has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.6, object.entries@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.7.tgz#2b47760e2a2e3a752f39dd874655c61a7f03c131" - integrity sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA== +object.entries@^1.1.7: + version "1.1.8" + resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" + integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" -object.fromentries@^2.0.6, object.fromentries@^2.0.7: - version "2.0.7" - resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" - integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== +object.fromentries@^2.0.7: + version "2.0.8" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.8.tgz#f7195d8a9b97bd95cbc1999ea939ecd1a2b00c65" + integrity sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.2" + es-object-atoms "^1.0.0" object.groupby@^1.0.1: version "1.0.1" @@ -7264,7 +7377,7 @@ object.groupby@^1.0.1: es-abstract "^1.22.1" get-intrinsic "^1.2.1" -object.hasown@^1.1.2: +object.hasown@^1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/object.hasown/-/object.hasown-1.1.3.tgz#6a5f2897bb4d3668b8e79364f98ccf971bda55ae" integrity sha512-fFI4VcYpRHvSLXxP7yiZOMAd331cPfd2p7PFDVbgUsYOfCT3tICVqXWngbjr4m49OvsBwUBQ6O2uQoJvy3RexA== @@ -7273,13 +7386,13 @@ object.hasown@^1.1.2: es-abstract "^1.22.1" object.values@^1.1.6, object.values@^1.1.7: - version "1.1.7" - resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" - integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + version "1.2.0" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.2.0.tgz#65405a9d92cee68ac2d303002e0b8470a4d9ab1b" + integrity sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" oidc-client-ts@3.0.1, oidc-client-ts@^3.0.1: version "3.0.1" @@ -7448,12 +7561,12 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.10.1: - version "1.10.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.1.tgz#9ba6bf5aa8500fe9fd67df4f0d9483b2b0bfc698" - integrity sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ== +path-scurry@^1.10.2: + version "1.10.2" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.10.2.tgz#8f6357eb1239d5fa1da8b9f70e9c080675458ba7" + integrity sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA== dependencies: - lru-cache "^9.1.1 || ^10.0.0" + lru-cache "^10.2.0" minipass "^5.0.0 || ^6.0.2 || ^7.0.0" path-to-regexp@0.1.7: @@ -7513,17 +7626,17 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.41.2: - version "1.41.2" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.41.2.tgz#db22372c708926c697acc261f0ef8406606802d9" - integrity sha512-VaTvwCA4Y8kxEe+kfm2+uUUw5Lubf38RxF7FpBxLPmGe5sdNkSg5e3ChEigaGrX7qdqT3pt2m/98LiyvU2x6CA== +playwright-core@1.42.1: + version "1.42.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.42.1.tgz#13c150b93c940a3280ab1d3fbc945bc855c9459e" + integrity sha512-mxz6zclokgrke9p1vtdy/COWBH+eOZgYUVVU34C73M+4j4HLlQJHtfcqiqqxpP0o8HhMkflvfbquLX5dg6wlfA== -playwright@1.41.2: - version "1.41.2" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.41.2.tgz#4e760b1c79f33d9129a8c65cc27953be6dd35042" - integrity sha512-v0bOa6H2GJChDL8pAeLa/LZC4feoAMbSQm1/jF/ySsWWoaNItvrMP7GEkvEEFyCTUYKMxjQKaTSg5up7nR6/8A== +playwright@1.42.1: + version "1.42.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.42.1.tgz#79c828b51fe3830211137550542426111dc8239f" + integrity sha512-PgwB03s2DZBcNRoW+1w9E+VkLBxweib6KTXM0M3tkiT4jVxKSi6PmVJ591J+0u10LUrgxB7dLRbiJqO5s2QPMg== dependencies: - playwright-core "1.41.2" + playwright-core "1.42.1" optionalDependencies: fsevents "2.3.2" @@ -7582,6 +7695,14 @@ postcss-selector-parser@^6.0.15: cssesc "^3.0.0" util-deprecate "^1.0.2" +postcss-selector-parser@^6.0.16: + version "6.0.16" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.16.tgz#3b88b9f5c5abd989ef4e2fc9ec8eedd34b20fb04" + integrity sha512-A0RVJrX+IUkVZbW3ClroRWurercFhieevHB38sr2+l9eUClMqome3LmEmnhlNy+5Mr2EYN6B2Kaw9wYdd+VHiw== + dependencies: + cssesc "^3.0.0" + util-deprecate "^1.0.2" + postcss-value-parser@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" @@ -7596,19 +7717,19 @@ postcss@^8.3.11: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.33: - version "8.4.33" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.33.tgz#1378e859c9f69bf6f638b990a0212f43e2aaa742" - integrity sha512-Kkpbhhdjw2qQs2O2DGX+8m5OVqEcbB9HRBvuYM9pgrjEFUg30A9LmXNlTAUj4S9kgtGyrMbTzVjH7E+s5Re2yg== +postcss@^8.4.38: + version "8.4.38" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e" + integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A== dependencies: nanoid "^3.3.7" picocolors "^1.0.0" - source-map-js "^1.0.2" + source-map-js "^1.2.0" -posthog-js@1.106.0: - version "1.106.0" - resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.106.0.tgz#d107d1a0b252f337b6fe552c5755a4df4e1e8493" - integrity sha512-TjzyP/pbmttDJk8M7298LKWyXa5LQLJbc+OFvNJhznbUtSs+CW+k8vr5fXYjj2nF3biigG/TJgR0M3C7AgeXzQ== +posthog-js@1.116.6: + version "1.116.6" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.116.6.tgz#9a5c9f49230a76642f4c44d93b96710f886c2880" + integrity sha512-rvt8HxzJD4c2B/xsUa4jle8ApdqljeBI2Qqjp4XJMohQf18DXRyM6b96H5/UMs8jxYuZG14Er0h/kEIWeU6Fmw== dependencies: fflate "^0.4.8" preact "^10.19.3" @@ -7778,10 +7899,10 @@ range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" @@ -7843,9 +7964,9 @@ react-error-boundary@^3.1.0: "@babel/runtime" "^7.12.5" react-focus-lock@^2.5.1: - version "2.11.1" - resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.11.1.tgz#9d532b29107c760c68ddadc1baff1a36e69c1fe0" - integrity sha512-IXLwnTBrLTlKTpASZXqqXJ8oymWrgAlOfuuDYN4XCuN1YJ72dwX198UCaF1QqGUk5C3QOnlMik//n3ufcfe8Ig== + version "2.11.2" + resolved "https://registry.yarnpkg.com/react-focus-lock/-/react-focus-lock-2.11.2.tgz#dcc9a0dde630f0b9c694b823066f1b954c024422" + integrity sha512-DDTbEiov0+RthESPVSTIdAWPPKic+op3sCcP+icbMRobvQNt7LuAlJ3KoarqQv5sCgKArru3kXmlmFTa27/CdQ== dependencies: "@babel/runtime" "^7.0.0" focus-lock "^1.3.2" @@ -7882,9 +8003,9 @@ react-redux@^7.2.0: react-is "^17.0.2" react-remove-scroll-bar@^2.3.3: - version "2.3.4" - resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.4.tgz#53e272d7a5cb8242990c7f144c44d8bd8ab5afd9" - integrity sha512-63C4YQBUt0m6ALadE9XV56hV8BgJWDmmTPY758iIJjfQKt2nYwoUrPk0LXRXcB/yIj82T1/Ixfdpdk68LwIB0A== + version "2.3.5" + resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.5.tgz#cd2543b3ed7716c7c5b446342d21b0e0b303f47c" + integrity sha512-3cqjOqg6s0XbOjWvmasmqHch+RLxIEk2r/70rzGXuz3iIGQsQheEQyqYCBb5EECoD01Vo2SIbDqW4paLeLTASw== dependencies: react-style-singleton "^2.2.1" tslib "^2.0.0" @@ -7982,14 +8103,15 @@ redux@^4.0.0, redux@^4.0.4: "@babel/runtime" "^7.9.2" reflect.getprototypeof@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.4.tgz#aaccbf41aca3821b87bb71d9dcbc7ad0ba50a3f3" - integrity sha512-ECkTw8TmJwW60lOTR+ZkODISW6RQ8+2CL3COqtiJKLd6MmB45hN51HprHFziKLGkAuTGQhBb91V8cy+KHlaCjw== + version "1.0.6" + resolved "https://registry.yarnpkg.com/reflect.getprototypeof/-/reflect.getprototypeof-1.0.6.tgz#3ab04c32a8390b770712b7a8633972702d278859" + integrity sha512-fmfw4XgoDke3kdI6h4xcUz1dG8uaiv5q9gcEwLS4Pnth2kxT+GZ7YehS1JTMGBQmtV7Y4GFGbs2re2NqhdozUg== dependencies: - call-bind "^1.0.2" - define-properties "^1.2.0" - es-abstract "^1.22.1" - get-intrinsic "^1.2.1" + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.1" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" globalthis "^1.0.3" which-builtin-type "^1.1.3" @@ -8022,7 +8144,7 @@ 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.4.3, regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1: +regexp.prototype.flags@^1.4.3: version "1.5.1" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== @@ -8031,7 +8153,7 @@ regexp.prototype.flags@^1.4.3, regexp.prototype.flags@^1.5.0, regexp.prototype.f define-properties "^1.2.0" set-function-name "^2.0.0" -regexp.prototype.flags@^1.5.2: +regexp.prototype.flags@^1.5.0, regexp.prototype.flags@^1.5.1, regexp.prototype.flags@^1.5.2: version "1.5.2" resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz#138f644a3350f981a858c44f6bb1a61ff59be334" integrity sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw== @@ -8143,7 +8265,7 @@ resolve@^1.20.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" -resolve@^2.0.0-next.4: +resolve@^2.0.0-next.5: version "2.0.0-next.5" resolved "https://registry.yarnpkg.com/resolve/-/resolve-2.0.0-next.5.tgz#6b0ec3107e671e52b68cd068ef327173b90dc03c" integrity sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA== @@ -8174,7 +8296,7 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rimraf@^5.0.0, rimraf@^5.0.5: +rimraf@^5.0.0: version "5.0.5" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.5.tgz#9be65d2d6e683447d2e9013da2bf451139a61ccf" integrity sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A== @@ -8189,16 +8311,6 @@ run-parallel@^1.1.9: queue-microtask "^1.2.2" safe-array-concat@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" - integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-array-concat@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.1.0.tgz#8d0cae9cb806d6d1c06e08ab13d847293ebe0692" integrity sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg== @@ -8208,6 +8320,16 @@ safe-array-concat@^1.1.0: has-symbols "^1.0.3" isarray "^2.0.5" +safe-array-concat@^1.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== + dependencies: + call-bind "^1.0.7" + get-intrinsic "^1.2.4" + has-symbols "^1.0.3" + isarray "^2.0.5" + safe-buffer@5.2.1: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -8218,16 +8340,7 @@ safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-regex-test@^1.0.0: - version "1.0.1" - resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.1.tgz#207369b445fd007e534864635b28b2ae7b105783" - integrity sha512-Y5NejJTTliTyY4H7sipGqY+RX5P87i3F7c4Rcepy72nq+mNLhIsD0W4c7kEmduMDQCSqtPsXPlSTsFhh2LQv+g== - dependencies: - call-bind "^1.0.5" - get-intrinsic "^1.2.2" - is-regex "^1.1.4" - -safe-regex-test@^1.0.3: +safe-regex-test@^1.0.0, 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== @@ -8248,10 +8361,10 @@ sanitize-filename@^1.6.3: dependencies: truncate-utf8-bytes "^1.0.0" -sanitize-html@2.12.1: - version "2.12.1" - resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.12.1.tgz#280a0f5c37305222921f6f9d605be1f6558914c7" - integrity sha512-Plh+JAn0UVDpBRP/xEjsk+xDCoOvMBwQUf/K+/cBAVuTbtX8bj2VB7S1sL1dssVpykqp0/KPSesHrqXtokVBpA== +sanitize-html@2.13.0: + version "2.13.0" + resolved "https://registry.yarnpkg.com/sanitize-html/-/sanitize-html-2.13.0.tgz#71aedcdb777897985a4ea1877bf4f895a1170dae" + integrity sha512-Xff91Z+4Mz5QiNSLdLWwjgBDm5b1RU6xBT0+12rapjiaR7SwfRdjw8f+6Rir2MXKLrDicRFHdb51hGOAxmsUIA== dependencies: deepmerge "^4.2.2" escape-string-regexp "^4.0.0" @@ -8299,14 +8412,14 @@ semver@^6.3.0, semver@^6.3.1: resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== -semver@^7.3.7: +semver@^7.3.7, semver@^7.5.4: version "7.6.0" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d" integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg== dependencies: lru-cache "^6.0.0" -semver@^7.5.3, semver@^7.5.4: +semver@^7.5.3: version "7.5.4" resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== @@ -8347,36 +8460,27 @@ 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.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" - integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== - dependencies: - define-data-property "^1.1.1" - get-intrinsic "^1.2.1" - gopd "^1.0.1" - has-property-descriptors "^1.0.0" - set-function-length@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.1.tgz#47cc5945f2c771e2cf261c6737cf9684a2a5e425" - integrity sha512-j4t6ccc+VsKwYHso+kElc5neZpjtq9EnRICFZtWyBsLojhmeF/ZBd/elqm22WJh/BziDe/SBiOeAt0m2mfLD0g== + 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== dependencies: - define-data-property "^1.1.2" + define-data-property "^1.1.4" es-errors "^1.3.0" function-bind "^1.1.2" - get-intrinsic "^1.2.3" + get-intrinsic "^1.2.4" gopd "^1.0.1" - has-property-descriptors "^1.0.1" + has-property-descriptors "^1.0.2" set-function-name@^2.0.0, set-function-name@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" - integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + 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== dependencies: - define-data-property "^1.0.1" + define-data-property "^1.1.4" + es-errors "^1.3.0" functions-have-names "^1.2.3" - has-property-descriptors "^1.0.0" + has-property-descriptors "^1.0.2" setimmediate@^1.0.5: version "1.0.5" @@ -8408,13 +8512,14 @@ shebang-regex@^3.0.0: integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== side-channel@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" - integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + 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== dependencies: - call-bind "^1.0.0" - get-intrinsic "^1.0.2" - object-inspect "^1.9.0" + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" signal-exit@^3.0.3, signal-exit@^3.0.7: version "3.0.7" @@ -8450,7 +8555,12 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" -source-map-js@^1.0.1, source-map-js@^1.0.2: +source-map-js@^1.0.1, source-map-js@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af" + integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg== + +source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -8544,7 +8654,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8562,7 +8681,7 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" -string.prototype.matchall@^4.0.8: +string.prototype.matchall@^4.0.10: version "4.0.10" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.10.tgz#a1553eb532221d4180c51581d6072cd65d1ee100" integrity sha512-rGXbGmOEosIQi6Qva94HUjgPs9vKW+dkG7Y8Q5O2OYkWL6wFaTRZO8zM4mhP94uX55wgyrXzfS2aGtGzUL7EJQ== @@ -8585,7 +8704,7 @@ string.prototype.repeat@^1.0.0: define-properties "^1.1.3" es-abstract "^1.17.5" -string.prototype.trim@^1.2.7, string.prototype.trim@^1.2.8: +string.prototype.trim@^1.2.7: version "1.2.8" resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== @@ -8594,7 +8713,17 @@ string.prototype.trim@^1.2.7, string.prototype.trim@^1.2.8: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trimend@^1.0.6, string.prototype.trimend@^1.0.7: +string.prototype.trim@^1.2.8, 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== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-abstract "^1.23.0" + es-object-atoms "^1.0.0" + +string.prototype.trimend@^1.0.6: version "1.0.7" resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== @@ -8603,6 +8732,15 @@ string.prototype.trimend@^1.0.6, string.prototype.trimend@^1.0.7: define-properties "^1.2.0" es-abstract "^1.22.1" +string.prototype.trimend@^1.0.7, 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== + dependencies: + call-bind "^1.0.7" + define-properties "^1.2.1" + es-object-atoms "^1.0.0" + string.prototype.trimstart@^1.0.6, string.prototype.trimstart@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" @@ -8619,7 +8757,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -8673,9 +8818,9 @@ stylelint-config-standard@^36.0.0: stylelint-config-recommended "^14.0.0" stylelint-scss@^6.0.0: - version "6.1.0" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.1.0.tgz#b7ef162c417132e8df2b69d1759ae07395d54fb5" - integrity sha512-kCfK8TQzthGwb4vaZniZgxRsVbCM4ZckmT1b/H5m4FU3I8Dz0id9llKsy1NMp3XXqC8+OPD4rVKtUbSxXlJb5g== + version "6.2.1" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.2.1.tgz#7675f3f5034a3b1d7d064d480e0d834ef9353244" + integrity sha512-ZoGLbVb1keZYRVGQlhB8G6sZOoNqw61whzzzGFWp05N12ErqLFfBv3JPrXiMLZaW98sBS7K/vUQhRnvUj4vwdw== dependencies: known-css-properties "^0.29.0" postcss-media-query-parser "^0.2.3" @@ -8684,14 +8829,15 @@ stylelint-scss@^6.0.0: postcss-value-parser "^4.2.0" stylelint@^16.1.0: - version "16.2.1" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.2.1.tgz#895d6d42523c5126ec0895f0ca2a58febeb77e89" - integrity sha512-SfIMGFK+4n7XVAyv50CpVfcGYWG4v41y6xG7PqOgQSY8M/PgdK0SQbjWFblxjJZlN9jNq879mB4BCZHJRIJ1hA== - dependencies: - "@csstools/css-parser-algorithms" "^2.5.0" - "@csstools/css-tokenizer" "^2.2.3" - "@csstools/media-query-list-parser" "^2.1.7" - "@csstools/selector-specificity" "^3.0.1" + version "16.3.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-16.3.1.tgz#006cc6cd4bd8e7b3acb1607bb8e8de85121b7847" + integrity sha512-/JOwQnBvxEKOT2RtNgGpBVXnCSMBgKOL2k7w0K52htwCyJls4+cHvc4YZgXlVoAZS9QJd2DgYAiRnja96pTgxw== + dependencies: + "@csstools/css-parser-algorithms" "^2.6.1" + "@csstools/css-tokenizer" "^2.2.4" + "@csstools/media-query-list-parser" "^2.1.9" + "@csstools/selector-specificity" "^3.0.2" + "@dual-bundle/import-meta-resolve" "^4.0.0" balanced-match "^2.0.0" colord "^2.9.3" cosmiconfig "^9.0.0" @@ -8705,19 +8851,19 @@ stylelint@^16.1.0: globby "^11.1.0" globjoin "^0.1.4" html-tags "^3.3.1" - ignore "^5.3.0" + ignore "^5.3.1" imurmurhash "^0.1.4" is-plain-object "^5.0.0" - known-css-properties "^0.29.0" + known-css-properties "^0.30.0" mathml-tag-names "^2.1.3" - meow "^13.1.0" + meow "^13.2.0" micromatch "^4.0.5" normalize-path "^3.0.0" picocolors "^1.0.0" - postcss "^8.4.33" + postcss "^8.4.38" postcss-resolve-nested-selector "^0.1.1" postcss-safe-parser "^7.0.0" - postcss-selector-parser "^6.0.15" + postcss-selector-parser "^6.0.16" postcss-value-parser "^4.2.0" resolve-from "^5.0.0" string-width "^4.2.3" @@ -8822,10 +8968,15 @@ symbol-tree@^3.2.4: resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2" integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw== +tabbable@^6.0.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/tabbable/-/tabbable-6.2.0.tgz#732fb62bc0175cfcec257330be187dcfba1f3b97" + integrity sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew== + table@^6.8.1: - version "6.8.1" - resolved "https://registry.yarnpkg.com/table/-/table-6.8.1.tgz#ea2b71359fe03b017a5fbc296204471158080bdf" - integrity sha512-Y4X9zqrCftUhMeH2EptSSERdVKt/nEdijTOacGD/97EKjhQ/Qs8RTlEGABSJNNN8lac9kheH+af7yAkEWlgneA== + version "6.8.2" + resolved "https://registry.yarnpkg.com/table/-/table-6.8.2.tgz#c5504ccf201213fa227248bdc8c5569716ac6c58" + integrity sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA== dependencies: ajv "^8.0.1" lodash.truncate "^4.4.2" @@ -8921,9 +9072,9 @@ truncate-utf8-bytes@^1.0.0: utf8-byte-length "^1.0.1" ts-api-utils@^1.0.1: - version "1.0.3" - resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" - integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== + version "1.3.0" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.3.0.tgz#4b490e27129f1e8e686b45cc4ab63714dc60eea1" + integrity sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ== ts-node@^10.9.1: version "10.9.2" @@ -9011,16 +9162,7 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typed-array-buffer@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" - integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== - dependencies: - call-bind "^1.0.2" - get-intrinsic "^1.2.1" - is-typed-array "^1.1.10" - -typed-array-buffer@^1.0.1: +typed-array-buffer@^1.0.1, 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== @@ -9029,40 +9171,45 @@ typed-array-buffer@^1.0.1: es-errors "^1.3.0" is-typed-array "^1.1.13" -typed-array-byte-length@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" - integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== +typed-array-byte-length@^1.0.0, 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== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" -typed-array-byte-offset@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" - integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== +typed-array-byte-offset@^1.0.0, 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== dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" for-each "^0.3.3" - has-proto "^1.0.1" - is-typed-array "^1.1.10" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" -typed-array-length@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" - integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== +typed-array-length@^1.0.4, typed-array-length@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.5.tgz#57d44da160296d8663fd63180a1802ebf25905d5" + integrity sha512-yMi0PlwuznKHxKmcpoOdeLwxBoVPkqZxd7q2FgMkmD3bNwvF5VW0+UlUQ1k1vmktTu4Yu13Q0RIxEP8+B+wloA== dependencies: - call-bind "^1.0.2" + call-bind "^1.0.7" for-each "^0.3.3" - is-typed-array "^1.1.9" + gopd "^1.0.1" + has-proto "^1.0.3" + is-typed-array "^1.1.13" + possible-typed-array-names "^1.0.0" -typescript@5.3.3: - version "5.3.3" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" - integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== +typescript@5.4.3: + version "5.4.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.3.tgz#5c6fedd4c87bee01cd7a528a30145521f8e0feff" + integrity sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg== ua-parser-js@^1.0.2: version "1.0.37" @@ -9267,10 +9414,10 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -webcrypto-core@^1.7.8: - version "1.7.8" - resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.8.tgz#056918036e846c72cfebbb04052e283f57f1114a" - integrity sha512-eBR98r9nQXTqXt/yDRtInszPMjTaSAMJAFDg2AHsgrnczawT1asx9YNBX6k5p+MekbPF4+s/UJJrr88zsTqkSg== +webcrypto-core@^1.7.9: + version "1.7.9" + resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.7.9.tgz#a585f0032dbc88d202cff4f266cbef02ba48bd7a" + integrity sha512-FE+a4PPkOmBbgNDIyRmcHhgXn+2ClRl3JzJdDu/P4+B8y81LqKe6RAsI9b3lAOHe1T1BMkSjsRHTYRikImZnVA== dependencies: "@peculiar/asn1-schema" "^2.3.8" "@peculiar/json-schema" "^1.1.12" @@ -9365,32 +9512,21 @@ which-builtin-type@^1.1.3: which-typed-array "^1.1.9" which-collection@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.1.tgz#70eab71ebbbd2aefaf32f917082fc62cdcb70906" - integrity sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A== + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-collection/-/which-collection-1.0.2.tgz#627ef76243920a107e7ce8e96191debe4b16c2a0" + integrity sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw== dependencies: - is-map "^2.0.1" - is-set "^2.0.1" - is-weakmap "^2.0.1" - is-weakset "^2.0.1" + is-map "^2.0.3" + is-set "^2.0.3" + is-weakmap "^2.0.2" + is-weakset "^2.0.3" which-module@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" integrity sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q== -which-typed-array@^1.1.11, which-typed-array@^1.1.13, which-typed-array@^1.1.9: - version "1.1.13" - resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" - integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== - dependencies: - available-typed-arrays "^1.0.5" - call-bind "^1.0.4" - for-each "^0.3.3" - gopd "^1.0.1" - has-tostringtag "^1.0.0" - -which-typed-array@^1.1.14: +which-typed-array@^1.1.13: version "1.1.14" resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.14.tgz#1f78a111aee1e131ca66164d8bdc3ab062c95a06" integrity sha512-VnXFiIW8yNn9kIHN88xvZ4yOWchftKDsRJ8fEPacX/wl1lOvBrhsJ/OeJCXq7B0AaijRuqgzSKalJoPk+D8MPg== @@ -9401,6 +9537,17 @@ which-typed-array@^1.1.14: gopd "^1.0.1" has-tostringtag "^1.0.1" +which-typed-array@^1.1.14, which-typed-array@^1.1.15, which-typed-array@^1.1.9: + 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== + dependencies: + available-typed-arrays "^1.0.7" + call-bind "^1.0.7" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.2" + which@^1.3.1: version "1.3.1" resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" @@ -9415,8 +9562,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: - name wrap-ansi-cjs +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9434,6 +9580,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214"