From eb288987541fde244ba0d9c416c312a5947a1dfb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 25 Jun 2024 15:21:47 +0100 Subject: [PATCH 01/63] Reduce number of parallel runners for Playwright (#12695) --- .github/workflows/end-to-end-tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/end-to-end-tests.yaml b/.github/workflows/end-to-end-tests.yaml index 832e0d5f4e..ae99cf910e 100644 --- a/.github/workflows/end-to-end-tests.yaml +++ b/.github/workflows/end-to-end-tests.yaml @@ -103,7 +103,7 @@ jobs: fail-fast: false matrix: # Run multiple instances in parallel to speed up the tests - runner: [1, 2, 3, 4, 5, 6, 7, 8] + runner: [1, 2, 3, 4, 5, 6] steps: - uses: actions/checkout@v4 with: From 32a838496cc49b2c63075d7711c908ce696d2239 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:13:18 +0000 Subject: [PATCH 02/63] Update peter-evans/create-pull-request digest to 4e1beaa (#12680) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/playwright-image-updates.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright-image-updates.yaml b/.github/workflows/playwright-image-updates.yaml index 15bea28e0f..a31e99156d 100644 --- a/.github/workflows/playwright-image-updates.yaml +++ b/.github/workflows/playwright-image-updates.yaml @@ -20,7 +20,7 @@ jobs: - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5 + uses: peter-evans/create-pull-request@4e1beaa7521e8b457b572c090b25bd3db56bf1c5 # v5 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} branch: actions/playwright-image-updates From 4e6674bbfb4c4a1842ac6af13b706f9a1be15a11 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:14:04 +0000 Subject: [PATCH 03/63] Update dependency @sentry/browser to v8.11.0 (#12686) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 110 +++++++++++++++++++++++++++--------------------------- 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/yarn.lock b/yarn.lock index c834200d41..c495143fc1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2307,76 +2307,76 @@ dependencies: "@babel/runtime" "^7.13.10" -"@sentry-internal/browser-utils@8.9.2": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.9.2.tgz#36b077fcb1a4ee8f2ed67437b2d9030c4e9e7586" - integrity sha512-2A0A6TnfzFDvYCRWS9My3t+JKG6KlslhyaN35BTiOTlYDauEekyJP7BFFyeTJXCHm2BQgI8aRZhBKm+oR9QuYw== +"@sentry-internal/browser-utils@8.12.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.12.0.tgz#ddea4b1ed1ee798beccf71b5b531928f7bdfd082" + integrity sha512-h7HRqED15Qa+DRt8iZGna24Z331nglgjPzdFn4+u+jvnZrehUjH0vjsfuj7qhwSUNZu8Rxi1ZlUYFURjLDTKCA== dependencies: - "@sentry/core" "8.9.2" - "@sentry/types" "8.9.2" - "@sentry/utils" "8.9.2" + "@sentry/core" "8.12.0" + "@sentry/types" "8.12.0" + "@sentry/utils" "8.12.0" -"@sentry-internal/feedback@8.9.2": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.9.2.tgz#0afa4c630820b49125ad4b9ad2b38db10de81134" - integrity sha512-v04Q+08ohwautwmiDfK5hI+nFW2B/IYhBz7pZM9x1srkwmNA69XOFyo5u34TeVHhYOPbMM2Ubs0uNEcSWHgbbQ== +"@sentry-internal/feedback@8.12.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.12.0.tgz#c4ba284ad7ab8a611f5cde4f705df2888c686ae0" + integrity sha512-PvQ14wVOPmzRdYdmXD791CqERZZC4jZa5hnyBKBuF6ZpifIQ4Uk7spPu6ZO+Ympx3GtRlpYjk4dbjHyNSfYTwA== dependencies: - "@sentry/core" "8.9.2" - "@sentry/types" "8.9.2" - "@sentry/utils" "8.9.2" + "@sentry/core" "8.12.0" + "@sentry/types" "8.12.0" + "@sentry/utils" "8.12.0" -"@sentry-internal/replay-canvas@8.9.2": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.9.2.tgz#76ff2302f7dd6e3870a34b656e6b9b34e9275c18" - integrity sha512-vu9TssSjO+XbZjnoyYxMrBI4KgXG+zyqw3ThfPqG6o7O0BGa54fFwtZiMdGq/BHz017FuNiEz4fgtzuDd4gZJQ== +"@sentry-internal/replay-canvas@8.12.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.12.0.tgz#b3f473ff3000f9151cdfcd26e1cf07ce8e3d60b4" + integrity sha512-0slfHZ3TD3MKeBu5NEGuKuecxStX23gts5L3mGFJd/zwsd04A31fhVmo6agIkxnZbOU4GPX/7HPWIeevkvy3ig== dependencies: - "@sentry-internal/replay" "8.9.2" - "@sentry/core" "8.9.2" - "@sentry/types" "8.9.2" - "@sentry/utils" "8.9.2" + "@sentry-internal/replay" "8.12.0" + "@sentry/core" "8.12.0" + "@sentry/types" "8.12.0" + "@sentry/utils" "8.12.0" -"@sentry-internal/replay@8.9.2": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.9.2.tgz#35460590a4be71ba050fd49de95e3f8b0f27e50f" - integrity sha512-YPnrnXJd6mJpJspJ8pI8hd1KTMOxw+BARP5twiDwXlij1RTotwnNoX9UGaSm+ZPTexPD++6Zyp6xQf4vKKP3yg== +"@sentry-internal/replay@8.12.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.12.0.tgz#c518139ea6805dcc3d47c050d9857486166e6e21" + integrity sha512-TJceMtzRnY3SCvt3nFDu9rlT00Le7SaV2RL3D7SyDuijvJbWvIw3DRk7yutpF8c9YKO9j6FMa4NlkCJ+YAnnKQ== dependencies: - "@sentry-internal/browser-utils" "8.9.2" - "@sentry/core" "8.9.2" - "@sentry/types" "8.9.2" - "@sentry/utils" "8.9.2" + "@sentry-internal/browser-utils" "8.12.0" + "@sentry/core" "8.12.0" + "@sentry/types" "8.12.0" + "@sentry/utils" "8.12.0" "@sentry/browser@^8.0.0": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.9.2.tgz#4cfd63449f0038718b5435a4537f3d11123a396b" - integrity sha512-jI5XY4j8Sa+YteokI+4SW+A/ErZxPDnspjvV3dm5pIPWvEFhvDyXWZSepqaoqwo3L7fdkRMzXY8Bi4T7qDVMWg== + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.12.0.tgz#12dba1c7c54d74bba6830e6625f851d55c56bce8" + integrity sha512-H82dmr7KQWoS2DQc5dJko5wNepltcEro1EM4mBeL2YmVbNRtoZzD3HQTpbxJJuFsTvEMZevvez5HFlpUgxmIwQ== dependencies: - "@sentry-internal/browser-utils" "8.9.2" - "@sentry-internal/feedback" "8.9.2" - "@sentry-internal/replay" "8.9.2" - "@sentry-internal/replay-canvas" "8.9.2" - "@sentry/core" "8.9.2" - "@sentry/types" "8.9.2" - "@sentry/utils" "8.9.2" + "@sentry-internal/browser-utils" "8.12.0" + "@sentry-internal/feedback" "8.12.0" + "@sentry-internal/replay" "8.12.0" + "@sentry-internal/replay-canvas" "8.12.0" + "@sentry/core" "8.12.0" + "@sentry/types" "8.12.0" + "@sentry/utils" "8.12.0" -"@sentry/core@8.9.2": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.9.2.tgz#af0f2ec25b88da5467cf327d2ffcd555323c30e6" - integrity sha512-ixm8NISFlPlEo3FjSaqmq4nnd13BRHoafwJ5MG+okCz6BKGZ1SexEggP42/QpGvDprUUHnfncG6WUMgcarr1zA== +"@sentry/core@8.12.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.12.0.tgz#e1cbb5c0494db708ade84295f40360250709fd81" + integrity sha512-y+5Hlf/E45nj2adJy4aUCNBefQbyWIX66Z9bOM6JjnVB0hxCm5H0sYqrFKldYqaeZx6/Q2cgAcGs61krUxNerQ== dependencies: - "@sentry/types" "8.9.2" - "@sentry/utils" "8.9.2" + "@sentry/types" "8.12.0" + "@sentry/utils" "8.12.0" -"@sentry/types@8.9.2": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.9.2.tgz#d143383fc35552d9f153042cc6d56c5ee8ec2fa6" - integrity sha512-+LFOyQGl+zk5SZRGZD2MEURf7i5RHgP/mt3s85Rza+vz8M211WJ0YsjkIGUJFSY842nged5QLx4JysLaBlLymg== +"@sentry/types@8.12.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.12.0.tgz#a14608eddec270c994d86a06408c0d3e5b11f1f2" + integrity sha512-pKuW64IjgcklWAOHzPJ02Ej480hyL25TLnYCAfl2TDMrYc+N0bbbH1N7ZxqJpTSVK9IxZPY/t2TRxpQBiyPEcg== -"@sentry/utils@8.9.2": - version "8.9.2" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.9.2.tgz#58b003d9c1302f61192e7c99ea42bf1cd5cad7f7" - integrity sha512-A4srR9mEBFdVXwSEKjQ94msUbVkMr8JeFiEj9ouOFORw/Y/ux/WV2bWVD/ZI9wq0TcTNK8L1wBgU8UMS5lIq3A== +"@sentry/utils@8.12.0": + version "8.12.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.12.0.tgz#be6a6514a034a04bb8feb5556a90ac2b83aa9310" + integrity sha512-pwYMoOmexz3vsNSOJGPvD2qwp/fsPcr8mkFk67wMM37Y+30KQ8pF4Aq1cc+HBRIn1tKmenzFDPTczSdVPFxm3Q== dependencies: - "@sentry/types" "8.9.2" + "@sentry/types" "8.12.0" "@sinclair/typebox@^0.27.8": version "0.27.8" From 7da394bf1d1963c69f7f17155b4f517604d7d52c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:14:06 +0000 Subject: [PATCH 04/63] Update dependency @playwright/test to v1.45.0 (#12685) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/yarn.lock b/yarn.lock index c495143fc1..7ff4112bc4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1969,11 +1969,11 @@ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@playwright/test@^1.40.1": - version "1.44.1" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.44.1.tgz#cc874ec31342479ad99838040e99b5f604299bcb" - integrity sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q== + version "1.45.0" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.45.0.tgz#790a66165a46466c0d7099dd260881802f5aba7e" + integrity sha512-TVYsfMlGAaxeUllNkywbwek67Ncf8FRGn8ZlRdO291OL3NjG9oMbfVhyP82HQF0CZLMrYsvesqoUekxdWuF9Qw== dependencies: - playwright "1.44.1" + playwright "1.45.0" "@radix-ui/primitive@1.0.1": version "1.0.1" @@ -7619,17 +7619,17 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.44.1: - version "1.44.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.44.1.tgz#53ec975503b763af6fc1a7aa995f34bc09ff447c" - integrity sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA== +playwright-core@1.45.0: + version "1.45.0" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.45.0.tgz#5741a670b7c9060ce06852c0051d84736fb94edc" + integrity sha512-lZmHlFQ0VYSpAs43dRq1/nJ9G/6SiTI7VPqidld9TDefL9tX87bTKExWZZUF5PeRyqtXqd8fQi2qmfIedkwsNQ== -playwright@1.44.1: - version "1.44.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.44.1.tgz#5634369d777111c1eea9180430b7a184028e7892" - integrity sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg== +playwright@1.45.0: + version "1.45.0" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.45.0.tgz#400c709c64438690f13705cb9c88ef93089c5c27" + integrity sha512-4z3ac3plDfYzGB6r0Q3LF8POPR20Z8D0aXcxbJvmfMgSSq1hkcgvFRXJk9rUq5H/MJ0Ktal869hhOdI/zUTeLA== dependencies: - playwright-core "1.44.1" + playwright-core "1.45.0" optionalDependencies: fsevents "2.3.2" From 91779e0351ab70738166689d382b818396c079e6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:14:06 +0000 Subject: [PATCH 05/63] Update stylelint (#12684) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 39 +++++++++++++-------------------------- 1 file changed, 13 insertions(+), 26 deletions(-) diff --git a/yarn.lock b/yarn.lock index 7ff4112bc4..ca41fefdf4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6762,11 +6762,6 @@ kleur@^3.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e" integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w== -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== - known-css-properties@^0.31.0: version "0.31.0" resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.31.0.tgz#5c8d9d8777b3ca09482b2397f6a241e5d69a1023" @@ -7680,14 +7675,6 @@ postcss-scss@^4.0.4: resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.9.tgz#a03c773cd4c9623cb04ce142a52afcec74806685" integrity sha512-AjKOeiwAitL/MXxQW2DliT28EKukvvbEWx3LBmJIRN8KfBGZbRTxNYW0kSqi1COiTZ57nZ9NW06S6ux//N1c9A== -postcss-selector-parser@^6.0.15: - 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-selector-parser@^6.1.0: version "6.1.0" resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.1.0.tgz#49694cb4e7c649299fea510a29fa6577104bcf53" @@ -8825,27 +8812,27 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -stylelint-config-recommended@^14.0.0: - version "14.0.0" - resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-14.0.0.tgz#b395c7014838d2aaca1755eebd914d0bb5274994" - integrity sha512-jSkx290CglS8StmrLp2TxAppIajzIBZKYm3IxT89Kg6fGlxbPiTiyH9PS5YUuVAFwaJLl1ikiXX0QWjI0jmgZQ== +stylelint-config-recommended@^14.0.1: + version "14.0.1" + resolved "https://registry.yarnpkg.com/stylelint-config-recommended/-/stylelint-config-recommended-14.0.1.tgz#d25e86409aaf79ee6c6085c2c14b33c7e23c90c6" + integrity sha512-bLvc1WOz/14aPImu/cufKAZYfXs/A/owZfSMZ4N+16WGXLoX5lOir53M6odBxvhgmgdxCVnNySJmZKx73T93cg== stylelint-config-standard@^36.0.0: - version "36.0.0" - resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-36.0.0.tgz#6704c044d611edc12692d4a5e37b039a441604d4" - integrity sha512-3Kjyq4d62bYFp/Aq8PMKDwlgUyPU4nacXsjDLWJdNPRUgpuxALu1KnlAHIj36cdtxViVhXexZij65yM0uNIHug== + version "36.0.1" + resolved "https://registry.yarnpkg.com/stylelint-config-standard/-/stylelint-config-standard-36.0.1.tgz#727cbb2a1ef3e210f5ce8329cde531129f156609" + integrity sha512-8aX8mTzJ6cuO8mmD5yon61CWuIM4UD8Q5aBcWKGSf6kg+EC3uhB+iOywpTK4ca6ZL7B49en8yanOFtUW0qNzyw== dependencies: - stylelint-config-recommended "^14.0.0" + stylelint-config-recommended "^14.0.1" stylelint-scss@^6.0.0: - version "6.3.0" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.3.0.tgz#2020d0f0d21b8b4151f523e303ae8966728a6e54" - integrity sha512-8OSpiuf1xC7f8kllJsBOFAOYp/mR/C1FXMVeOFjtJPw+AFvEmC93FaklHt7MlOqU4poxuQ1TkYMyfI0V+1SxjA== + version "6.3.2" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-6.3.2.tgz#085072e774e5a31e65aa2acefaad5417a29d6ec1" + integrity sha512-pNk9mXOVKkQtd+SROPC9io8ISSgX+tOVPhFdBE+LaKQnJMLdWPbGKAGYv4Wmf/RrnOjkutunNTN9kKMhkdE5qA== dependencies: - known-css-properties "^0.30.0" + known-css-properties "^0.31.0" postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.1" - postcss-selector-parser "^6.0.15" + postcss-selector-parser "^6.1.0" postcss-value-parser "^4.2.0" stylelint@^16.1.0: From 3aba3f6fab354ceaa7c5fa45531db0bd7f1c3fa9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:14:19 +0000 Subject: [PATCH 06/63] Update dependency @types/node to v18.19.39 (#12682) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/yarn.lock b/yarn.lock index ca41fefdf4..1e38eafe59 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2745,9 +2745,9 @@ undici-types "~5.26.4" "@types/node@18": - version "18.19.36" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.36.tgz#c9861e84727e07ecf79a5ff6d0e14f91bab2b478" - integrity sha512-tX1BNmYSWEvViftB26VLNxT6mEr37M7+ldUtq7rlKnv4/2fKYsJIOmqJAjT6h1DNuwQjIKgw3VJ/Dtw3yiTIQw== + version "18.19.39" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.39.tgz#c316340a5b4adca3aee9dcbf05de385978590593" + integrity sha512-nPwTRDKUctxw3di5b4TfT3I0sWDiWoPQCZjXhvdkINntwr8lcoVCKsTgnXeRubKIlfnV+eN/HYk6Jb40tbcEAQ== dependencies: undici-types "~5.26.4" From 8977a05387b27c1c82eccd6f800dc704f9ba55d8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:15:55 +0000 Subject: [PATCH 07/63] Update matrix-org (#12683) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index e3a9099527..71d053d3a8 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@babel/runtime": "^7.12.5", "@matrix-org/analytics-events": "^0.23.0", "@matrix-org/emojibase-bindings": "^1.1.2", - "@matrix-org/matrix-wysiwyg": "2.37.3", + "@matrix-org/matrix-wysiwyg": "2.37.4", "@matrix-org/olm": "3.2.15", "@matrix-org/react-sdk-module-api": "^2.4.0", "@matrix-org/spec": "^1.7.0", diff --git a/yarn.lock b/yarn.lock index 1e38eafe59..72fee8d8e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1881,10 +1881,10 @@ resolved "https://registry.yarnpkg.com/@matrix-org/matrix-sdk-crypto-wasm/-/matrix-sdk-crypto-wasm-5.0.0.tgz#f45a7bccaad218c05bcf9e7c8ca783c9d9a07af4" integrity sha512-37ASjCKSTU5ycGfkP+LUXG4Ok6OAf6vE+1qU6uwWhe6FwadCS3vVWzJYd/3d9BQFwsx4GhFTIAXrW4iLG85rmQ== -"@matrix-org/matrix-wysiwyg@2.37.3": - version "2.37.3" - resolved "https://registry.yarnpkg.com/@matrix-org/matrix-wysiwyg/-/matrix-wysiwyg-2.37.3.tgz#3f068252948f036b3d233828aecf856f74f9d7f1" - integrity sha512-WGDZi9ksgkEXS2WlOqGloc9vbgLYVNN/gBhXihAjFtPwix0qEhDSIfzplyQO24WrPpq//PSnXlEFShWhJH0OIg== +"@matrix-org/matrix-wysiwyg@2.37.4": + version "2.37.4" + resolved "https://registry.yarnpkg.com/@matrix-org/matrix-wysiwyg/-/matrix-wysiwyg-2.37.4.tgz#bd9b46051a21c9986477e3a83a1417b1ee926d81" + integrity sha512-4OtBWAHNAOu9P5C6jOIeHlu4ChwV2YusxnbGuN20IceC4bT2h38flZQgm0x9/jgHfF0LwnKUwKXsxtRoq8xW0g== "@matrix-org/olm@3.2.15": version "3.2.15" @@ -1899,9 +1899,9 @@ "@babel/runtime" "^7.17.9" "@matrix-org/spec@^1.7.0": - version "1.10.1" - resolved "https://registry.yarnpkg.com/@matrix-org/spec/-/spec-1.10.1.tgz#6c62a7ee4524224c29fe39e67b33983e70c99944" - integrity sha512-ryNSzJkaJi/fwp6AQ6ujS9oqJtw60e+/+llIzwJhbuWTr1V07B6KfUA44+bFrudIFmfghdOuxRfzUnWOQ2K6gw== + version "1.11.0" + resolved "https://registry.yarnpkg.com/@matrix-org/spec/-/spec-1.11.0.tgz#73864eab965c81a4c8c48ca0da8c9d94e8efd5dc" + integrity sha512-80000pCXpUnt3ue910uZY70kLo9b7pNfrUrlXY5smpDjfycEs1oztUAriPAnKxMp31gUqt9/tfjmBM2H/LNCZw== "@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3": version "2.1.8-no-fsevents.3" From 8c3cc6159e6c12c15b8740bd74ac2c575b84d2fe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:16:19 +0000 Subject: [PATCH 08/63] Update dependency @vector-im/compound-web to v4.10.0 (#12687) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 498 +++++++++++++++++++++++++++--------------------------- 1 file changed, 253 insertions(+), 245 deletions(-) diff --git a/yarn.lock b/yarn.lock index 72fee8d8e8..110fcad299 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,20 +1283,13 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" 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.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": +"@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.24.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== dependencies: regenerator-runtime "^0.14.0" -"@babel/runtime@^7.13.10": - version "7.24.6" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.6.tgz#5b76eb89ad45e2e4a0a8db54c456251469a3358e" - integrity sha512-Ja18XcETdEl5mzzACGd+DKgaGJzPTCow7EglgwTmHdwokzDFYh/MHua6lU6DV/hjF2IaOJ4oX2nqnjG7RElKOw== - dependencies: - regenerator-runtime "^0.14.0" - "@babel/template@^7.22.15": version "7.24.0" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50" @@ -1491,24 +1484,24 @@ integrity sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g== "@floating-ui/core@^1.0.0": - version "1.6.2" - resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.2.tgz#d37f3e0ac1f1c756c7de45db13303a266226851a" - integrity sha512-+2XpQV9LLZeanU4ZevzRnGFg2neDeKHgFLjP6YLW+tly0IvrhqT4u8enLGjLH3qeh85g19xY5rsAusfwTdn5lg== + version "1.6.3" + resolved "https://registry.yarnpkg.com/@floating-ui/core/-/core-1.6.3.tgz#5e7bb92843f47fd1d8dcb9b3cc3c243aaed54f95" + integrity sha512-1ZpCvYf788/ZXOhRQGFxnYQOVgeU+pi0i+d0Ow34La7qjIXETi6RNswGVKkA6KcDO8/+Ysu2E/CeUmmeEBDvTg== dependencies: - "@floating-ui/utils" "^0.2.0" + "@floating-ui/utils" "^0.2.3" "@floating-ui/dom@^1.0.0": - version "1.6.5" - resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.5.tgz#323f065c003f1d3ecf0ff16d2c2c4d38979f4cb9" - integrity sha512-Nsdud2X65Dz+1RHjAIP0t8z5e2ff/IRbei6BqFrl1urT8sDVzM1HMQ+R0XcU5ceRfyO3I6ayeqIfh+6Wb8LGTw== + version "1.6.6" + resolved "https://registry.yarnpkg.com/@floating-ui/dom/-/dom-1.6.6.tgz#be54c1ab2d19112ad323e63dbeb08185fed0ffd3" + integrity sha512-qiTYajAnh3P+38kECeffMSQgbvXty2VB6rS+42iWR4FPIlZjLK84E9qtLnMTLIpPz2znD/TaFqaiavMUrS+Hcw== dependencies: "@floating-ui/core" "^1.0.0" - "@floating-ui/utils" "^0.2.0" + "@floating-ui/utils" "^0.2.3" "@floating-ui/react-dom@^2.0.0", "@floating-ui/react-dom@^2.0.8": - version "2.1.0" - resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.0.tgz#4f0e5e9920137874b2405f7d6c862873baf4beff" - integrity sha512-lNzj5EQmEKn5FFKc04+zasr09h/uX8RtJRNj5gUXsSQIXHVWTVh+hVAg1vOMCexkX8EgvemMvIFpQfkosnVNyA== + version "2.1.1" + resolved "https://registry.yarnpkg.com/@floating-ui/react-dom/-/react-dom-2.1.1.tgz#cca58b6b04fc92b4c39288252e285e0422291fb0" + integrity sha512-4h84MJt3CHrtG18mGsXuLCHMrug49d7DFkU0RMIyshRveBeyV2hmV/pDaF2Uxtu8kgq5r46llp5E5FQiR0K2Yg== dependencies: "@floating-ui/dom" "^1.0.0" @@ -1521,10 +1514,10 @@ "@floating-ui/utils" "^0.2.0" tabbable "^6.0.0" -"@floating-ui/utils@^0.2.0": - version "0.2.2" - resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.2.tgz#d8bae93ac8b815b2bd7a98078cf91e2724ef11e5" - integrity sha512-J4yDIIthosAsRZ5CPYP/jQvUAQtlZTTD/4suA08/FEnlxqW3sKS9iAhgsa9VYLZ6vDHn/ixJgIqRQPotoBjxIw== +"@floating-ui/utils@^0.2.0", "@floating-ui/utils@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@floating-ui/utils/-/utils-0.2.3.tgz#506fcc73f730affd093044cb2956c31ba6431545" + integrity sha512-XGndio0l5/Gvd6CLIABvsav9HHezgDFFhDfHk1bvLfr9ni8dojqLSvBbotJEjmIwNHL7vK4QzBJTdBRoB+c1ww== "@humanwhocodes/config-array@^0.11.14": version "0.11.14" @@ -1982,24 +1975,27 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-arrow@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.0.3.tgz#c24f7968996ed934d57fe6cde5d6ec7266e1d25d" - integrity sha512-wSP+pHsB/jQRaL6voubsQ/ZlrGBHHrOjmBnr19hxYgtS0WvAFwZhK2WP/YY5yF9uKECCEEDGxuLxq1NBK51wFA== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.3" +"@radix-ui/primitive@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.0.tgz#42ef83b3b56dccad5d703ae8c42919a68798bbe2" + integrity sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA== -"@radix-ui/react-collection@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.0.3.tgz#9595a66e09026187524a36c6e7e9c7d286469159" - integrity sha512-3SzW+0PW7yBBoQlT8wNcGtaxaD0XSu0uLUFgrtHY08Acx05TaHaOmVLR73c0j/cqpDy53KBMO7s0dx2wmOIDIA== +"@radix-ui/react-arrow@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz#744f388182d360b86285217e43b6c63633f39e7a" + integrity sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-slot" "1.0.2" + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/react-collection@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-collection/-/react-collection-1.1.0.tgz#f18af78e46454a2360d103c2251773028b7724ed" + integrity sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" "@radix-ui/react-compose-refs@1.0.1": version "1.0.1" @@ -2008,18 +2004,22 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-compose-refs@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz#656432461fc8283d7b591dcf0d79152fae9ecc74" + integrity sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw== + "@radix-ui/react-context-menu@^2.1.5": - version "2.1.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.1.5.tgz#1bdbd72761439f9166f75dc4598f276265785c83" - integrity sha512-R5XaDj06Xul1KGb+WP8qiOh7tKJNz2durpLBXAGZjSVtctcRFCuEvy2gtMwRJGePwQQE5nV77gs4FwRi8T+r2g== + version "2.2.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context-menu/-/react-context-menu-2.2.1.tgz#a2c7812336a40cd22900c888336ad6e1adc6a1bc" + integrity sha512-wvMKKIeb3eOrkJ96s722vcidZ+2ZNfcYZWBPRHIB1VWrF+fiF851Io6LX0kmK5wTDQFKdulCCKJk2c3SBaQHvA== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-menu" "2.0.6" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-menu" "2.1.1" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" "@radix-ui/react-context@1.0.1": version "1.0.1" @@ -2028,76 +2028,73 @@ dependencies: "@babel/runtime" "^7.13.10" +"@radix-ui/react-context@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-context/-/react-context-1.1.0.tgz#6df8d983546cfd1999c8512f3a8ad85a6e7fcee8" + integrity sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A== + "@radix-ui/react-dialog@^1.0.4": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.0.5.tgz#71657b1b116de6c7a0b03242d7d43e01062c7300" - integrity sha512-GjWJX/AUpB703eEBanuBnIWdIXg6NvJFCXcNlSZk4xdszCdhrJgBoUd1cGk67vFO+WdA2pfI/plOpqz/5GUP6Q== + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.1.tgz#4906507f7b4ad31e22d7dad69d9330c87c431d44" + integrity sha512-zysS+iU4YP3STKNS6USvFVqI4qqx8EpiwmT5TuCApVEBca+eRCbONi4EgzfNSuVnOXvC5UPHHMjs8RXO6DH9Bg== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-dismissable-layer" "1.0.5" - "@radix-ui/react-focus-guards" "1.0.1" - "@radix-ui/react-focus-scope" "1.0.4" - "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-portal" "1.0.4" - "@radix-ui/react-presence" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-slot" "1.0.2" - "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" aria-hidden "^1.1.1" - react-remove-scroll "2.5.5" + react-remove-scroll "2.5.7" -"@radix-ui/react-direction@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.0.1.tgz#9cb61bf2ccf568f3421422d182637b7f47596c9b" - integrity sha512-RXcvnXgyvYvBEOhCBuddKecVkoMiI10Jcm5cTI7abJRAHYfFxeu+FBQs/DvdxSYucxR5mna0dNsL6QFlds5TMA== - dependencies: - "@babel/runtime" "^7.13.10" +"@radix-ui/react-direction@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-direction/-/react-direction-1.1.0.tgz#a7d39855f4d077adc2a1922f9c353c5977a09cdc" + integrity sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg== -"@radix-ui/react-dismissable-layer@1.0.5": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.0.5.tgz#3f98425b82b9068dfbab5db5fff3df6ebf48b9d4" - integrity sha512-aJeDjQhywg9LBu2t/At58hCvr7pEm0o2Ke1x33B+MhjNmmZ17sy4KImo0KPLgsnc/zN7GPdce8Cnn0SWvwZO7g== +"@radix-ui/react-dismissable-layer@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz#2cd0a49a732372513733754e6032d3fb7988834e" + integrity sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - "@radix-ui/react-use-escape-keydown" "1.0.3" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-escape-keydown" "1.1.0" "@radix-ui/react-dropdown-menu@^2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.0.6.tgz#cdf13c956c5e263afe4e5f3587b3071a25755b63" - integrity sha512-i6TuFOoWmLWq+M/eCLGd/bQ2HfAX1RJgvrBQ6AQLmzfvsLdefxbWu8G9zczcPFfcSPehz9GcpF6K9QYreFV8hA== + version "2.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-dropdown-menu/-/react-dropdown-menu-2.1.1.tgz#3dc578488688250dbbe109d9ff2ca28a9bca27ec" + integrity sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-menu" "2.0.6" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-menu" "2.1.1" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-controllable-state" "1.1.0" -"@radix-ui/react-focus-guards@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.0.1.tgz#1ea7e32092216b946397866199d892f71f7f98ad" - integrity sha512-Rect2dWbQ8waGzhMavsIbmSVCgYxkXLxxR3ZvCX79JOglzdEy4JXMb98lq4hPxUbLr77nP0UOGf4rcMU+s1pUA== - dependencies: - "@babel/runtime" "^7.13.10" +"@radix-ui/react-focus-guards@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-guards/-/react-focus-guards-1.1.0.tgz#8e9abb472a9a394f59a1b45f3dd26cfe3fc6da13" + integrity sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw== -"@radix-ui/react-focus-scope@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.0.4.tgz#2ac45fce8c5bb33eb18419cdc1905ef4f1906525" - integrity sha512-sL04Mgvf+FmyvZeYfNu1EPAaaxD+aw7cYeIB9L9Fvq8+urhltTRaEo5ysKOpHuKPclsZcSUMKlN05x4u+CINpA== +"@radix-ui/react-focus-scope@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.0.tgz#ebe2891a298e0a33ad34daab2aad8dea31caf0b2" + integrity sha512-200UD8zylvEyL8Bx+z76RJnASR2gRMuxlgFCPAe/Q/679a/r0eK3MBVYMb7vZODZcffZBdob1EGnky78xmVvcA== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-form@^0.0.3": version "0.0.3" @@ -2120,6 +2117,13 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-use-layout-effect" "1.0.1" +"@radix-ui/react-id@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-id/-/react-id-1.1.0.tgz#de47339656594ad722eb87f94a6b25f9cffae0ed" + integrity sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA== + dependencies: + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-label@2.0.2": version "2.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-label/-/react-label-2.0.2.tgz#9c72f1d334aac996fdc27b48a8bdddd82108fb6d" @@ -2128,64 +2132,61 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-primitive" "1.0.3" -"@radix-ui/react-menu@2.0.6": - version "2.0.6" - resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.0.6.tgz#2c9e093c1a5d5daa87304b2a2f884e32288ae79e" - integrity sha512-BVkFLS+bUC8HcImkRKPSiVumA1VPOOEC5WBMiT+QAVsPzW1FJzI9KnqgGxVDPBcql5xXrHkD3JOVoXWEXD8SYA== +"@radix-ui/react-menu@2.1.1": + version "2.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-menu/-/react-menu-2.1.1.tgz#bd623ace0e1ae1ac78023a505fec0541d59fb346" + integrity sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-collection" "1.0.3" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-direction" "1.0.1" - "@radix-ui/react-dismissable-layer" "1.0.5" - "@radix-ui/react-focus-guards" "1.0.1" - "@radix-ui/react-focus-scope" "1.0.4" - "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-popper" "1.1.3" - "@radix-ui/react-portal" "1.0.4" - "@radix-ui/react-presence" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-roving-focus" "1.0.4" - "@radix-ui/react-slot" "1.0.2" - "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-focus-guards" "1.1.0" + "@radix-ui/react-focus-scope" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-roving-focus" "1.1.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-callback-ref" "1.1.0" aria-hidden "^1.1.1" - react-remove-scroll "2.5.5" + react-remove-scroll "2.5.7" -"@radix-ui/react-popper@1.1.3": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.1.3.tgz#24c03f527e7ac348fabf18c89795d85d21b00b42" - integrity sha512-cKpopj/5RHZWjrbF2846jBNacjQVwkP068DfmgrNJXpvVWrOvlAmE9xSiy5OqeE+Gi8D9fP+oDhUnPqNMY8/5w== +"@radix-ui/react-popper@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-popper/-/react-popper-1.2.0.tgz#a3e500193d144fe2d8f5d5e60e393d64111f2a7a" + integrity sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg== dependencies: - "@babel/runtime" "^7.13.10" "@floating-ui/react-dom" "^2.0.0" - "@radix-ui/react-arrow" "1.0.3" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - "@radix-ui/react-use-layout-effect" "1.0.1" - "@radix-ui/react-use-rect" "1.0.1" - "@radix-ui/react-use-size" "1.0.1" - "@radix-ui/rect" "1.0.1" + "@radix-ui/react-arrow" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" + "@radix-ui/react-use-rect" "1.1.0" + "@radix-ui/react-use-size" "1.1.0" + "@radix-ui/rect" "1.1.0" -"@radix-ui/react-portal@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.0.4.tgz#df4bfd353db3b1e84e639e9c63a5f2565fb00e15" - integrity sha512-Qki+C/EuGUVCQTOTD5vzJzJuMUlewbzuKyUy+/iHM2uwGiru9gZeBJtHAPKAEkB5KWGi9mP/CHKcY0wt1aW45Q== +"@radix-ui/react-portal@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.1.tgz#1957f1eb2e1aedfb4a5475bd6867d67b50b1d15f" + integrity sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/react-presence@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.0.1.tgz#491990ba913b8e2a5db1b06b203cb24b5cdef9ba" - integrity sha512-UXLW4UAbIY5ZjcvzjfRFo5gxva8QirC9hF7wRE4U5gz+TP0DbRk+//qyuAQ1McDxBt1xNMBTaciFGvEmJvAZCg== +"@radix-ui/react-presence@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.0.tgz#227d84d20ca6bfe7da97104b1a8b48a833bfb478" + integrity sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-use-layout-effect" "1.1.0" "@radix-ui/react-primitive@1.0.3": version "1.0.3" @@ -2195,31 +2196,36 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-slot" "1.0.2" -"@radix-ui/react-roving-focus@1.0.4": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.0.4.tgz#e90c4a6a5f6ac09d3b8c1f5b5e81aab2f0db1974" - integrity sha512-2mUg5Mgcu001VkGy+FfzZyzbmuUWzgWkj3rvv4yu+mLw03+mTzbxZHvfcGyFp2b8EkQeMkpRQ5FiA2Vr2O6TeQ== +"@radix-ui/react-primitive@2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz#fe05715faa9203a223ccc0be15dc44b9f9822884" + integrity sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-collection" "1.0.3" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-direction" "1.0.1" - "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-use-callback-ref" "1.0.1" - "@radix-ui/react-use-controllable-state" "1.0.1" + "@radix-ui/react-slot" "1.1.0" + +"@radix-ui/react-roving-focus@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-roving-focus/-/react-roving-focus-1.1.0.tgz#b30c59daf7e714c748805bfe11c76f96caaac35e" + integrity sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA== + dependencies: + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-collection" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-direction" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-use-callback-ref" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" "@radix-ui/react-separator@^1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.0.3.tgz#be5a931a543d5726336b112f465f58585c04c8aa" - integrity sha512-itYmTy/kokS21aiV5+Z56MZB54KrhPgn6eHDKkFeOLR34HMN2s8PaN47qZZAGnvupcjxHaFZnW4pQEh0BvvVuw== + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-separator/-/react-separator-1.1.0.tgz#ee0f4d86003b0e3ea7bc6ccab01ea0adee32663e" + integrity sha512-3uBAs+egzvJBDZAzvb/n4NxxOYpnspmWxO2u5NbZ8Y6FM/NdrGSF9bop3Cf6F6C71z1rTSn8KV0Fo2ZVd79lGA== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-primitive" "2.0.0" -"@radix-ui/react-slot@1.0.2", "@radix-ui/react-slot@^1.0.2": +"@radix-ui/react-slot@1.0.2": version "1.0.2" resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.0.2.tgz#a9ff4423eade67f501ffb32ec22064bc9d3099ab" integrity sha512-YeTpuq4deV+6DusvVUW4ivBgnkHwECUu0BiN43L5UCDFgdhsRUWAghhTF5MbvNTPzmiFOx90asDSUjWuCNapwg== @@ -2227,47 +2233,49 @@ "@babel/runtime" "^7.13.10" "@radix-ui/react-compose-refs" "1.0.1" +"@radix-ui/react-slot@1.1.0", "@radix-ui/react-slot@^1.0.2": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-slot/-/react-slot-1.1.0.tgz#7c5e48c36ef5496d97b08f1357bb26ed7c714b84" + integrity sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw== + dependencies: + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-tooltip@^1.0.6": - version "1.0.7" - resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.0.7.tgz#8f55070f852e7e7450cc1d9210b793d2e5a7686e" - integrity sha512-lPh5iKNFVQ/jav/j6ZrWq3blfDJ0OH9R6FlNUHPMqdLuQ9vwDgFsRxvl8b7Asuy5c8xmoojHUxKHQSOAvMHxyw== + version "1.1.1" + resolved "https://registry.yarnpkg.com/@radix-ui/react-tooltip/-/react-tooltip-1.1.1.tgz#1807386562015c49b3e83d938910dd47f8cc6175" + integrity sha512-LLE8nzNE4MzPMw3O2zlVlkLFid3y9hMUs7uCbSHyKSo+tCN4yMCf+ZCCcfrYgsOC0TiHBPQ1mtpJ2liY3ZT3SQ== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/primitive" "1.0.1" - "@radix-ui/react-compose-refs" "1.0.1" - "@radix-ui/react-context" "1.0.1" - "@radix-ui/react-dismissable-layer" "1.0.5" - "@radix-ui/react-id" "1.0.1" - "@radix-ui/react-popper" "1.1.3" - "@radix-ui/react-portal" "1.0.4" - "@radix-ui/react-presence" "1.0.1" - "@radix-ui/react-primitive" "1.0.3" - "@radix-ui/react-slot" "1.0.2" - "@radix-ui/react-use-controllable-state" "1.0.1" - "@radix-ui/react-visually-hidden" "1.0.3" + "@radix-ui/primitive" "1.1.0" + "@radix-ui/react-compose-refs" "1.1.0" + "@radix-ui/react-context" "1.1.0" + "@radix-ui/react-dismissable-layer" "1.1.0" + "@radix-ui/react-id" "1.1.0" + "@radix-ui/react-popper" "1.2.0" + "@radix-ui/react-portal" "1.1.1" + "@radix-ui/react-presence" "1.1.0" + "@radix-ui/react-primitive" "2.0.0" + "@radix-ui/react-slot" "1.1.0" + "@radix-ui/react-use-controllable-state" "1.1.0" + "@radix-ui/react-visually-hidden" "1.1.0" -"@radix-ui/react-use-callback-ref@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz#f4bb1f27f2023c984e6534317ebc411fc181107a" - integrity sha512-D94LjX4Sp0xJFVaoQOd3OO9k7tpBYNOXdVhkltUbGv2Qb9OXdrg/CpsjlZv7ia14Sylv398LswWBVVu5nqKzAQ== - dependencies: - "@babel/runtime" "^7.13.10" +"@radix-ui/react-use-callback-ref@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz#bce938ca413675bc937944b0d01ef6f4a6dc5bf1" + integrity sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw== -"@radix-ui/react-use-controllable-state@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.0.1.tgz#ecd2ced34e6330caf89a82854aa2f77e07440286" - integrity sha512-Svl5GY5FQeN758fWKrjM6Qb7asvXeiZltlT4U2gVfl8Gx5UAv2sMR0LWo8yhsIZh2oQ0eFdZ59aoOOMV7b47VA== +"@radix-ui/react-use-controllable-state@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz#1321446857bb786917df54c0d4d084877aab04b0" + integrity sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.1.0" -"@radix-ui/react-use-escape-keydown@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.0.3.tgz#217b840c250541609c66f67ed7bab2b733620755" - integrity sha512-vyL82j40hcFicA+M4Ex7hVkB9vHgSse1ZWomAqV2Je3RleKGO5iM8KMOEtfoSB0PnIelMd2lATjTGMYqN5ylTg== +"@radix-ui/react-use-escape-keydown@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz#31a5b87c3b726504b74e05dac1edce7437b98754" + integrity sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-callback-ref" "1.0.1" + "@radix-ui/react-use-callback-ref" "1.1.0" "@radix-ui/react-use-layout-effect@1.0.1": version "1.0.1" @@ -2276,36 +2284,36 @@ dependencies: "@babel/runtime" "^7.13.10" -"@radix-ui/react-use-rect@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.0.1.tgz#fde50b3bb9fd08f4a1cd204572e5943c244fcec2" - integrity sha512-Cq5DLuSiuYVKNU8orzJMbl15TXilTnJKUCltMVQg53BQOF1/C5toAaGrowkgksdBQ9H+SRL23g0HDmg9tvmxXw== - dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/rect" "1.0.1" +"@radix-ui/react-use-layout-effect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz#3c2c8ce04827b26a39e442ff4888d9212268bd27" + integrity sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w== -"@radix-ui/react-use-size@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.0.1.tgz#1c5f5fea940a7d7ade77694bb98116fb49f870b2" - integrity sha512-ibay+VqrgcaI6veAojjofPATwledXiSmX+C0KrBk/xgpX9rBzPV3OsfwlhQdUOFbh+LKQorLYT+xTXW9V8yd0g== +"@radix-ui/react-use-rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz#13b25b913bd3e3987cc9b073a1a164bb1cf47b88" + integrity sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-use-layout-effect" "1.0.1" + "@radix-ui/rect" "1.1.0" -"@radix-ui/react-visually-hidden@1.0.3": - version "1.0.3" - resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.0.3.tgz#51aed9dd0fe5abcad7dee2a234ad36106a6984ac" - integrity sha512-D4w41yN5YRKtu464TLnByKzMDG/JlMPHtfZgQAu9v6mNakUqGUI9vUrfQKz8NK41VMm/xbZbh76NUTVtIYqOMA== +"@radix-ui/react-use-size@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz#b4dba7fbd3882ee09e8d2a44a3eed3a7e555246b" + integrity sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw== dependencies: - "@babel/runtime" "^7.13.10" - "@radix-ui/react-primitive" "1.0.3" + "@radix-ui/react-use-layout-effect" "1.1.0" -"@radix-ui/rect@1.0.1": - version "1.0.1" - resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.0.1.tgz#bf8e7d947671996da2e30f4904ece343bc4a883f" - integrity sha512-fyrgCaedtvMg9NK3en0pnOYJdtfwxUcNolezkNPUsoX57X8oQk+NkqcvzHXD2uKNij6GXmWU9NDru2IWjrO4BQ== +"@radix-ui/react-visually-hidden@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz#ad47a8572580f7034b3807c8e6740cd41038a5a2" + integrity sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ== dependencies: - "@babel/runtime" "^7.13.10" + "@radix-ui/react-primitive" "2.0.0" + +"@radix-ui/rect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@radix-ui/rect/-/rect-1.1.0.tgz#f817d1d3265ac5415dadc67edab30ae196696438" + integrity sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg== "@sentry-internal/browser-utils@8.12.0": version "8.12.0" @@ -3053,9 +3061,9 @@ svg2vectordrawable "^2.9.1" "@vector-im/compound-web@^4.9.0": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-4.9.0.tgz#f1e70119024110c439a551a65b97019b65149878" - integrity sha512-ojVteP3h/dZ53JGZGDNXKn6Zza3WafOJn+whj+Kt2C1UxxyExDLTLd+Y5f6xD/ho+9/BiNgs6x8eewGR1qaTrQ== + version "4.10.0" + resolved "https://registry.yarnpkg.com/@vector-im/compound-web/-/compound-web-4.10.0.tgz#5403c9933af91d432b5fb5f92a305acadc810893" + integrity sha512-SPeol6FK/h/q8ChHyuCCncUIVoIGNdPODBf7UqvaohRjt8EzyAAHKP89l1YhWKqEaOtG67+28IXoFvdS46tbUA== dependencies: "@floating-ui/react" "^0.26.9" "@floating-ui/react-dom" "^2.0.8" @@ -7982,7 +7990,7 @@ react-redux@^7.2.0: prop-types "^15.7.2" react-is "^17.0.2" -react-remove-scroll-bar@^2.3.3: +react-remove-scroll-bar@^2.3.4: version "2.3.6" resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.6.tgz#3e585e9d163be84a010180b18721e851ac81a29c" integrity sha512-DtSYaao4mBmX+HDo5YWYdBWQwYIQQshUV/dVxFxK+KM26Wjwp1gZ6rv6OC3oujI6Bfu6Xyg3TwK533AQutsn/g== @@ -7990,12 +7998,12 @@ react-remove-scroll-bar@^2.3.3: react-style-singleton "^2.2.1" tslib "^2.0.0" -react-remove-scroll@2.5.5: - version "2.5.5" - resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.5.tgz#1e31a1260df08887a8a0e46d09271b52b3a37e77" - integrity sha512-ImKhrzJJsyXJfBZ4bzu8Bwpka14c/fQt0k+cyFp/PBhTfyDnU5hjOtM4AG/0AMyy8oKzOTR0lDgJIM7pYXI0kw== +react-remove-scroll@2.5.7: + version "2.5.7" + resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.5.7.tgz#15a1fd038e8497f65a695bf26a4a57970cac1ccb" + integrity sha512-FnrTWO4L7/Bhhf3CYBNArEG/yROV0tKmTv7/3h9QCFvH6sndeFf1wPqOcbFVu5VAulS5dV1wGT3GZZ/1GawqiA== dependencies: - react-remove-scroll-bar "^2.3.3" + react-remove-scroll-bar "^2.3.4" react-style-singleton "^2.2.1" tslib "^2.1.0" use-callback-ref "^1.3.0" @@ -9112,12 +9120,12 @@ tsconfig-paths@^3.15.0: minimist "^1.2.6" strip-bom "^3.0.0" -tslib@^2.0.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6.2: +tslib@^2.0.0, tslib@^2.1.0, tslib@^2.4.0, tslib@^2.6.1, tslib@^2.6.2: version "2.6.3" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.3.tgz#0438f810ad7a9edcde7a241c3d80db693c8cbfe0" integrity sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ== -tslib@^2.0.3, tslib@^2.1.0: +tslib@^2.0.3: version "2.6.2" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== From 4bf8766885a675c5b1562777d0efc2cc4aebb599 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:59:07 +0100 Subject: [PATCH 09/63] Update dependency typescript to v5.5.2 (#12688) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- .../views/audio_messages/PlayPauseButton.tsx | 6 +++--- .../views/context_menus/KebabContextMenu.tsx | 6 +++--- .../views/dialogs/spotlight/TooltipOption.tsx | 16 +++++++++++----- .../views/elements/AccessibleButton.tsx | 2 ++ src/components/views/elements/LearnMore.tsx | 6 +++--- src/components/views/rooms/CollapsibleButton.tsx | 6 +++--- .../LegacyCallView/LegacyCallViewButtons.tsx | 6 +++--- src/settings/SettingsStore.ts | 16 +++++++++++----- tsconfig.json | 2 +- yarn.lock | 8 ++++---- 11 files changed, 45 insertions(+), 31 deletions(-) diff --git a/package.json b/package.json index 71d053d3a8..c25ee59d40 100644 --- a/package.json +++ b/package.json @@ -227,7 +227,7 @@ "stylelint-config-standard": "^36.0.0", "stylelint-scss": "^6.0.0", "ts-node": "^10.9.1", - "typescript": "5.4.5" + "typescript": "5.5.2" }, "peerDependencies": { "postcss": "^8.4.19", diff --git a/src/components/views/audio_messages/PlayPauseButton.tsx b/src/components/views/audio_messages/PlayPauseButton.tsx index c49fd2e74c..2ffe621309 100644 --- a/src/components/views/audio_messages/PlayPauseButton.tsx +++ b/src/components/views/audio_messages/PlayPauseButton.tsx @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps, ReactNode } from "react"; +import React, { ReactNode } from "react"; import classNames from "classnames"; import { _t } from "../../../languageHandler"; import { Playback, PlaybackState } from "../../../audio/Playback"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonProps } from "../elements/AccessibleButton"; -type Props = Omit, "title" | "onClick" | "disabled" | "element" | "ref"> & { +type Props = Omit, "title" | "onClick" | "disabled" | "element" | "ref"> & { // Playback instance to manipulate. Cannot change during the component lifecycle. playback: Playback; diff --git a/src/components/views/context_menus/KebabContextMenu.tsx b/src/components/views/context_menus/KebabContextMenu.tsx index 7a6b09668d..f963933bdb 100644 --- a/src/components/views/context_menus/KebabContextMenu.tsx +++ b/src/components/views/context_menus/KebabContextMenu.tsx @@ -18,7 +18,7 @@ import React from "react"; import { Icon as ContextMenuIcon } from "../../../../res/img/element-icons/context-menu.svg"; import { ChevronFace, ContextMenuButton, MenuProps, useContextMenu } from "../../structures/ContextMenu"; -import AccessibleButton from "../elements/AccessibleButton"; +import { ButtonProps } from "../elements/AccessibleButton"; import IconizedContextMenu, { IconizedContextMenuOptionList } from "./IconizedContextMenu"; const contextMenuBelow = (elementRect: DOMRect): MenuProps => { @@ -29,10 +29,10 @@ const contextMenuBelow = (elementRect: DOMRect): MenuProps => { return { left, top, chevronFace }; }; -interface KebabContextMenuProps extends Partial> { +type KebabContextMenuProps = Partial> & { options: React.ReactNode[]; title: string; -} +}; export const KebabContextMenu: React.FC = ({ options, title, ...props }) => { const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); diff --git a/src/components/views/dialogs/spotlight/TooltipOption.tsx b/src/components/views/dialogs/spotlight/TooltipOption.tsx index 0deb4b1311..24c97d601f 100644 --- a/src/components/views/dialogs/spotlight/TooltipOption.tsx +++ b/src/components/views/dialogs/spotlight/TooltipOption.tsx @@ -15,18 +15,23 @@ limitations under the License. */ import classNames from "classnames"; -import React, { ComponentProps, ReactNode } from "react"; +import React, { ReactNode } from "react"; import { useRovingTabIndex } from "../../../../accessibility/RovingTabIndex"; -import AccessibleButton from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonProps } from "../../elements/AccessibleButton"; import { Ref } from "../../../../accessibility/roving/types"; -interface TooltipOptionProps extends ComponentProps { +type TooltipOptionProps = ButtonProps & { endAdornment?: ReactNode; inputRef?: Ref; -} +}; -export const TooltipOption: React.FC = ({ inputRef, className, ...props }) => { +export const TooltipOption = ({ + inputRef, + className, + element, + ...props +}: TooltipOptionProps): JSX.Element => { const [onFocus, isActive, ref] = useRovingTabIndex(inputRef); return ( = ({ inputRef, classNam tabIndex={-1} aria-selected={isActive} role="option" + element={element as keyof JSX.IntrinsicElements} /> ); }; diff --git a/src/components/views/elements/AccessibleButton.tsx b/src/components/views/elements/AccessibleButton.tsx index 76b90506dc..c80f8a018d 100644 --- a/src/components/views/elements/AccessibleButton.tsx +++ b/src/components/views/elements/AccessibleButton.tsx @@ -113,6 +113,8 @@ type Props = DynamicHtmlElementProps & disableTooltip?: TooltipProps["disabled"]; }; +export type ButtonProps = Props; + /** * Type of the props passed to the element that is rendered by AccessibleButton. */ diff --git a/src/components/views/elements/LearnMore.tsx b/src/components/views/elements/LearnMore.tsx index efce35bfe3..c7c7a1925e 100644 --- a/src/components/views/elements/LearnMore.tsx +++ b/src/components/views/elements/LearnMore.tsx @@ -14,14 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps } from "react"; +import React from "react"; import { _t } from "../../../languageHandler"; import Modal from "../../../Modal"; import InfoDialog from "../dialogs/InfoDialog"; -import AccessibleButton from "./AccessibleButton"; +import AccessibleButton, { ButtonProps } from "./AccessibleButton"; -type Props = Omit, "kind" | "onClick" | "className"> & { +type Props = Omit, "element" | "kind" | "onClick" | "className"> & { title: string; description: string | React.ReactNode; }; diff --git a/src/components/views/rooms/CollapsibleButton.tsx b/src/components/views/rooms/CollapsibleButton.tsx index 157e7f7a1a..d2d5de5eaa 100644 --- a/src/components/views/rooms/CollapsibleButton.tsx +++ b/src/components/views/rooms/CollapsibleButton.tsx @@ -14,15 +14,15 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps, useContext } from "react"; +import React, { useContext } from "react"; import classNames from "classnames"; -import AccessibleButton from "../elements/AccessibleButton"; +import AccessibleButton, { ButtonProps } from "../elements/AccessibleButton"; import { OverflowMenuContext } from "./MessageComposerButtons"; import { IconizedContextMenuOption } from "../context_menus/IconizedContextMenu"; import { Ref } from "../../../accessibility/roving/types"; -interface Props extends Omit, "element"> { +interface Props extends Omit, "element"> { inputRef?: Ref; title: string; iconClassName: string; diff --git a/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx b/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx index 055c3fe49e..4b7b5b9923 100644 --- a/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx +++ b/src/components/views/voip/LegacyCallView/LegacyCallViewButtons.tsx @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ComponentProps, createRef, useState, forwardRef } from "react"; +import React, { createRef, useState, forwardRef } from "react"; import classNames from "classnames"; import { MatrixCall } from "matrix-js-sdk/src/webrtc/call"; @@ -32,7 +32,7 @@ import { import { _t } from "../../../../languageHandler"; import DeviceContextMenu from "../../context_menus/DeviceContextMenu"; import { MediaDeviceKindEnum } from "../../../../MediaDeviceHandler"; -import AccessibleButton, { ButtonEvent } from "../../elements/AccessibleButton"; +import AccessibleButton, { ButtonEvent, ButtonProps as AccessibleButtonProps } from "../../elements/AccessibleButton"; // Height of the header duplicated from CSS because we need to subtract it from our max // height to get the max height of the video @@ -40,7 +40,7 @@ const CONTEXT_MENU_VPADDING = 8; // How far the context menu sits above the butt const CONTROLS_HIDE_DELAY = 2000; -type ButtonProps = Omit, "title" | "element"> & { +type ButtonProps = Omit, "title" | "element"> & { state: boolean; onLabel?: string; offLabel?: string; diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index 2afe03424c..2a52021618 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -263,13 +263,19 @@ export default class SettingsStore { public static getDisplayName(settingName: string, atLevel = SettingLevel.DEFAULT): string | null { if (!SETTINGS[settingName] || !SETTINGS[settingName].displayName) return null; - let displayName = SETTINGS[settingName].displayName; - if (displayName instanceof Object) { - if (displayName[atLevel]) displayName = displayName[atLevel]; - else displayName = displayName["default"]; + const displayName = SETTINGS[settingName].displayName; + + if (typeof displayName === "string") { + return _t(displayName); + } + if (displayName?.[atLevel]) { + return _t(displayName[atLevel]); + } + if (displayName?.["default"]) { + return _t(displayName["default"]); } - return displayName ? _t(displayName) : null; + return null; } /** diff --git a/tsconfig.json b/tsconfig.json index 3d5f96e1c2..382874c24f 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -6,7 +6,7 @@ "esModuleInterop": true, "module": "es2022", "moduleResolution": "node", - "target": "es2016", + "target": "es2018", "noUnusedLocals": true, "sourceMap": false, "outDir": "./lib", diff --git a/yarn.lock b/yarn.lock index 110fcad299..6dc99f4605 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9226,10 +9226,10 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -typescript@5.4.5: - version "5.4.5" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" - integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== +typescript@5.5.2: + version "5.5.2" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.2.tgz#c26f023cb0054e657ce04f72583ea2d85f8d0507" + integrity sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew== ua-parser-js@^1.0.2: version "1.0.38" From 5c50605f527e4fd9530b8c54cb7d3d384c8e7cc8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:17:04 +0000 Subject: [PATCH 10/63] Update typescript-eslint monorepo to v7.14.1 (#12689) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 96 +++++++++++++++++++++++++++---------------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/yarn.lock b/yarn.lock index 6dc99f4605..000185ab43 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2923,29 +2923,29 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^7.0.0": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.13.1.tgz#cdc521c8bca38b55585cf30db787fb2abad3f9fd" - integrity sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg== + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.14.1.tgz#90e2f76a5930d553ede124e1f541a39b4417465e" + integrity sha512-aAJd6bIf2vvQRjUG3ZkNXkmBpN+J7Wd0mfQiiVCJMu9Z5GcZZdcc0j8XwN/BM97Fl7e3SkTXODSk4VehUv7CGw== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/type-utils" "7.13.1" - "@typescript-eslint/utils" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/scope-manager" "7.14.1" + "@typescript-eslint/type-utils" "7.14.1" + "@typescript-eslint/utils" "7.14.1" + "@typescript-eslint/visitor-keys" "7.14.1" graphemer "^1.4.0" ignore "^5.3.1" natural-compare "^1.4.0" ts-api-utils "^1.3.0" "@typescript-eslint/parser@^7.0.0": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.13.1.tgz#fac57811b3e519185f7259bac312291f7b9c4e72" - integrity sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A== + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.14.1.tgz#13d97f357aed3c5719f259a6cc3d1a1f065d3692" + integrity sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA== dependencies: - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/typescript-estree" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/scope-manager" "7.14.1" + "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/typescript-estree" "7.14.1" + "@typescript-eslint/visitor-keys" "7.14.1" debug "^4.3.4" "@typescript-eslint/scope-manager@7.13.0": @@ -2956,21 +2956,21 @@ "@typescript-eslint/types" "7.13.0" "@typescript-eslint/visitor-keys" "7.13.0" -"@typescript-eslint/scope-manager@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.13.1.tgz#c08041206904bf36f0e6997efdb0ca775e0c452e" - integrity sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg== +"@typescript-eslint/scope-manager@7.14.1": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.14.1.tgz#63de7a577bc6fe8ee6e412a5b85499f654b93ee5" + integrity sha512-gPrFSsoYcsffYXTOZ+hT7fyJr95rdVe4kGVX1ps/dJ+DfmlnjFN/GcMxXcVkeHDKqsq6uAcVaQaIi3cFffmAbA== dependencies: - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/visitor-keys" "7.14.1" -"@typescript-eslint/type-utils@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.13.1.tgz#63bec3f1fb43cf0bc409cbdb88ef96d118ca8632" - integrity sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg== +"@typescript-eslint/type-utils@7.14.1": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.14.1.tgz#c183f2f28c4c8578eb80aebc4ac9ace400160af6" + integrity sha512-/MzmgNd3nnbDbOi3LfasXWWe292+iuo+umJ0bCCMCPc1jLO/z2BQmWUUUXvXLbrQey/JgzdF/OV+I5bzEGwJkQ== dependencies: - "@typescript-eslint/typescript-estree" "7.13.1" - "@typescript-eslint/utils" "7.13.1" + "@typescript-eslint/typescript-estree" "7.14.1" + "@typescript-eslint/utils" "7.14.1" debug "^4.3.4" ts-api-utils "^1.3.0" @@ -2979,10 +2979,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.0.tgz#0cca95edf1f1fdb0cfe1bb875e121b49617477c5" integrity sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA== -"@typescript-eslint/types@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.1.tgz#787db283bd0b58751094c90d5b58bbf5e9fc9bd8" - integrity sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw== +"@typescript-eslint/types@7.14.1": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.14.1.tgz#a43a540dbe5df7f2a11269683d777fc50b4350aa" + integrity sha512-mL7zNEOQybo5R3AavY+Am7KLv8BorIv7HCYS5rKoNZKQD9tsfGUpO4KdAn3sSUvTiS4PQkr2+K0KJbxj8H9NDg== "@typescript-eslint/typescript-estree@7.13.0": version "7.13.0" @@ -2998,13 +2998,13 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/typescript-estree@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.13.1.tgz#3412841b130e070db2f675e3d9b8cb1ae49e1c3f" - integrity sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw== +"@typescript-eslint/typescript-estree@7.14.1": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.14.1.tgz#ba7c9bac8744487749d19569e254d057754a1575" + integrity sha512-k5d0VuxViE2ulIO6FbxxSZaxqDVUyMbXcidC8rHvii0I56XZPv8cq+EhMns+d/EVIL41sMXqRbK3D10Oza1bbA== dependencies: - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/visitor-keys" "7.13.1" + "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/visitor-keys" "7.14.1" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -3012,15 +3012,15 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@typescript-eslint/utils@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.13.1.tgz#611083379caa0d3a2c09d126c65065a3e4337ba2" - integrity sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ== +"@typescript-eslint/utils@7.14.1": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.14.1.tgz#3307b8226f99103dca2133d0ebcae38419d82c9d" + integrity sha512-CMmVVELns3nak3cpJhZosDkm63n+DwBlDX8g0k4QUa9BMnF+lH2lr3d130M1Zt1xxmB3LLk3NV7KQCq86ZBBhQ== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.13.1" - "@typescript-eslint/types" "7.13.1" - "@typescript-eslint/typescript-estree" "7.13.1" + "@typescript-eslint/scope-manager" "7.14.1" + "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/typescript-estree" "7.14.1" "@typescript-eslint/utils@^6.0.0 || ^7.0.0": version "7.13.0" @@ -3040,12 +3040,12 @@ "@typescript-eslint/types" "7.13.0" eslint-visitor-keys "^3.4.3" -"@typescript-eslint/visitor-keys@7.13.1": - version "7.13.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.13.1.tgz#9c229a795a919db61f2d7f2337ef584ac05fbe96" - integrity sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA== +"@typescript-eslint/visitor-keys@7.14.1": + version "7.14.1" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.14.1.tgz#cc79b5ea154aea734b2a13b983670749f5742274" + integrity sha512-Crb+F75U1JAEtBeQGxSKwI60hZmmzaqA3z9sYsVm8X7W5cwLEm5bRe0/uXS6+MR/y8CVpKSR/ontIAIEPFcEkA== dependencies: - "@typescript-eslint/types" "7.13.1" + "@typescript-eslint/types" "7.14.1" eslint-visitor-keys "^3.4.3" "@ungap/structured-clone@^1.2.0": From 4fbfc946db346123cb820ea04f5a74f9c95f12c8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:20:42 +0000 Subject: [PATCH 11/63] Update actions/checkout action to v4 (#12690) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/playwright-image-updates.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright-image-updates.yaml b/.github/workflows/playwright-image-updates.yaml index a31e99156d..a73c4bf5c2 100644 --- a/.github/workflows/playwright-image-updates.yaml +++ b/.github/workflows/playwright-image-updates.yaml @@ -7,7 +7,7 @@ jobs: update: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Update matrixdotorg/synapse image run: | From 894b4e738da27292c9d1807a32f82d6cdaa17466 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:20:43 +0000 Subject: [PATCH 12/63] Update dependency @types/uuid to v10 (#12692) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index c25ee59d40..2d41364d32 100644 --- a/package.json +++ b/package.json @@ -188,7 +188,7 @@ "@types/seedrandom": "3.0.8", "@types/tar-js": "^0.3.2", "@types/ua-parser-js": "^0.7.36", - "@types/uuid": "^9.0.2", + "@types/uuid": "^10.0.0", "@typescript-eslint/eslint-plugin": "^7.0.0", "@typescript-eslint/parser": "^7.0.0", "axe-core": "4.9.1", diff --git a/yarn.lock b/yarn.lock index 000185ab43..f2084c203e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2905,10 +2905,10 @@ resolved "https://registry.yarnpkg.com/@types/ua-parser-js/-/ua-parser-js-0.7.39.tgz#832c58e460c9435e4e34bb866e85e9146e12cdbb" integrity sha512-P/oDfpofrdtF5xw433SPALpdSchtJmY7nsJItf8h3KXqOslkbySh8zq4dSWXH2oTjRvJ5PczVEoCZPow6GicLg== -"@types/uuid@^9.0.2": - version "9.0.8" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-9.0.8.tgz#7545ba4fc3c003d6c756f651f3bf163d8f0f29ba" - integrity sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA== +"@types/uuid@^10.0.0": + version "10.0.0" + resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-10.0.0.tgz#e9c07fe50da0f53dc24970cca94d619ff03f6f6d" + integrity sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ== "@types/yargs-parser@*": version "21.0.3" From 59512f98085e86f181ed596f7e12f50beef6e46e Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 14:22:34 +0000 Subject: [PATCH 13/63] Update dependency eslint-plugin-unicorn to v54 (#12693) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 2d41364d32..f7ae002a22 100644 --- a/package.json +++ b/package.json @@ -204,7 +204,7 @@ "eslint-plugin-matrix-org": "1.2.1", "eslint-plugin-react": "^7.28.0", "eslint-plugin-react-hooks": "^4.3.0", - "eslint-plugin-unicorn": "^53.0.0", + "eslint-plugin-unicorn": "^54.0.0", "express": "^4.18.2", "fake-indexeddb": "^6.0.0", "fetch-mock-jest": "^1.5.1", diff --git a/yarn.lock b/yarn.lock index f2084c203e..48bd6de57f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4900,10 +4900,10 @@ eslint-plugin-react@^7.28.0: semver "^6.3.1" string.prototype.matchall "^4.0.11" -eslint-plugin-unicorn@^53.0.0: - version "53.0.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-53.0.0.tgz#df3a5c9ecabeb759e6fd867b2d84198466ac8c4d" - integrity sha512-kuTcNo9IwwUCfyHGwQFOK/HjJAYzbODHN3wP0PgqbW+jbXqpNWxNVpVhj2tO9SixBwuAdmal8rVcWKBxwFnGuw== +eslint-plugin-unicorn@^54.0.0: + version "54.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-unicorn/-/eslint-plugin-unicorn-54.0.0.tgz#ce3ea853e8fd7ca2bda2fd6065bf065adb5d8b6d" + integrity sha512-XxYLRiYtAWiAjPv6z4JREby1TAE2byBC7wlh0V4vWDCpccOSU1KovWV//jqPXF6bq3WKxqX9rdjoRQ1EhdmNdQ== dependencies: "@babel/helper-validator-identifier" "^7.24.5" "@eslint-community/eslint-utils" "^4.4.0" From 070c4763ec177581cbc78c59cbb4bb6755acf248 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 15:02:02 +0000 Subject: [PATCH 14/63] Update actions/github-script action to v7 (#12691) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/pull_request_base_branch.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pull_request_base_branch.yaml b/.github/workflows/pull_request_base_branch.yaml index 13542a30f4..49d7bcef7c 100644 --- a/.github/workflows/pull_request_base_branch.yaml +++ b/.github/workflows/pull_request_base_branch.yaml @@ -7,7 +7,7 @@ jobs: name: Check PR base branch runs-on: ubuntu-latest steps: - - uses: actions/github-script@v3 + - uses: actions/github-script@v7 with: script: | const baseBranch = context.payload.pull_request.base.ref; From 7d9ff8b3ff99c26a04ec93d97b5aa30609b3c521 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 16:58:57 +0000 Subject: [PATCH 15/63] Update peter-evans/create-pull-request action to v6 (#12694) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/playwright-image-updates.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/playwright-image-updates.yaml b/.github/workflows/playwright-image-updates.yaml index a73c4bf5c2..a160b77bcf 100644 --- a/.github/workflows/playwright-image-updates.yaml +++ b/.github/workflows/playwright-image-updates.yaml @@ -20,7 +20,7 @@ jobs: - name: Create Pull Request id: cpr - uses: peter-evans/create-pull-request@4e1beaa7521e8b457b572c090b25bd3db56bf1c5 # v5 + uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6 with: token: ${{ secrets.ELEMENT_BOT_TOKEN }} branch: actions/playwright-image-updates From ffbb903eb6fca5ebdd570c974425f545f9b91c01 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 17:14:16 +0000 Subject: [PATCH 16/63] Update all non-major dependencies (#12681) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- playwright/Dockerfile | 2 +- yarn.lock | 347 ++++++++++++++---------------------------- 3 files changed, 120 insertions(+), 231 deletions(-) diff --git a/package.json b/package.json index f7ae002a22..0ce6df9d06 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "opus-recorder": "^8.0.3", "pako": "^2.0.3", "png-chunks-extract": "^1.0.0", - "posthog-js": "1.139.2", + "posthog-js": "1.140.1", "proposal-temporal": "^0.9.0", "qrcode": "1.5.3", "re-resizable": "^6.9.0", diff --git a/playwright/Dockerfile b/playwright/Dockerfile index 7179e08ab0..f20a77b952 100644 --- a/playwright/Dockerfile +++ b/playwright/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/playwright:v1.44.1-jammy +FROM mcr.microsoft.com/playwright:v1.45.0-jammy WORKDIR /work/matrix-react-sdk VOLUME ["/work/element-web/node_modules"] diff --git a/yarn.lock b/yarn.lock index 48bd6de57f..c61acf9776 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1283,7 +1283,7 @@ resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310" 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": +"@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.5.5", "@babel/runtime@^7.8.4", "@babel/runtime@^7.8.7", "@babel/runtime@^7.9.2": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.24.7.tgz#f4f0d5530e8dbdf59b3451b9b3e594b6ba082e12" integrity sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw== @@ -3259,14 +3259,14 @@ aria-hidden@^1.1.1: dependencies: tslib "^2.0.0" -aria-query@5.1.3: +aria-query@5.1.3, aria-query@~5.1.3: version "5.1.3" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.1.3.tgz#19db27cd101152773631396f7a95a3b58c22c35e" integrity sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ== dependencies: deep-equal "^2.0.5" -aria-query@^5.0.0, aria-query@^5.3.0: +aria-query@^5.0.0: version "5.3.0" resolved "https://registry.yarnpkg.com/aria-query/-/aria-query-5.3.0.tgz#650c569e41ad90b51b3d7df5e5eed1c7549c103e" integrity sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A== @@ -3367,7 +3367,7 @@ array.prototype.toreversed@^1.1.2: es-abstract "^1.22.1" es-shim-unscopables "^1.0.0" -array.prototype.tosorted@^1.1.3: +array.prototype.tosorted@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz#fe954678ff53034e717ea3352a03f0b0b86f7ffc" integrity sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA== @@ -3411,19 +3411,12 @@ astral-regex@^2.0.0: resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ== -asynciterator.prototype@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/asynciterator.prototype/-/asynciterator.prototype-1.0.0.tgz#8c5df0514936cdd133604dfcc9d3fb93f09b2b62" - integrity sha512-wwHYEIS0Q80f5mosx3L/dfG5t5rjEa9Ft51GTaNt862EnpyGHpgz2RkZvLPp1oF5TnAiTohkEKVEu8pQPJI7Vg== - dependencies: - has-symbols "^1.0.3" - asynckit@^0.4.0: version "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, available-typed-arrays@^1.0.6, available-typed-arrays@^1.0.7: +available-typed-arrays@^1.0.5, 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== @@ -3435,22 +3428,17 @@ 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.9.1, axe-core@~4.9.1: +axe-core@4.9.1, axe-core@^4.9.1, axe-core@~4.9.1: version "4.9.1" resolved "https://registry.yarnpkg.com/axe-core/-/axe-core-4.9.1.tgz#fcd0f4496dad09e0c899b44f6c4bb7848da912ae" integrity sha512-QbUdXJVTpvUTHU7871ppZkdOLBeGUKBQWHkHrvN2V9IQWGMt61zf3B45BtzjxEJzYuj0JBjBZP/hmYS/R9pmAw== -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== - -axobject-query@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.2.1.tgz#39c378a6e3b06ca679f29138151e45b2b32da62a" - integrity sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg== +axobject-query@~3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/axobject-query/-/axobject-query-3.1.1.tgz#3b6e5c6d4e43ca7ba51c5babf99d22a9c68485e1" + integrity sha512-goKlv8DZrK9hUh975fnHzhNIO4jUnFCfv/dszV5VwUGDFjI6vQ2VwoyjYjYNEbBE8AH87TduWP5uyDR1D+Iteg== dependencies: - dequal "^2.0.3" + deep-equal "^2.0.5" babel-jest@^29.0.0, babel-jest@^29.7.0: version "29.7.0" @@ -4509,94 +4497,7 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" -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== - dependencies: - array-buffer-byte-length "^1.0.1" - arraybuffer.prototype.slice "^1.0.3" - available-typed-arrays "^1.0.6" - call-bind "^1.0.7" - es-define-property "^1.0.0" - es-errors "^1.3.0" - es-set-tostringtag "^2.0.2" - 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.1" - has-symbols "^1.0.3" - 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-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - 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.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.1" - typed-array-byte-length "^1.0.0" - typed-array-byte-offset "^1.0.0" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.14" - -es-abstract@^1.18.3: - version "1.21.2" - resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" - integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== - dependencies: - array-buffer-byte-length "^1.0.0" - available-typed-arrays "^1.0.5" - call-bind "^1.0.2" - es-set-tostringtag "^2.0.1" - es-to-primitive "^1.2.1" - function.prototype.name "^1.1.5" - get-intrinsic "^1.2.0" - get-symbol-description "^1.0.0" - globalthis "^1.0.3" - gopd "^1.0.1" - has "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - is-array-buffer "^3.0.2" - is-callable "^1.2.7" - is-negative-zero "^2.0.2" - is-regex "^1.1.4" - is-shared-array-buffer "^1.0.2" - is-string "^1.0.7" - is-typed-array "^1.1.10" - is-weakref "^1.0.2" - object-inspect "^1.12.3" - object-keys "^1.1.1" - object.assign "^4.1.4" - regexp.prototype.flags "^1.4.3" - safe-regex-test "^1.0.0" - string.prototype.trim "^1.2.7" - string.prototype.trimend "^1.0.6" - string.prototype.trimstart "^1.0.6" - typed-array-length "^1.0.4" - unbox-primitive "^1.0.2" - which-typed-array "^1.1.9" - -es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: +es-abstract@^1.17.5, es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23.1, es-abstract@^1.23.2, es-abstract@^1.23.3: version "1.23.3" resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.23.3.tgz#8f0c5a35cd215312573c5a27c87dfd6c881a0aa0" integrity sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A== @@ -4648,6 +4549,46 @@ es-abstract@^1.22.1, es-abstract@^1.22.3, es-abstract@^1.23.0, es-abstract@^1.23 unbox-primitive "^1.0.2" which-typed-array "^1.1.15" +es-abstract@^1.18.3: + version "1.21.2" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.21.2.tgz#a56b9695322c8a185dc25975aa3b8ec31d0e7eff" + integrity sha512-y/B5POM2iBnIxCiernH1G7rC9qQoM77lLIMQLuob0zhp8C56Po81+2Nj0WFKnd0pNReDTnkYryc+zhOzpEIROg== + dependencies: + array-buffer-byte-length "^1.0.0" + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.5" + get-intrinsic "^1.2.0" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has "^1.0.3" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.10" + is-weakref "^1.0.2" + object-inspect "^1.12.3" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.4.3" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.7" + string.prototype.trimend "^1.0.6" + string.prototype.trimstart "^1.0.6" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.9" + es-define-property@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" @@ -4675,26 +4616,6 @@ es-get-iterator@^1.1.3: isarray "^2.0.5" stop-iteration-iterator "^1.0.0" -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== - dependencies: - asynciterator.prototype "^1.0.0" - call-bind "^1.0.2" - define-properties "^1.2.1" - es-abstract "^1.22.1" - es-set-tostringtag "^2.0.1" - function-bind "^1.1.1" - get-intrinsic "^1.2.1" - globalthis "^1.0.3" - has-property-descriptors "^1.0.0" - has-proto "^1.0.1" - has-symbols "^1.0.3" - internal-slot "^1.0.5" - iterator.prototype "^1.1.2" - safe-array-concat "^1.0.1" - es-iterator-helpers@^1.0.19: version "1.0.19" resolved "https://registry.yarnpkg.com/es-iterator-helpers/-/es-iterator-helpers-1.0.19.tgz#117003d0e5fec237b4b5c08aded722e0c6d50ca8" @@ -4722,7 +4643,7 @@ es-object-atoms@^1.0.0: dependencies: es-errors "^1.3.0" -es-set-tostringtag@^2.0.1, es-set-tostringtag@^2.0.2, es-set-tostringtag@^2.0.3: +es-set-tostringtag@^2.0.1, 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== @@ -4845,26 +4766,26 @@ eslint-plugin-jest@^28.0.0: "@typescript-eslint/utils" "^6.0.0 || ^7.0.0" eslint-plugin-jsx-a11y@^6.5.1: - version "6.8.0" - resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2" - integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA== + version "6.9.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.9.0.tgz#67ab8ff460d4d3d6a0b4a570e9c1670a0a8245c8" + integrity sha512-nOFOCaJG2pYqORjK19lqPqxMO/JpvdCZdPtNdxY3kvom3jTvkAbOvQvD8wuD0G8BYR0IGAGYDlzqWJOh/ybn2g== dependencies: - "@babel/runtime" "^7.23.2" - aria-query "^5.3.0" - array-includes "^3.1.7" + aria-query "~5.1.3" + array-includes "^3.1.8" array.prototype.flatmap "^1.3.2" ast-types-flow "^0.0.8" - axe-core "=4.7.0" - axobject-query "^3.2.1" + axe-core "^4.9.1" + axobject-query "~3.1.1" damerau-levenshtein "^1.0.8" emoji-regex "^9.2.2" - es-iterator-helpers "^1.0.15" - hasown "^2.0.0" + es-iterator-helpers "^1.0.19" + hasown "^2.0.2" jsx-ast-utils "^3.3.5" language-tags "^1.0.9" minimatch "^3.1.2" - object.entries "^1.1.7" - object.fromentries "^2.0.7" + object.fromentries "^2.0.8" + safe-regex-test "^1.0.3" + string.prototype.includes "^2.0.0" eslint-plugin-matrix-org@1.2.1: version "1.2.1" @@ -4877,15 +4798,15 @@ eslint-plugin-react-hooks@^4.3.0: integrity sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ== eslint-plugin-react@^7.28.0: - version "7.34.2" - resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.2.tgz#2780a1a35a51aca379d86d29b9a72adc6bfe6b66" - integrity sha512-2HCmrU+/JNigDN6tg55cRDKCQWicYAPB38JGSFDQt95jDm8rrvSUo7YPkOIm5l6ts1j1zCvysNcasvfTMQzUOw== + version "7.34.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.34.3.tgz#9965f27bd1250a787b5d4cfcc765e5a5d58dcb7b" + integrity sha512-aoW4MV891jkUulwDApQbPYTVZmeuSyFrudpbTAQuj5Fv8VL+o6df2xIGpw8B0hPjAaih1/Fb0om9grCdyFYemA== dependencies: array-includes "^3.1.8" array.prototype.findlast "^1.2.5" array.prototype.flatmap "^1.3.2" array.prototype.toreversed "^1.1.2" - array.prototype.tosorted "^1.1.3" + array.prototype.tosorted "^1.1.4" doctrine "^2.1.0" es-iterator-helpers "^1.0.19" estraverse "^5.3.0" @@ -5399,7 +5320,7 @@ fsevents@^2.3.2, fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== -function-bind@^1.1.1, function-bind@^1.1.2: +function-bind@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== @@ -5628,7 +5549,7 @@ has-symbols@^1.0.2, has-symbols@^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, has-tostringtag@^1.0.1, has-tostringtag@^1.0.2: +has-tostringtag@^1.0.0, 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== @@ -5807,16 +5728,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: - version "1.0.6" - resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.6.tgz#37e756098c4911c5e912b8edbf71ed3aa116f930" - integrity sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg== - dependencies: - get-intrinsic "^1.2.2" - hasown "^2.0.0" - side-channel "^1.0.4" - -internal-slot@^1.0.5, internal-slot@^1.0.7: +internal-slot@^1.0.4, 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== @@ -5921,7 +5833,14 @@ is-core-module@^2.11.0: dependencies: has "^1.0.3" -is-core-module@^2.13.0, is-core-module@^2.13.1: +is-core-module@^2.13.0: + version "2.14.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.14.0.tgz#43b8ef9f46a6a08888db67b1ffd4ec9e3dfd59d1" + integrity sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A== + dependencies: + hasown "^2.0.2" + +is-core-module@^2.13.1: version "2.13.1" resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== @@ -5985,12 +5904,7 @@ is-ip@^3.1.0: dependencies: ip-regex "^4.0.0" -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-map@^2.0.3: +is-map@^2.0.2, 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== @@ -6042,12 +5956,7 @@ is-regex@^1.1.4: call-bind "^1.0.2" has-tostringtag "^1.0.0" -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-set@^2.0.3: +is-set@^2.0.2, is-set@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/is-set/-/is-set-2.0.3.tgz#8ab209ea424608141372ded6e0cb200ef1d9d01d" integrity sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg== @@ -6776,9 +6685,9 @@ known-css-properties@^0.31.0: integrity sha512-sBPIUGTNF0czz0mwGGUoKKJC8Q7On1GPbCSFPfyEsfHb2DyBG0Y4QtV+EVWpINSaiGKZblDNuF5AezxSgOhesQ== 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" - integrity sha512-tN0MCzyWnoz/4nHS6uxdlFWoUZT7ABptwKPQ52Ea7URk6vll88bWBVhodtnlfEuCcKWNGoc+uGbw1cwa9IKh/w== + version "0.3.23" + resolved "https://registry.yarnpkg.com/language-subtag-registry/-/language-subtag-registry-0.3.23.tgz#23529e04d9e3b74679d70142df3fd2eb6ec572e7" + integrity sha512-0K65Lea881pHotoGEa5gDlMxt3pctLi2RplBb7Ezh4rRdLEOtgi7n4EwK9lamnUCkKBqaeKRVebTq6BAxSkpXQ== language-tags@^1.0.9: version "1.0.9" @@ -7315,18 +7224,23 @@ 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.12.3: version "1.13.1" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + object-is@^1.1.5: - version "1.1.5" - resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.5.tgz#b9deeaa5fc7f1846a0faecdceec138e5778f53ac" - integrity sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw== + version "1.1.6" + resolved "https://registry.yarnpkg.com/object-is/-/object-is-1.1.6.tgz#1a6a53aed2dd8f7e6775ff870bea58545956ab07" + integrity sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q== dependencies: - call-bind "^1.0.2" - define-properties "^1.1.3" + call-bind "^1.0.7" + define-properties "^1.2.1" object-keys@^1.1.1: version "1.1.1" @@ -7343,7 +7257,7 @@ object.assign@^4.1.4, object.assign@^4.1.5: has-symbols "^1.0.3" object-keys "^1.1.1" -object.entries@^1.1.7, object.entries@^1.1.8: +object.entries@^1.1.8: version "1.1.8" resolved "https://registry.yarnpkg.com/object.entries/-/object.entries-1.1.8.tgz#bffe6f282e01f4d17807204a24f8edd823599c41" integrity sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ== @@ -7714,10 +7628,10 @@ postcss@^8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" -posthog-js@1.139.2: - version "1.139.2" - resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.139.2.tgz#f8de29edf2770da47fcccb7838902d1e89d6b43d" - integrity sha512-myyuOADqZvYwgqmriwlKDEUDwLhscivFLh67UWBj4Wt9kOlmklvJb36W0ES2GAS6IdojbnGZGH5lF3heqreLWQ== +posthog-js@1.140.1: + version "1.140.1" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.140.1.tgz#34efc0d326fa5fcf7950106f350fb4f0e73b2da6" + integrity sha512-UeKuAtQSvbzmTCzNVaauku8F194EYwAP33WrRrWZlDlMNbMy7GKcZOgKbr7jZqnha7FlVlHrWk+Rpyr1zCFhPQ== dependencies: fflate "^0.4.8" preact "^10.19.3" @@ -8303,17 +8217,7 @@ run-parallel@^1.1.9: dependencies: queue-microtask "^1.2.2" -safe-array-concat@^1.0.1: - 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== - dependencies: - call-bind "^1.0.5" - get-intrinsic "^1.2.2" - has-symbols "^1.0.3" - isarray "^2.0.5" - -safe-array-concat@^1.1.0, safe-array-concat@^1.1.2: +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== @@ -8684,6 +8588,14 @@ string-width@^5.0.1, string-width@^5.1.2: emoji-regex "^9.2.2" strip-ansi "^7.0.1" +string.prototype.includes@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/string.prototype.includes/-/string.prototype.includes-2.0.0.tgz#8986d57aee66d5460c144620a6d873778ad7289f" + integrity sha512-E34CkBgyeqNDcrbU76cDjL5JLcVrtSdYq0MEh/B10r17pRP4ciHLwTgnuLV8Ay6cgEMLkcBkFCKyFZ43YldYzg== + dependencies: + define-properties "^1.1.3" + es-abstract "^1.17.5" + string.prototype.matchall@^4.0.11: version "4.0.11" resolved "https://registry.yarnpkg.com/string.prototype.matchall/-/string.prototype.matchall-4.0.11.tgz#1092a72c59268d2abaad76582dccc687c0297e0a" @@ -8719,7 +8631,7 @@ string.prototype.trim@^1.2.7: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trim@^1.2.8, string.prototype.trim@^1.2.9: +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== @@ -8738,7 +8650,7 @@ string.prototype.trimend@^1.0.6: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trimend@^1.0.7, string.prototype.trimend@^1.0.8: +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== @@ -8756,7 +8668,7 @@ string.prototype.trimstart@^1.0.6: define-properties "^1.2.0" es-abstract "^1.22.1" -string.prototype.trimstart@^1.0.7, string.prototype.trimstart@^1.0.8: +string.prototype.trimstart@^1.0.8: version "1.0.8" resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz#7ee834dda8c7c17eff3118472bb35bfedaa34dde" integrity sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg== @@ -9170,7 +9082,7 @@ type-is@~1.6.18: media-typer "0.3.0" mime-types "~2.1.24" -typed-array-buffer@^1.0.1, typed-array-buffer@^1.0.2: +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== @@ -9179,7 +9091,7 @@ typed-array-buffer@^1.0.1, typed-array-buffer@^1.0.2: es-errors "^1.3.0" is-typed-array "^1.1.13" -typed-array-byte-length@^1.0.0, typed-array-byte-length@^1.0.1: +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== @@ -9190,7 +9102,7 @@ typed-array-byte-length@^1.0.0, typed-array-byte-length@^1.0.1: has-proto "^1.0.3" is-typed-array "^1.1.13" -typed-array-byte-offset@^1.0.0, typed-array-byte-offset@^1.0.2: +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== @@ -9202,19 +9114,7 @@ typed-array-byte-offset@^1.0.0, typed-array-byte-offset@^1.0.2: has-proto "^1.0.3" is-typed-array "^1.1.13" -typed-array-length@^1.0.4: - 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.7" - for-each "^0.3.3" - gopd "^1.0.1" - has-proto "^1.0.3" - is-typed-array "^1.1.13" - possible-typed-array-names "^1.0.0" - -typed-array-length@^1.0.6: +typed-array-length@^1.0.4, typed-array-length@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.6.tgz#57155207c76e64a3457482dfdc1c9d1d3c4c73a3" integrity sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g== @@ -9538,18 +9438,7 @@ which-module@^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.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== - dependencies: - available-typed-arrays "^1.0.6" - call-bind "^1.0.5" - for-each "^0.3.3" - 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: +which-typed-array@^1.1.13, 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== From d8a671d7535c39937b1efe62942b4fa3800d7792 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 25 Jun 2024 22:45:39 +0100 Subject: [PATCH 17/63] Update dependency posthog-js to v1.141.3 (#12700) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 14 ++++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0ce6df9d06..45c955aa92 100644 --- a/package.json +++ b/package.json @@ -119,7 +119,7 @@ "opus-recorder": "^8.0.3", "pako": "^2.0.3", "png-chunks-extract": "^1.0.0", - "posthog-js": "1.140.1", + "posthog-js": "1.141.3", "proposal-temporal": "^0.9.0", "qrcode": "1.5.3", "re-resizable": "^6.9.0", diff --git a/yarn.lock b/yarn.lock index c61acf9776..180d30b654 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7628,13 +7628,14 @@ postcss@^8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" -posthog-js@1.140.1: - version "1.140.1" - resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.140.1.tgz#34efc0d326fa5fcf7950106f350fb4f0e73b2da6" - integrity sha512-UeKuAtQSvbzmTCzNVaauku8F194EYwAP33WrRrWZlDlMNbMy7GKcZOgKbr7jZqnha7FlVlHrWk+Rpyr1zCFhPQ== +posthog-js@1.141.3: + version "1.141.3" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.141.3.tgz#c0b78e62567b5de15e400254905d2b72544e3618" + integrity sha512-LZ+I6wJS82yX/SZVaK20V2WV4MEfB2G9fT2ZJoWlzwN5L3wsbpmjD9F2dVW818deBV3ms1w0Ho7rnlJtBGHx2g== dependencies: fflate "^0.4.8" preact "^10.19.3" + web-vitals "^4.0.1" potpack@^1.0.2: version "1.0.2" @@ -9326,6 +9327,11 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" +web-vitals@^4.0.1: + version "4.2.0" + resolved "https://registry.yarnpkg.com/web-vitals/-/web-vitals-4.2.0.tgz#008949ab79717a68ccaaa3c4371cbc7bbbd78a92" + integrity sha512-ohj72kbtVWCpKYMxcbJ+xaOBV3En76hW47j52dG+tEGG36LZQgfFw5yHl9xyjmosy3XUMn8d/GBUAy4YPM839w== + webcrypto-core@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.8.0.tgz#aaea17f3dd9c77c304e3c494eb27ca07cc72ca37" From b78e6f02f728592295fd57020ff55cd18594b122 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 26 Jun 2024 07:19:17 +0100 Subject: [PATCH 18/63] [create-pull-request] automated change (#12701) Co-authored-by: github-merge-queue --- src/i18n/strings/cs.json | 5 ----- src/i18n/strings/de_DE.json | 1 - src/i18n/strings/es.json | 1 - src/i18n/strings/et.json | 5 ----- src/i18n/strings/fi.json | 1 - src/i18n/strings/fr.json | 14 +++++++++----- src/i18n/strings/hu.json | 1 - src/i18n/strings/id.json | 1 - src/i18n/strings/it.json | 5 ----- src/i18n/strings/ja.json | 1 - src/i18n/strings/pl.json | 5 ----- src/i18n/strings/ru.json | 1 - src/i18n/strings/sk.json | 1 - src/i18n/strings/sq.json | 1 - src/i18n/strings/sv.json | 5 ----- src/i18n/strings/uk.json | 1 - src/i18n/strings/vi.json | 1 - src/i18n/strings/zh_Hans.json | 1 - src/i18n/strings/zh_Hant.json | 1 - 19 files changed, 9 insertions(+), 43 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 5ae15d435b..2b2ab472d7 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -1429,11 +1429,6 @@ "render_reaction_images_description": "Někdy se označují jako \"vlastní emoji\".", "report_to_moderators": "Nahlásit moderátorům", "report_to_moderators_description": "V místnostech, které podporují moderování, můžete pomocí tlačítka \"Nahlásit\" nahlásit zneužití moderátorům místnosti.", - "rust_crypto": "Implementace kryptografie v jazyce Rust", - "rust_crypto_in_config": "Rust kryptografii nelze v tomto %(brand)s deaktivovat", - "rust_crypto_in_config_description": "Přechod na Rust kryptografii vyžaduje proces migrace, který může trvat několik minut. Nelze jej vypnout; používejte jej s opatrností!", - "rust_crypto_optin_warning": "Přechod na Rust kryptografii vyžaduje proces migrace, který může trvat několik minut. Pro deaktivaci se budete muset odhlásit a znovu přihlásit; používejte s opatrností!", - "rust_crypto_requires_logout": "Jakmile je Rust kryptografie povolena, lze ji vypnout pouze odhlášením a opětovným přihlášením.", "sliding_sync": "Režim klouzavé synchronizace", "sliding_sync_description": "V aktivním vývoji, nelze zakázat.", "sliding_sync_disabled_notice": "Pro vypnutí se odhlaste a znovu přihlaste", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index f6f2b4dc59..a48a348362 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -1418,7 +1418,6 @@ "render_reaction_images_description": "Werden manchmal auch als „benutzerdefinierte Emojis“ bezeichnet.", "report_to_moderators": "An Raummoderation melden", "report_to_moderators_description": "In Räumen, die Moderation unterstützen, lässt dich die Schaltfläche „Melden“ missbräuchliche Verwendung an die Raummoderation melden.", - "rust_crypto": "Rust-Verschlüsselungsumsetzung", "sliding_sync": "Sliding-Sync-Modus", "sliding_sync_description": "In aktiver Entwicklung, kann nicht deaktiviert werden.", "sliding_sync_disabled_notice": "Zum Deaktivieren, melde dich ab und erneut an", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 7691cc644f..8c3a9021af 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -1311,7 +1311,6 @@ "pinning": "Mensajes anclados", "report_to_moderators": "Denunciar ante los moderadores", "report_to_moderators_description": "En las salas que sean compatible con la moderación, el botón de «Denunciar» avisará a los moderadores de la sala.", - "rust_crypto": "Implementación de la criptografía en Rust", "sliding_sync": "Modo de sincronización progresiva", "sliding_sync_description": "En desarrollo, no se puede desactivar.", "sliding_sync_disabled_notice": "Cierra sesión y vuélvela a abrir para desactivar", diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 2e7c1d45a7..1279af4469 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -1422,11 +1422,6 @@ "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_description": "Aktiivselt arendamisel ega ole võimalik välja lülitada.", "sliding_sync_disabled_notice": "Väljalülitamiseks logi Matrix'i võrgust välja ja seejärel tagasi", diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index 6becb67c4b..993a82a3b5 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -1241,7 +1241,6 @@ "pinning": "Viestien kiinnittäminen", "report_to_moderators": "Ilmoita moderaattoreille", "report_to_moderators_description": "Moderointia tukevissa huoneissa väärinkäytökset voi ilmoittaa Ilmoita-painikkeella huoneen moderaattoreille.", - "rust_crypto": "Rust-kryptografiatoteutus", "sliding_sync": "Liukuvan synkronoinnin tila", "sliding_sync_description": "Työn alla, käytöstä poistaminen ei ole mahdollista.", "sliding_sync_disabled_notice": "Poista käytöstä kirjautumalla ulos ja takaisin sisään", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 5c04e371dd..3b8351dd79 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -1428,11 +1428,6 @@ "render_reaction_images_description": "Parfois appelés « émojis personnalisés ».", "report_to_moderators": "Signaler aux modérateurs", "report_to_moderators_description": "Dans les salons prenant en charge la modération, le bouton « Signaler » vous permet de signaler des abus aux modérateurs du salon.", - "rust_crypto": "Implémentation cryptographique en Rust", - "rust_crypto_in_config": "La cryptographie Rust ne peut être désactivée sur ce déploiement de %(brand)s", - "rust_crypto_in_config_description": "Si vous passez à la cryptographie Rust, cela démarrera un processus de migration qui peut durer plusieurs minutes. Il ne peut être arrêté; à utiliser prudemment !", - "rust_crypto_optin_warning": "Si vous passez à la cryptographie Rust, cela démarrera un processus de migration qui peut durer plusieurs minutes. Pour la désactiver, vous devrez vous déconnecter et vous reconnecter; à utiliser prudemment !", - "rust_crypto_requires_logout": "Une fois activée, la cryptographie Rust ne peut être désactivée qu'en se déconnectant et se reconnectant", "sliding_sync": "Mode synchronisation progressive", "sliding_sync_description": "En cours de développement, ne peut être désactivé.", "sliding_sync_disabled_notice": "Déconnectez et revenez pour désactiver", @@ -1857,6 +1852,7 @@ "forget": "Oublier le salon", "low_priority": "Priorité basse", "mark_read": "Marquer comme lu", + "mark_unread": "Marquer comme non lu", "mentions_only": "Seulement les mentions", "notifications_default": "Réglage par défaut", "notifications_mute": "Salon muet", @@ -2803,6 +2799,7 @@ "show_redaction_placeholder": "Afficher les messages supprimés", "show_stickers_button": "Afficher le bouton des autocollants", "show_typing_notifications": "Afficher les notifications de saisie", + "showbold": "Afficher toute l'activité dans la liste des salons (points ou nombre de messages non lus)", "sidebar": { "metaspaces_favourites_description": "Regroupez tous vos salons et personnes préférés au même endroit.", "metaspaces_home_all_rooms": "Afficher tous les salons", @@ -2816,6 +2813,7 @@ "title": "Barre latérale" }, "start_automatically": "Démarrer automatiquement après la phase d'authentification du système", + "tac_only_notifications": "Afficher uniquement les notifications dans le centre d'activité du fil de discussion", "use_12_hour_format": "Afficher l’heure au format am/pm (par ex. 2:30pm)", "use_command_enter_send_message": "Utilisez Ctrl + Entrée pour envoyer un message", "use_command_f_search": "Utilisez Commande + F pour rechercher dans le fil de discussion", @@ -3103,12 +3101,18 @@ "empty_heading": "Garde les discussions organisées à l’aide de fils de discussion", "empty_tip": "Conseil : Utilisez « %(replyInThread)s » en survolant un message.", "error_start_thread_existing_relation": "Impossible de créer un fil de discussion à partir d’un événement avec une relation existante", + "mark_all_read": "Tout marquer comme lu", "my_threads": "Mes fils de discussion", "my_threads_description": "Affiche tous les fils de discussion auxquels vous avez participé", "open_thread": "Ouvrir le fil de discussion", "show_all_threads": "Afficher tous les fils de discussion", "show_thread_filter": "Affiche :" }, + "threads_activity_centre": { + "header": "Activité des fils de discussions", + "no_rooms_with_threads_notifs": "Vous n’avez pas encore de salons avec des notifications de fil de discussion.", + "release_announcement_header": "Centre d'activité des fils de discussions" + }, "time": { "about_day_ago": "il y a environ un jour", "about_hour_ago": "il y a environ une heure", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 498b46afbd..9ad9aba958 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -1399,7 +1399,6 @@ "pinning": "Üzenet kitűzése", "report_to_moderators": "Jelentés a moderátoroknak", "report_to_moderators_description": "A moderálást támogató szobákban a problémás tartalmat a „Jelentés” gombbal lehet a moderátorok felé jelezni.", - "rust_crypto": "Rust titkosítási implementáció", "sliding_sync": "Csúszó szinkronizációs mód", "sliding_sync_description": "Aktív fejlesztés alatt, nem kapcsolható ki.", "sliding_sync_disabled_notice": "A kikapcsoláshoz ki-, és bejelentkezés szükséges", diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index 2e38dd459e..d6b408f14d 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -1405,7 +1405,6 @@ "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", "sliding_sync": "Mode Sinkronisasi Geser", "sliding_sync_description": "Dalam pengembangan aktif, tidak dapat dinonaktifkan.", "sliding_sync_disabled_notice": "Keluar dan masuk kembali ke akun untuk menonaktifkan", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index 9163a177f2..4bcbb8c4bc 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -1428,11 +1428,6 @@ "render_reaction_images_description": "A volte chiamati \"emoji personalizzati\".", "report_to_moderators": "Segnala ai moderatori", "report_to_moderators_description": "Nelle stanze che supportano la moderazione, il pulsante \"Segnala\" ti permetterà di segnalare abusi ai moderatori della stanza.", - "rust_crypto": "Implementazione crittografia Rust", - "rust_crypto_in_config": "La crittografia Rust non può essere disattivata in questa distribuzione di %(brand)s", - "rust_crypto_in_config_description": "Il passaggio alla crittografia Rust richiede un processo di migrazione che può impiegare diversi minuti. Non può essere disattivata, usala con cautela!", - "rust_crypto_optin_warning": "Il passaggio alla crittografia Rust richiede un processo di migrazione che può impiegare diversi minuti. Per disattivarla dovrai disconnetterti e poi riaccedere, usala con cautela!", - "rust_crypto_requires_logout": "Una volta attivata, la crittografia Rust può essere disattivata solo disconnettendoti e riaccedendo.", "sliding_sync": "Modalità di sincr. con slide", "sliding_sync_description": "In sviluppo attivo, non può essere disattivato.", "sliding_sync_disabled_notice": "Disconnettiti e riconnettiti per disattivare", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index c37e50ec95..9c219edc3d 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -1325,7 +1325,6 @@ "pinning": "固定メッセージを有効にする", "report_to_moderators": "モデレーターに報告", "report_to_moderators_description": "モデレートをサポートするルームで「報告」ボタンを使用すると、ルームのモデレーターに問題を報告できます。", - "rust_crypto": "Rustによる暗号の実装", "sliding_sync": "スライド式同期モード", "sliding_sync_description": "開発中です。無効にできません。", "sliding_sync_server_no_support": "あなたのサーバーはネイティブでサポートしていません", diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 0e37a7fa14..db0885ac90 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -1467,11 +1467,6 @@ "render_reaction_images_description": "Czasami określane jako \"emoji niestandardowe\".", "report_to_moderators": "Zgłoś do moderatorów", "report_to_moderators_description": "W pokojach, które wspierają moderacje, przycisk \"Zgłoś\" pozwoli Ci zgłosić nadużycia moderatorom.", - "rust_crypto": "Implementacja kryptografii Rust", - "rust_crypto_in_config": "Kryptografia Rust nie może zostać włączona na tym wydaniu %(brand)s", - "rust_crypto_in_config_description": "Przejście na kryptografię Rust wymaga procesu migracji, która może potrwać kilka minut. Nie można jej wyłączyć; zachowaj ostrożność!", - "rust_crypto_optin_warning": "Przejście na kryptografię Rust wymaga procesu migracji, która może potrwać kilka minut. Aby ją wyłączyć, będziesz musiał zalogować się ponownie; zachowaj ostrożność!", - "rust_crypto_requires_logout": "Po włączeniu, kryptografia Rust może zostać wyłączona tylko po ponownym zalogowaniu.", "sliding_sync": "Tryb synchronizacji przesuwanej", "sliding_sync_description": "W trakcie aktywnego rozwoju, nie można wyłączyć.", "sliding_sync_disabled_notice": "Zaloguj się ponownie, aby wyłączyć", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 809247bccf..0297a34d51 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -1417,7 +1417,6 @@ "render_reaction_images_description": "Иногда их называют \"пользовательскими эмодзи\".", "report_to_moderators": "Пожаловаться модераторам", "report_to_moderators_description": "В поддерживающих модерирование комнатах, кнопка \"Пожаловаться\" позволит вам сообщить о нарушении модераторам комнаты.", - "rust_crypto": "Реализация криптографии Rust", "sliding_sync": "Режим Sliding Sync", "sliding_sync_description": "В активной разработке, нельзя отключить.", "sliding_sync_disabled_notice": "Выйдите из системы и снова войдите, чтобы отключить", diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index cd9d6997d5..ad2ab62641 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -1422,7 +1422,6 @@ "render_reaction_images_description": "Niekedy sa označujú ako „vlastné emotikony“.", "report_to_moderators": "Nahlásiť moderátorom", "report_to_moderators_description": "V miestnostiach, ktoré podporujú moderovanie, môžete pomocou tlačidla \"Nahlásiť\" nahlásiť porušovanie pravidiel moderátorom miestnosti.", - "rust_crypto": "Implementácia kryptografie Rust", "sliding_sync": "Režim kĺzavej synchronizácie", "sliding_sync_description": "V štádiu aktívneho vývoja, nie je možné to vypnúť.", "sliding_sync_disabled_notice": "Odhláste sa a znova sa prihláste, aby sa to vyplo", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 5c258a1437..1b6e3b4d2d 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -1336,7 +1336,6 @@ "pinning": "Fiksim Mesazhi", "report_to_moderators": "Raportojeni te moderatorët", "report_to_moderators_description": "Në dhoma që mbulojnë moderimin, butoni “Raportojeni” do t’ju lejojë t’u raportoni abuzim moderatorëve të dhomës.", - "rust_crypto": "Sendërtim kriptografie Rust", "sliding_sync_description": "Nën zhvillim aktiv, s’mund të çaktivizohet.", "sliding_sync_disabled_notice": "Që të çaktivizohet, dilni dhe rihyni në llogari", "sliding_sync_server_no_support": "Shërbyesit tuaj i mungon mbulim i brendshëm për këtë", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 6b1fa185e4..d995fa8abf 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -1428,11 +1428,6 @@ "render_reaction_images_description": "Ibland kallat för ”anpassade emojis”.", "report_to_moderators": "Rapportera till moderatorer", "report_to_moderators_description": "I rum som stöder moderering så låter \"Rapportera\"-knappen dig rapportera trakasseri till rumsmoderatorer.", - "rust_crypto": "Kryptografiimplementering i Rust", - "rust_crypto_in_config": "Rust-kryptografi kan inte inaktiveras på den här distributionen av %(brand)s", - "rust_crypto_in_config_description": "Byte till Rust-kryptografi kräver en migreringsprocess som kan ta flera minuter. Den kan inte inaktiveras; använd den med försiktighet!", - "rust_crypto_optin_warning": "Byte till Rust-kryptografi kräver en migreringsprocess som kan ta flera minuter. För att inaktivera måste du logga ut och in igen; använd med försiktighet!", - "rust_crypto_requires_logout": "När Rust-kryptografi har aktiverats kan den endast avaktiveras genom att logga ut och logga in igen", "sliding_sync": "Sliding sync-läge", "sliding_sync_description": "Under aktiv utveckling, kan inte inaktiveras.", "sliding_sync_disabled_notice": "Logga ut och in igen för att inaktivera", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 6f6e4f2e15..362bccc302 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -1383,7 +1383,6 @@ "pinning": "Закріплені повідомлення", "report_to_moderators": "Поскаржитись модераторам", "report_to_moderators_description": "У кімнатах, які підтримують модерацію, кнопка «Поскаржитися» дає змогу повідомити про зловживання модераторам кімнати.", - "rust_crypto": "Реалізація криптографії Rust", "sliding_sync": "Режим ковзної синхронізації", "sliding_sync_description": "На стадії активної розробки, вимкнути не можна.", "sliding_sync_disabled_notice": "Вийдіть і знову увійдіть, щоб вимкнути", diff --git a/src/i18n/strings/vi.json b/src/i18n/strings/vi.json index 1a03ecba9f..212216bf0c 100644 --- a/src/i18n/strings/vi.json +++ b/src/i18n/strings/vi.json @@ -1282,7 +1282,6 @@ "pinning": "Ghim tin nhắn", "report_to_moderators": "Báo cáo cho điều phối viên", "report_to_moderators_description": "Trong các phòng hỗ trợ điều phối, nút \"Báo cáo\" sẽ giúp bạn báo cáo lạm dụng cho điều phối viên của phòng.", - "rust_crypto": "Mã hóa dựa trên Rust", "sliding_sync": "Chế độ đồng bộ tối ưu (Sync v3)", "sliding_sync_description": "Đang được phát triển tích cực, không thể vô hiệu.", "sliding_sync_disabled_notice": "Đăng xuất và đăng nhập lại để vô hiệu hóa", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index b05fe153ff..3570cb9238 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -1302,7 +1302,6 @@ "pinning": "消息置顶", "report_to_moderators": "报告给协管员", "report_to_moderators_description": "在支持审核的房间中,“报告”按钮将让你向房间协管员举报滥用行为。", - "rust_crypto": "Rust加密实现", "sliding_sync": "滑动同步模式", "sliding_sync_description": "正在积极开发中,不能禁用。", "sliding_sync_server_no_support": "你的服务器缺少原生支持", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index aa16f591f4..5675b04889 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -1386,7 +1386,6 @@ "pinning": "訊息釘選功能", "report_to_moderators": "回報給版主", "report_to_moderators_description": "在支援審核的聊天室中,「回報」按鈕讓您可以回報濫用行為給聊天室管理員。", - "rust_crypto": "Rust 密碼學實作", "sliding_sync": "滑動同步模式", "sliding_sync_description": "正在積極開發中,無法停用。", "sliding_sync_disabled_notice": "登出並重新登入以停用", From 95c8aa3d187cd2332cda721252b8c2d050d12934 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 26 Jun 2024 07:24:43 +0100 Subject: [PATCH 19/63] [create-pull-request] automated change (#12702) Co-authored-by: github-merge-queue <118344674+github-merge-queue@users.noreply.github.com> --- playwright/plugins/homeserver/synapse/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playwright/plugins/homeserver/synapse/index.ts b/playwright/plugins/homeserver/synapse/index.ts index ed836e2637..e86020b824 100644 --- a/playwright/plugins/homeserver/synapse/index.ts +++ b/playwright/plugins/homeserver/synapse/index.ts @@ -28,7 +28,7 @@ import { randB64Bytes } from "../../utils/rand"; // Docker tag to use for `matrixdotorg/synapse` image. // We target a specific digest as every now and then a Synapse update will break our CI. // This digest is updated by the playwright-image-updates.yaml workflow periodically. -const DOCKER_TAG = "develop@sha256:38bdd185e32dbfb40d11a69a26c5b04c0ccf1cb7d4078a14d6fdb16620bd4b3c"; +const DOCKER_TAG = "develop@sha256:beb8b67e7a8a37ce95f0ebb7041579968b67eb6356b5cedfc01fad13ad175a8b"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From 86a95cfff7c1ca727f1d21019f5dac35351a1673 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Jun 2024 10:34:07 +0100 Subject: [PATCH 20/63] Switch from graphemer to Intl.Segmenter (#12697) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 1 - src/HtmlUtils.tsx | 11 +++++------ src/editor/parts.ts | 12 +++++------- src/utils/strings.ts | 8 ++++---- tsconfig.json | 2 +- 5 files changed, 15 insertions(+), 19 deletions(-) diff --git a/package.json b/package.json index 45c955aa92..1c963e8bd6 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,6 @@ "filesize": "10.1.2", "github-markdown-css": "^5.5.1", "glob-to-regexp": "^0.4.1", - "graphemer": "^1.4.0", "highlight.js": "^11.3.1", "html-entities": "^2.0.0", "is-ip": "^3.1.0", diff --git a/src/HtmlUtils.tsx b/src/HtmlUtils.tsx index 655be4ac92..d8c154440b 100644 --- a/src/HtmlUtils.tsx +++ b/src/HtmlUtils.tsx @@ -26,7 +26,6 @@ import { decode } from "html-entities"; import { IContent } from "matrix-js-sdk/src/matrix"; import { Optional } from "matrix-events-sdk"; import escapeHtml from "escape-html"; -import GraphemeSplitter from "graphemer"; import { getEmojiFromUnicode } from "@matrix-org/emojibase-bindings"; import { IExtendedSanitizeOptions } from "./@types/sanitize-html"; @@ -34,6 +33,7 @@ import SettingsStore from "./settings/SettingsStore"; import { stripHTMLReply, stripPlainReply } from "./utils/Reply"; import { PERMITTED_URL_SCHEMES } from "./utils/UrlUtils"; import { sanitizeHtmlParams, transformTags } from "./Linkify"; +import { graphemeSegmenter } from "./utils/strings"; export { Linkify, linkifyElement, linkifyAndSanitizeHtml } from "./Linkify"; @@ -265,17 +265,16 @@ export function formatEmojis(message: string | undefined, isHtmlMessage?: boolea let text = ""; let key = 0; - const splitter = new GraphemeSplitter(); - for (const char of splitter.iterateGraphemes(message)) { - if (EMOJIBASE_REGEX.test(char)) { + for (const data of graphemeSegmenter.segment(message)) { + if (EMOJIBASE_REGEX.test(data.segment)) { if (text) { result.push(text); text = ""; } - result.push(emojiToSpan(char, key)); + result.push(emojiToSpan(data.segment, key)); key++; } else { - text += char; + text += data.segment; } } if (text) { diff --git a/src/editor/parts.ts b/src/editor/parts.ts index 12262280ae..3f482357d1 100644 --- a/src/editor/parts.ts +++ b/src/editor/parts.ts @@ -17,7 +17,6 @@ limitations under the License. import EMOJIBASE_REGEX from "emojibase-regex"; import { MatrixClient, RoomMember, Room } from "matrix-js-sdk/src/matrix"; -import GraphemeSplitter from "graphemer"; import AutocompleteWrapperModel, { GetAutocompleterComponent, UpdateCallback, UpdateQuery } from "./autocomplete"; import { unicodeToShortcode } from "../HtmlUtils"; @@ -25,7 +24,7 @@ import * as Avatar from "../Avatar"; import defaultDispatcher from "../dispatcher/dispatcher"; import { Action } from "../dispatcher/actions"; import SettingsStore from "../settings/SettingsStore"; -import { getFirstGrapheme } from "../utils/strings"; +import { getFirstGrapheme, graphemeSegmenter } from "../utils/strings"; const REGIONAL_EMOJI_SEPARATOR = String.fromCodePoint(0x200b); @@ -650,19 +649,18 @@ export class PartCreator { const parts: (PlainPart | EmojiPart)[] = []; let plainText = ""; - const splitter = new GraphemeSplitter(); - for (const char of splitter.iterateGraphemes(text)) { - if (EMOJIBASE_REGEX.test(char)) { + for (const data of graphemeSegmenter.segment(text)) { + if (EMOJIBASE_REGEX.test(data.segment)) { if (plainText) { parts.push(this.plain(plainText)); plainText = ""; } - parts.push(this.emoji(char)); + parts.push(this.emoji(data.segment)); if (PartCreator.isRegionalIndicator(text)) { parts.push(this.plain(REGIONAL_EMOJI_SEPARATOR)); } } else { - plainText += char; + plainText += data.segment; } } if (plainText) { diff --git a/src/utils/strings.ts b/src/utils/strings.ts index 53039cdc8f..8f7446e491 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -21,7 +21,6 @@ limitations under the License. * @param text the plaintext to put in the user's clipboard */ import { logger } from "matrix-js-sdk/src/logger"; -import GraphemeSplitter from "graphemer"; export async function copyPlaintext(text: string): Promise { try { @@ -85,6 +84,8 @@ export function getSelectedText(): string { return window.getSelection()!.toString(); } +export const graphemeSegmenter = new Intl.Segmenter(); + /** * Returns the first grapheme in the given string, * especially useful for strings containing emoji, will not break compound emoji up. @@ -92,7 +93,6 @@ export function getSelectedText(): string { * @returns the first grapheme or an empty string if given an empty string */ export function getFirstGrapheme(str: string): string { - const splitter = new GraphemeSplitter(); - const result = splitter.iterateGraphemes(str).next(); - return result.done ? "" : result.value; + const result = graphemeSegmenter.segment(str)[Symbol.iterator]().next(); + return result.done ? "" : result.value.segment; } diff --git a/tsconfig.json b/tsconfig.json index 382874c24f..3118f598c4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,7 @@ "outDir": "./lib", "declaration": true, "jsx": "react", - "lib": ["es2021", "dom", "dom.iterable"], + "lib": ["es2022", "dom", "dom.iterable"], "strict": true }, "include": [ From 7a81470558d051d9a51c3a8607a13a608ccd1956 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Jun 2024 10:34:15 +0100 Subject: [PATCH 21/63] Pass through BASE_URL env on playwright screenshot docker wrapper (#12696) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1c963e8bd6..8e1fd2ca83 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "test:playwright:open": "yarn test:playwright --ui", "test:playwright:screenshots": "yarn test:playwright:screenshots:build && yarn test:playwright:screenshots:run", "test:playwright:screenshots:build": "docker build playwright -t matrix-react-sdk-playwright", - "test:playwright:screenshots:run": "docker run --rm --network host -v $(pwd)/../:/work/ -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it matrix-react-sdk-playwright", + "test:playwright:screenshots:run": "docker run --rm --network host -e BASE_URL -v $(pwd)/../:/work/ -v /var/run/docker.sock:/var/run/docker.sock -v /tmp/:/tmp/ -it matrix-react-sdk-playwright", "coverage": "yarn test --coverage", "lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'" }, From 72475240ece2873932d4dda586a551e31df287c3 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Jun 2024 11:59:04 +0100 Subject: [PATCH 22/63] Extract SearchScope and SearchInfo into Searching (#12698) * Extract SearchScope and SearchInfo into Searching Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * delint Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Comments Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/Searching.ts | 46 +++++++++++++++++++ src/components/structures/RoomSearchView.tsx | 3 +- src/components/structures/RoomView.tsx | 8 ++-- .../views/rooms/LegacyRoomHeader.tsx | 18 ++------ src/components/views/rooms/SearchBar.tsx | 6 +-- .../structures/RoomSearchView-test.tsx | 4 +- test/components/structures/RoomView-test.tsx | 2 +- .../views/rooms/LegacyRoomHeader-test.tsx | 2 +- .../components/views/rooms/SearchBar-test.tsx | 3 +- 9 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/Searching.ts b/src/Searching.ts index ce3ea96c72..f868942b52 100644 --- a/src/Searching.ts +++ b/src/Searching.ts @@ -681,3 +681,49 @@ export default function eventSearch( return eventIndexSearch(client, term, roomId, abortSignal); } } + +/** + * The scope for a message search, either in the current room or across all rooms. + */ +export enum SearchScope { + Room = "Room", + All = "All", +} + +/** + * Information about a message search in progress. + */ +export interface SearchInfo { + /** + * Opaque ID for this search. + */ + searchId: number; + /** + * The room ID being searched, or undefined if searching all rooms. + */ + roomId?: string; + /** + * The search term. + */ + term: string; + /** + * The scope of the search. + */ + scope: SearchScope; + /** + * The promise for the search results. + */ + promise: Promise; + /** + * Controller for aborting the search. + */ + abortController?: AbortController; + /** + * Whether the search is currently awaiting data from the backend. + */ + inProgress?: boolean; + /** + * The total count of matching results as returned by the backend. + */ + count?: number; +} diff --git a/src/components/structures/RoomSearchView.tsx b/src/components/structures/RoomSearchView.tsx index aedf2cea39..7e08057211 100644 --- a/src/components/structures/RoomSearchView.tsx +++ b/src/components/structures/RoomSearchView.tsx @@ -24,12 +24,11 @@ import { import { logger } from "matrix-js-sdk/src/logger"; import ScrollPanel from "./ScrollPanel"; -import { SearchScope } from "../views/rooms/SearchBar"; import Spinner from "../views/elements/Spinner"; import { _t } from "../../languageHandler"; import { haveRendererForEvent } from "../../events/EventTileFactory"; import SearchResultTile from "../views/rooms/SearchResultTile"; -import { searchPagination } from "../../Searching"; +import { searchPagination, SearchScope } from "../../Searching"; import Modal from "../../Modal"; import ErrorDialog from "../views/dialogs/ErrorDialog"; import ResizeNotifier from "../../utils/ResizeNotifier"; diff --git a/src/components/structures/RoomView.tsx b/src/components/structures/RoomView.tsx index 25686c53c6..3ed1c52e89 100644 --- a/src/components/structures/RoomView.tsx +++ b/src/components/structures/RoomView.tsx @@ -70,10 +70,10 @@ import TimelinePanel from "./TimelinePanel"; import ErrorBoundary from "../views/elements/ErrorBoundary"; import RoomPreviewBar from "../views/rooms/RoomPreviewBar"; import RoomPreviewCard from "../views/rooms/RoomPreviewCard"; -import SearchBar, { SearchScope } from "../views/rooms/SearchBar"; +import SearchBar from "../views/rooms/SearchBar"; import RoomUpgradeWarningBar from "../views/rooms/RoomUpgradeWarningBar"; import AuxPanel from "../views/rooms/AuxPanel"; -import LegacyRoomHeader, { ISearchInfo } from "../views/rooms/LegacyRoomHeader"; +import LegacyRoomHeader from "../views/rooms/LegacyRoomHeader"; import RoomHeader from "../views/rooms/RoomHeader"; import { IOOBData, IThreepidInvite } from "../../stores/ThreepidInviteStore"; import EffectsOverlay from "../views/elements/EffectsOverlay"; @@ -121,7 +121,7 @@ import { SDKContext } from "../../contexts/SDKContext"; import { CallStore, CallStoreEvent } from "../../stores/CallStore"; import { Call } from "../../models/Call"; import { RoomSearchView } from "./RoomSearchView"; -import eventSearch from "../../Searching"; +import eventSearch, { SearchInfo, SearchScope } from "../../Searching"; import VoipUserMapper from "../../VoipUserMapper"; import { isCallEvent } from "./LegacyCallEventGrouper"; import { WidgetType } from "../../widgets/WidgetType"; @@ -190,7 +190,7 @@ export interface IRoomState { /** * The state of an ongoing search if there is one. */ - search?: ISearchInfo; + search?: SearchInfo; callState?: CallState; activeCall: Call | null; canPeek: boolean; diff --git a/src/components/views/rooms/LegacyRoomHeader.tsx b/src/components/views/rooms/LegacyRoomHeader.tsx index 82080fbd07..c6fa28fc7c 100644 --- a/src/components/views/rooms/LegacyRoomHeader.tsx +++ b/src/components/views/rooms/LegacyRoomHeader.tsx @@ -18,7 +18,7 @@ limitations under the License. import React, { FC, useState, useMemo, useCallback } from "react"; import classNames from "classnames"; import { throttle } from "lodash"; -import { RoomStateEvent, ISearchResults } from "matrix-js-sdk/src/matrix"; +import { RoomStateEvent } from "matrix-js-sdk/src/matrix"; import { CallType } from "matrix-js-sdk/src/webrtc/call"; import { IconButton, Tooltip } from "@vector-im/compound-web"; import { ViewRoomOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/RoomViewLifecycle"; @@ -38,7 +38,6 @@ import RoomName from "../elements/RoomName"; import { E2EStatus } from "../../../utils/ShieldUtils"; import { IOOBData } from "../../../stores/ThreepidInviteStore"; import { RoomKnocksBar } from "./RoomKnocksBar"; -import { SearchScope } from "./SearchBar"; import { aboveLeftOf, ContextMenuTooltipButton, useContextMenu } from "../../structures/ContextMenu"; import RoomContextMenu from "../context_menus/RoomContextMenu"; import { contextMenuBelow } from "./RoomTile"; @@ -70,6 +69,7 @@ import { SessionDuration } from "../voip/CallDuration"; import RoomCallBanner from "../beacon/RoomCallBanner"; import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; import { UIComponent } from "../../../settings/UIFeature"; +import { SearchInfo } from "../../../Searching"; class DisabledWithReason { public constructor(public readonly reason: string) {} @@ -456,18 +456,6 @@ const CallLayoutSelector: FC = ({ call }) => { ); }; -export interface ISearchInfo { - searchId: number; - roomId?: string; - term: string; - scope: SearchScope; - promise: Promise; - abortController?: AbortController; - - inProgress?: boolean; - count?: number; -} - export interface IProps { room: Room; oobData?: IOOBData; @@ -478,7 +466,7 @@ export interface IProps { onAppsClick: (() => void) | null; e2eStatus: E2EStatus; appsShown: boolean; - searchInfo?: ISearchInfo; + searchInfo?: SearchInfo; excludedRightPanelPhaseButtons?: Array; showButtons?: boolean; enableRoomOptionsMenu?: boolean; diff --git a/src/components/views/rooms/SearchBar.tsx b/src/components/views/rooms/SearchBar.tsx index aa67bc16cf..19b076f11d 100644 --- a/src/components/views/rooms/SearchBar.tsx +++ b/src/components/views/rooms/SearchBar.tsx @@ -24,6 +24,7 @@ import { PosthogScreenTracker } from "../../../PosthogTrackers"; import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; import SearchWarning, { WarningKind } from "../elements/SearchWarning"; +import { SearchScope } from "../../../Searching"; interface IProps { onCancelClick: () => void; @@ -36,11 +37,6 @@ interface IState { scope: SearchScope; } -export enum SearchScope { - Room = "Room", - All = "All", -} - export default class SearchBar extends React.Component { private searchTerm: RefObject = createRef(); diff --git a/test/components/structures/RoomSearchView-test.tsx b/test/components/structures/RoomSearchView-test.tsx index 5d69f6595a..7ba39283b6 100644 --- a/test/components/structures/RoomSearchView-test.tsx +++ b/test/components/structures/RoomSearchView-test.tsx @@ -29,15 +29,15 @@ import { import { defer } from "matrix-js-sdk/src/utils"; import { RoomSearchView } from "../../../src/components/structures/RoomSearchView"; -import { SearchScope } from "../../../src/components/views/rooms/SearchBar"; import ResizeNotifier from "../../../src/utils/ResizeNotifier"; import { stubClient } from "../../test-utils"; import MatrixClientContext from "../../../src/contexts/MatrixClientContext"; import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; -import { searchPagination } from "../../../src/Searching"; +import { searchPagination, SearchScope } from "../../../src/Searching"; jest.mock("../../../src/Searching", () => ({ searchPagination: jest.fn(), + SearchScope: jest.requireActual("../../../src/Searching").SearchScope, })); describe("", () => { diff --git a/test/components/structures/RoomView-test.tsx b/test/components/structures/RoomView-test.tsx index 8624e56246..37351cc4e5 100644 --- a/test/components/structures/RoomView-test.tsx +++ b/test/components/structures/RoomView-test.tsx @@ -70,7 +70,7 @@ import WidgetUtils from "../../../src/utils/WidgetUtils"; import { WidgetType } from "../../../src/widgets/WidgetType"; import WidgetStore from "../../../src/stores/WidgetStore"; import { ViewRoomErrorPayload } from "../../../src/dispatcher/payloads/ViewRoomErrorPayload"; -import { SearchScope } from "../../../src/components/views/rooms/SearchBar"; +import { SearchScope } from "../../../src/Searching"; const RoomView = wrapInMatrixClientContext(_RoomView); diff --git a/test/components/views/rooms/LegacyRoomHeader-test.tsx b/test/components/views/rooms/LegacyRoomHeader-test.tsx index c01d749eea..f13c9fce9a 100644 --- a/test/components/views/rooms/LegacyRoomHeader-test.tsx +++ b/test/components/views/rooms/LegacyRoomHeader-test.tsx @@ -51,7 +51,6 @@ import { import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; import DMRoomMap from "../../../../src/utils/DMRoomMap"; import RoomHeader, { IProps as RoomHeaderProps } from "../../../../src/components/views/rooms/LegacyRoomHeader"; -import { SearchScope } from "../../../../src/components/views/rooms/SearchBar"; import { E2EStatus } from "../../../../src/utils/ShieldUtils"; import { IRoomState } from "../../../../src/components/structures/RoomView"; import RoomContext from "../../../../src/contexts/RoomContext"; @@ -69,6 +68,7 @@ import { shouldShowComponent } from "../../../../src/customisations/helpers/UICo import { UIComponent } from "../../../../src/settings/UIFeature"; import WidgetUtils from "../../../../src/utils/WidgetUtils"; import { ElementWidgetActions } from "../../../../src/stores/widgets/ElementWidgetActions"; +import { SearchScope } from "../../../../src/Searching"; jest.mock("../../../../src/customisations/helpers/UIComponents", () => ({ shouldShowComponent: jest.fn(), diff --git a/test/components/views/rooms/SearchBar-test.tsx b/test/components/views/rooms/SearchBar-test.tsx index 2dc44c1cb5..830b66e3be 100644 --- a/test/components/views/rooms/SearchBar-test.tsx +++ b/test/components/views/rooms/SearchBar-test.tsx @@ -17,8 +17,9 @@ limitations under the License. import React from "react"; import { fireEvent, render } from "@testing-library/react"; -import SearchBar, { SearchScope } from "../../../../src/components/views/rooms/SearchBar"; +import SearchBar from "../../../../src/components/views/rooms/SearchBar"; import { KeyBindingAction } from "../../../../src/accessibility/KeyboardShortcuts"; +import { SearchScope } from "../../../../src/Searching"; let mockCurrentEvent = KeyBindingAction.Enter; From ea0baee1014e6cbf73b39c2502bc2f803d354983 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 26 Jun 2024 14:04:19 +0100 Subject: [PATCH 23/63] Split out email & phone number settings to separate components & move discovery to privacy tab (#12670) * WIP update of threepid settings section * Remove email / phone number section from original place and don't show the new one if 3pids are disabled * Update snapshots * Pull identity server / 3pid binding settings out to separate component and put it in the security & privacy section which is its new home * Update snapshot * Move relevant part of test & update screenshots / snapshots * Remove unnecessary dependency * Add test for discovery settings * Add spacing in terms agreement --- .../general-user-settings-tab.spec.ts | 5 - .../security-user-settings-tab.spec.ts | 9 + .../general-linux.png | Bin 50155 -> 48582 bytes .../views/terms/_InlineTermsAgreement.pcss | 1 + .../settings/UserPersonalInfoSettings.tsx | 130 +++++++++ .../settings/discovery/DiscoverySettings.tsx | 190 +++++++++++++ .../tabs/user/GeneralUserSettingsTab.tsx | 258 +----------------- .../tabs/user/SecurityUserSettingsTab.tsx | 2 + src/i18n/strings/en_EN.json | 12 +- .../discovery/DiscoverySettings-test.tsx | 104 +++++++ .../EmailAddresses-test.tsx.snap | 2 +- .../__snapshots__/PhoneNumbers-test.tsx.snap | 2 +- .../GeneralUserSettingsTab-test.tsx.snap | 8 +- 13 files changed, 454 insertions(+), 269 deletions(-) create mode 100644 src/components/views/settings/UserPersonalInfoSettings.tsx create mode 100644 src/components/views/settings/discovery/DiscoverySettings.tsx create mode 100644 test/components/views/settings/discovery/DiscoverySettings-test.tsx diff --git a/playwright/e2e/settings/general-user-settings-tab.spec.ts b/playwright/e2e/settings/general-user-settings-tab.spec.ts index 0244962914..32946053d8 100644 --- a/playwright/e2e/settings/general-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/general-user-settings-tab.spec.ts @@ -91,11 +91,6 @@ test.describe("General user settings tab", () => { // Assert that the default value is rendered again await expect(languageInput.getByText("English")).toBeVisible(); - const setIdServer = uut.locator(".mx_SetIdServer"); - await setIdServer.scrollIntoViewIfNeeded(); - // Assert that an input area for identity server exists - await expect(setIdServer.getByRole("textbox", { name: "Enter a new identity server" })).toBeVisible(); - const setIntegrationManager = uut.locator(".mx_SetIntegrationManager"); await setIntegrationManager.scrollIntoViewIfNeeded(); await expect( diff --git a/playwright/e2e/settings/security-user-settings-tab.spec.ts b/playwright/e2e/settings/security-user-settings-tab.spec.ts index 08640f603b..5cd2a92c16 100644 --- a/playwright/e2e/settings/security-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/security-user-settings-tab.spec.ts @@ -47,5 +47,14 @@ test.describe("Security user settings tab", () => { await expect(page.locator(".mx_AnalyticsLearnMoreDialog_wrapper .mx_Dialog")).toMatchScreenshot(); }); }); + + test("should contain section to set ID server", async ({ app }) => { + const tab = await app.settings.openUserSettings("Security"); + + const setIdServer = tab.locator(".mx_SetIdServer"); + await setIdServer.scrollIntoViewIfNeeded(); + // Assert that an input area for identity server exists + await expect(setIdServer.getByRole("textbox", { name: "Enter a new identity server" })).toBeVisible(); + }); }); }); diff --git a/playwright/snapshots/settings/general-user-settings-tab.spec.ts/general-linux.png b/playwright/snapshots/settings/general-user-settings-tab.spec.ts/general-linux.png index 73666d61c0ee380bef6ca1bfa42c2aaec999cb8d..4fa467dd351714e8d469e3f4b59347d5b17e80a4 100644 GIT binary patch delta 11831 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 WJ3G^OvVv~f@>Wz@q(E5v)Bghe0#ZBx diff --git a/res/css/views/terms/_InlineTermsAgreement.pcss b/res/css/views/terms/_InlineTermsAgreement.pcss index d7732b2a0d..162d1341e4 100644 --- a/res/css/views/terms/_InlineTermsAgreement.pcss +++ b/res/css/views/terms/_InlineTermsAgreement.pcss @@ -15,6 +15,7 @@ limitations under the License. */ .mx_InlineTermsAgreement_cbContainer { + margin-top: var(--cpd-space-4x); margin-bottom: 10px; font: var(--cpd-font-body-md-regular); diff --git a/src/components/views/settings/UserPersonalInfoSettings.tsx b/src/components/views/settings/UserPersonalInfoSettings.tsx new file mode 100644 index 0000000000..8e5880a517 --- /dev/null +++ b/src/components/views/settings/UserPersonalInfoSettings.tsx @@ -0,0 +1,130 @@ +/* +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, { useCallback, useEffect, useState } from "react"; +import { ThreepidMedium } from "matrix-js-sdk/src/matrix"; +import { Alert } from "@vector-im/compound-web"; + +import AccountEmailAddresses from "./account/EmailAddresses"; +import AccountPhoneNumbers from "./account/PhoneNumbers"; +import { _t } from "../../../languageHandler"; +import InlineSpinner from "../elements/InlineSpinner"; +import SettingsSubsection from "./shared/SettingsSubsection"; +import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; +import { ThirdPartyIdentifier } from "../../../AddThreepid"; +import SettingsStore from "../../../settings/SettingsStore"; +import { UIFeature } from "../../../settings/UIFeature"; + +type LoadingState = "loading" | "loaded" | "error"; + +interface ThreepidSectionWrapperProps { + error: string; + loadingState: LoadingState; + children: React.ReactNode; +} + +const ThreepidSectionWrapper: React.FC = ({ error, loadingState, children }) => { + if (loadingState === "loading") { + return ; + } else if (loadingState === "error") { + return ( + + {error} + + ); + } else { + return <>{children}; + } +}; + +interface UserPersonalInfoSettingsProps { + canMake3pidChanges: boolean; +} + +/** + * Settings controls allowing the user to set personal information like email addresses. + */ +export const UserPersonalInfoSettings: React.FC = ({ canMake3pidChanges }) => { + const [emails, setEmails] = useState(); + const [phoneNumbers, setPhoneNumbers] = useState(); + const [loadingState, setLoadingState] = useState<"loading" | "loaded" | "error">("loading"); + + const client = useMatrixClientContext(); + + useEffect(() => { + (async () => { + try { + const threepids = await client.getThreePids(); + setEmails(threepids.threepids.filter((a) => a.medium === ThreepidMedium.Email)); + setPhoneNumbers(threepids.threepids.filter((a) => a.medium === ThreepidMedium.Phone)); + setLoadingState("loaded"); + } catch (e) { + setLoadingState("error"); + } + })(); + }, [client]); + + const onEmailsChange = useCallback((emails: ThirdPartyIdentifier[]) => { + setEmails(emails); + }, []); + + const onMsisdnsChange = useCallback((msisdns: ThirdPartyIdentifier[]) => { + setPhoneNumbers(msisdns); + }, []); + + if (!SettingsStore.getValue(UIFeature.ThirdPartyID)) return null; + + return ( +
+

{_t("settings|general|personal_info")}

+ + + + + + + + + + + +
+ ); +}; + +export default UserPersonalInfoSettings; diff --git a/src/components/views/settings/discovery/DiscoverySettings.tsx b/src/components/views/settings/discovery/DiscoverySettings.tsx new file mode 100644 index 0000000000..8b1a20ac2e --- /dev/null +++ b/src/components/views/settings/discovery/DiscoverySettings.tsx @@ -0,0 +1,190 @@ +/* +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, { useCallback, useEffect, useState } from "react"; +import { SERVICE_TYPES, ThreepidMedium } from "matrix-js-sdk/src/matrix"; +import { logger } from "matrix-js-sdk/src/logger"; +import { Alert } from "@vector-im/compound-web"; + +import DiscoveryEmailAddresses from "../discovery/EmailAddresses"; +import DiscoveryPhoneNumbers from "../discovery/PhoneNumbers"; +import { getThreepidsWithBindStatus } from "../../../../boundThreepids"; +import { useMatrixClientContext } from "../../../../contexts/MatrixClientContext"; +import { ThirdPartyIdentifier } from "../../../../AddThreepid"; +import SettingsStore from "../../../../settings/SettingsStore"; +import { UIFeature } from "../../../../settings/UIFeature"; +import { _t } from "../../../../languageHandler"; +import SetIdServer from "../SetIdServer"; +import SettingsSubsection from "../shared/SettingsSubsection"; +import InlineTermsAgreement from "../../terms/InlineTermsAgreement"; +import { Service, ServicePolicyPair, startTermsFlow } from "../../../../Terms"; +import IdentityAuthClient from "../../../../IdentityAuthClient"; +import { abbreviateUrl } from "../../../../utils/UrlUtils"; +import { useDispatcher } from "../../../../hooks/useDispatcher"; +import defaultDispatcher from "../../../../dispatcher/dispatcher"; +import { ActionPayload } from "../../../../dispatcher/payloads"; + +type RequiredPolicyInfo = + | { + // This object is passed along to a component for handling + policiesAndServices: null; // From the startTermsFlow callback + agreedUrls: null; // From the startTermsFlow callback + resolve: null; // Promise resolve function for startTermsFlow callback + } + | { + policiesAndServices: ServicePolicyPair[]; + agreedUrls: string[]; + resolve: (values: string[]) => void; + }; + +/** + * Settings controlling how a user's email addreses and phone numbers can be used to discover them + */ +export const DiscoverySettings: React.FC = () => { + const client = useMatrixClientContext(); + + const [emails, setEmails] = useState([]); + const [phoneNumbers, setPhoneNumbers] = useState([]); + const [loadingState, setLoadingState] = useState<"loading" | "loaded" | "error">("loading"); + const [idServerName, setIdServerName] = useState(abbreviateUrl(client.getIdentityServerUrl())); + const [canMake3pidChanges, setCanMake3pidChanges] = useState(false); + + const [requiredPolicyInfo, setRequiredPolicyInfo] = useState({ + // This object is passed along to a component for handling + policiesAndServices: null, // From the startTermsFlow callback + agreedUrls: null, // From the startTermsFlow callback + resolve: null, // Promise resolve function for startTermsFlow callback + }); + const [hasTerms, setHasTerms] = useState(false); + + const getThreepidState = useCallback(async () => { + const threepids = await getThreepidsWithBindStatus(client); + setEmails(threepids.filter((a) => a.medium === ThreepidMedium.Email)); + setPhoneNumbers(threepids.filter((a) => a.medium === ThreepidMedium.Phone)); + }, [client]); + + useDispatcher( + defaultDispatcher, + useCallback( + (payload: ActionPayload) => { + if (payload.action === "id_server_changed") { + setIdServerName(abbreviateUrl(client.getIdentityServerUrl())); + + getThreepidState().then(); + } + }, + [client, getThreepidState], + ), + ); + + useEffect(() => { + (async () => { + try { + await getThreepidState(); + + const capabilities = await client.getCapabilities(); + setCanMake3pidChanges( + !capabilities["m.3pid_changes"] || capabilities["m.3pid_changes"].enabled === true, + ); + + // By starting the terms flow we get the logic for checking which terms the user has signed + // for free. So we might as well use that for our own purposes. + const idServerUrl = client.getIdentityServerUrl(); + if (!idServerUrl) { + return; + } + + const authClient = new IdentityAuthClient(); + try { + const idAccessToken = await authClient.getAccessToken({ check: false }); + await startTermsFlow( + client, + [new Service(SERVICE_TYPES.IS, idServerUrl, idAccessToken!)], + (policiesAndServices, agreedUrls, extraClassNames) => { + return new Promise((resolve) => { + setIdServerName(abbreviateUrl(idServerUrl)); + setHasTerms(true); + setRequiredPolicyInfo({ + policiesAndServices, + agreedUrls, + resolve, + }); + }); + }, + ); + // User accepted all terms + setHasTerms(false); + } catch (e) { + logger.warn( + `Unable to reach identity server at ${idServerUrl} to check ` + `for terms in Settings`, + ); + logger.warn(e); + } + + setLoadingState("loaded"); + } catch (e) { + setLoadingState("error"); + } + })(); + }, [client, getThreepidState]); + + if (!SettingsStore.getValue(UIFeature.ThirdPartyID)) return null; + + if (hasTerms && requiredPolicyInfo.policiesAndServices) { + const intro = ( + + {_t("settings|general|discovery_needs_terms", { serverName: idServerName })} + + ); + return ( + <> + + {/* has its own heading as it includes the current identity server */} + + + ); + } + + const threepidSection = idServerName ? ( + <> + + + + ) : null; + + return ( + + {threepidSection} + {/* has its own heading as it includes the current identity server */} + + + ); +}; + +export default DiscoverySettings; diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx index 0e32b9126c..3b53e5f2f1 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx @@ -17,10 +17,9 @@ limitations under the License. */ import React, { ReactNode } from "react"; -import { SERVICE_TYPES, HTTPError, IThreepid, ThreepidMedium } from "matrix-js-sdk/src/matrix"; +import { HTTPError } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; -import { Icon as WarningIcon } from "../../../../../../res/img/feather-customised/warning-triangle.svg"; import { UserFriendlyError, _t } from "../../../../../languageHandler"; import UserProfileSettings from "../../UserProfileSettings"; import * as languageHandler from "../../../../../languageHandler"; @@ -31,22 +30,10 @@ import AccessibleButton from "../../../elements/AccessibleButton"; import DeactivateAccountDialog from "../../../dialogs/DeactivateAccountDialog"; import PlatformPeg from "../../../../../PlatformPeg"; import Modal from "../../../../../Modal"; -import dis from "../../../../../dispatcher/dispatcher"; -import { Service, ServicePolicyPair, startTermsFlow } from "../../../../../Terms"; -import IdentityAuthClient from "../../../../../IdentityAuthClient"; -import { abbreviateUrl } from "../../../../../utils/UrlUtils"; -import { getThreepidsWithBindStatus } from "../../../../../boundThreepids"; import { SettingLevel } from "../../../../../settings/SettingLevel"; import { UIFeature } from "../../../../../settings/UIFeature"; -import { ActionPayload } from "../../../../../dispatcher/payloads"; import ErrorDialog, { extractErrorMessageFromError } from "../../../dialogs/ErrorDialog"; -import AccountPhoneNumbers from "../../account/PhoneNumbers"; -import AccountEmailAddresses from "../../account/EmailAddresses"; -import DiscoveryEmailAddresses from "../../discovery/EmailAddresses"; -import DiscoveryPhoneNumbers from "../../discovery/PhoneNumbers"; import ChangePassword from "../../ChangePassword"; -import InlineTermsAgreement from "../../../terms/InlineTermsAgreement"; -import SetIdServer from "../../SetIdServer"; import SetIntegrationManager from "../../SetIntegrationManager"; import ToggleSwitch from "../../../elements/ToggleSwitch"; import { IS_MAC } from "../../../../../Keyboard"; @@ -54,10 +41,8 @@ import SettingsTab from "../SettingsTab"; import { SettingsSection } from "../../shared/SettingsSection"; import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection"; import { SettingsSubsectionHeading } from "../../shared/SettingsSubsectionHeading"; -import Heading from "../../../typography/Heading"; -import InlineSpinner from "../../../elements/InlineSpinner"; -import { ThirdPartyIdentifier } from "../../../../../AddThreepid"; import { SDKContext } from "../../../../../contexts/SDKContext"; +import UserPersonalInfoSettings from "../../UserPersonalInfoSettings"; interface IProps { closeSettingsFn: () => void; @@ -67,25 +52,6 @@ interface IState { language: string; spellCheckEnabled?: boolean; spellCheckLanguages: string[]; - haveIdServer: boolean; - idServerHasUnsignedTerms: boolean; - requiredPolicyInfo: - | { - // This object is passed along to a component for handling - hasTerms: false; - policiesAndServices: null; // From the startTermsFlow callback - agreedUrls: null; // From the startTermsFlow callback - resolve: null; // Promise resolve function for startTermsFlow callback - } - | { - hasTerms: boolean; - policiesAndServices: ServicePolicyPair[]; - agreedUrls: string[]; - resolve: (values: string[]) => void; - }; - emails: ThirdPartyIdentifier[]; - msisdns: ThirdPartyIdentifier[]; - loading3pids: boolean; // whether or not the emails and msisdns have been loaded canChangePassword: boolean; idServerName?: string; externalAccountManagementUrl?: string; @@ -96,38 +62,19 @@ export default class GeneralUserSettingsTab extends React.Component; - private readonly dispatcherRef: string; - public constructor(props: IProps, context: React.ContextType) { super(props); this.context = context; - const cli = this.context.client!; - this.state = { language: languageHandler.getCurrentLanguage(), spellCheckEnabled: false, spellCheckLanguages: [], - haveIdServer: Boolean(cli.getIdentityServerUrl()), - idServerHasUnsignedTerms: false, - requiredPolicyInfo: { - // This object is passed along to a component for handling - hasTerms: false, - policiesAndServices: null, // From the startTermsFlow callback - agreedUrls: null, // From the startTermsFlow callback - resolve: null, // Promise resolve function for startTermsFlow callback - }, - emails: [], - msisdns: [], - loading3pids: true, // whether or not the emails and msisdns have been loaded canChangePassword: false, canMake3pidChanges: false, }; - this.dispatcherRef = dis.register(this.onAction); - this.getCapabilities(); - this.getThreepidState(); } public async componentDidMount(): Promise { @@ -145,25 +92,6 @@ export default class GeneralUserSettingsTab extends React.Component { - if (payload.action === "id_server_changed") { - this.setState({ haveIdServer: Boolean(this.context.client!.getIdentityServerUrl()) }); - this.getThreepidState(); - } - }; - - private onEmailsChange = (emails: ThirdPartyIdentifier[]): void => { - this.setState({ emails }); - }; - - private onMsisdnsChange = (msisdns: ThirdPartyIdentifier[]): void => { - this.setState({ msisdns }); - }; - private async getCapabilities(): Promise { const cli = this.context.client!; @@ -185,73 +113,6 @@ export default class GeneralUserSettingsTab extends React.Component { - const cli = this.context.client!; - - // Check to see if terms need accepting - this.checkTerms(); - - // Need to get 3PIDs generally for Account section and possibly also for - // Discovery (assuming we have an IS and terms are agreed). - let threepids: IThreepid[] = []; - try { - threepids = await getThreepidsWithBindStatus(cli); - } catch (e) { - const idServerUrl = cli.getIdentityServerUrl(); - logger.warn( - `Unable to reach identity server at ${idServerUrl} to check ` + `for 3PIDs bindings in Settings`, - ); - logger.warn(e); - } - this.setState({ - emails: threepids.filter((a) => a.medium === ThreepidMedium.Email), - msisdns: threepids.filter((a) => a.medium === ThreepidMedium.Phone), - loading3pids: false, - }); - } - - private async checkTerms(): Promise { - // By starting the terms flow we get the logic for checking which terms the user has signed - // for free. So we might as well use that for our own purposes. - const idServerUrl = this.context.client!.getIdentityServerUrl(); - if (!this.state.haveIdServer || !idServerUrl) { - this.setState({ idServerHasUnsignedTerms: false }); - return; - } - - const authClient = new IdentityAuthClient(); - try { - const idAccessToken = await authClient.getAccessToken({ check: false }); - await startTermsFlow( - this.context.client!, - [new Service(SERVICE_TYPES.IS, idServerUrl, idAccessToken!)], - (policiesAndServices, agreedUrls, extraClassNames) => { - return new Promise((resolve, reject) => { - this.setState({ - idServerName: abbreviateUrl(idServerUrl), - requiredPolicyInfo: { - hasTerms: true, - policiesAndServices, - agreedUrls, - resolve, - }, - }); - }); - }, - ); - // User accepted all terms - this.setState({ - requiredPolicyInfo: { - ...this.state.requiredPolicyInfo, // set first so we can override - hasTerms: false, - }, - }); - } catch (e) { - logger.warn(`Unable to reach identity server at ${idServerUrl} to check ` + `for terms in Settings`); - logger.warn(e); - } - } - private onLanguageChange = (newLanguage: string): void => { if (this.state.language === newLanguage) return; @@ -324,48 +185,6 @@ export default class GeneralUserSettingsTab extends React.Component - ) : ( - - ); - const msisdns = this.state.loading3pids ? ( - - ) : ( - - ); - threepidSection = ( - <> - - {emails} - - - - {msisdns} - - - ); - } - let passwordChangeSection: ReactNode = null; if (this.state.canChangePassword) { passwordChangeSection = ( @@ -419,7 +238,6 @@ export default class GeneralUserSettingsTab extends React.Component - {threepidSection} ); } @@ -455,51 +273,6 @@ export default class GeneralUserSettingsTab extends React.Component - {_t("settings|general|discovery_needs_terms", { serverName: this.state.idServerName })} - - ); - return ( - <> - - {/* has its own heading as it includes the current identity server */} - - - ); - } - - const threepidSection = this.state.haveIdServer ? ( - <> - - - - ) : null; - - return ( - <> - {threepidSection} - {/* has its own heading as it includes the current identity server */} - - - ); - } - private renderManagementSection(): JSX.Element { // TODO: Improve warning text for account deactivation return ( @@ -533,40 +306,15 @@ export default class GeneralUserSettingsTab extends React.Component - ) : null; - const heading = ( - - {discoWarning} - {_t("settings|general|discovery_section")} - - ); - discoverySection = ( - - {this.renderDiscoverySection()} - - ); - } - return ( + {this.renderAccountSection()} {this.renderLanguageSection()} {supportsMultiLanguageSpellCheck ? this.renderSpellCheckSection() : null} - {discoverySection} {this.renderIntegrationManagerSection()} {accountManagementSection} diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index 80c02bb546..c636721201 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -43,6 +43,7 @@ import SettingsTab from "../SettingsTab"; import { SettingsSection } from "../../shared/SettingsSection"; import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection"; import { useOwnDevices } from "../../devices/useOwnDevices"; +import DiscoverySettings from "../../discovery/DiscoverySettings"; interface IIgnoredUserProps { userId: string; @@ -336,6 +337,7 @@ export default class SecurityUserSettingsTab extends React.Component + /plain to send without markdown.", @@ -2479,11 +2482,11 @@ "deactivate_section": "Deactivate Account", "deactivate_warning": "Deactivating your account is a permanent action — be careful!", "dialog_title": "Settings: General", - "discovery_email_empty": "Discovery options will appear once you have added an email above.", + "discovery_email_empty": "Discovery options will appear once you have added an email.", "discovery_email_verification_instructions": "Verify the link in your inbox", - "discovery_msisdn_empty": "Discovery options will appear once you have added a phone number above.", + "discovery_msisdn_empty": "Discovery options will appear once you have added a phone number.", "discovery_needs_terms": "Agree to the identity server (%(serverName)s) Terms of Service to allow yourself to be discoverable by email address or phone number.", - "discovery_section": "Discovery", + "discovery_needs_terms_title": "Let people find you", "display_name": "Display Name", "display_name_error": "Unable to set display name", "email_address_in_use": "This email address is already in use", @@ -2522,11 +2525,14 @@ "oidc_manage_button": "Manage account", "password_change_section": "Set a new account password…", "password_change_success": "Your password was successfully changed.", + "personal_info": "Personal info", "profile_subtitle": "This is how you appear to others on the app.", "remove_email_prompt": "Remove %(email)s?", "remove_msisdn_prompt": "Remove %(phone)s?", "spell_check_locale_placeholder": "Choose a locale", "spell_check_section": "Spell check", + "unable_to_load_emails": "Unable to load email addresses", + "unable_to_load_msisdns": "Unable to load phone numbers", "username": "Username" }, "image_thumbnails": "Show previews/thumbnails for images", diff --git a/test/components/views/settings/discovery/DiscoverySettings-test.tsx b/test/components/views/settings/discovery/DiscoverySettings-test.tsx new file mode 100644 index 0000000000..51a976bbc0 --- /dev/null +++ b/test/components/views/settings/discovery/DiscoverySettings-test.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 from "react"; +import { act, render, screen } from "@testing-library/react"; +import { MatrixClient } from "matrix-js-sdk/src/matrix"; +import { mocked } from "jest-mock"; +import userEvent from "@testing-library/user-event"; + +import DiscoverySettings from "../../../../../src/components/views/settings/discovery/DiscoverySettings"; +import { stubClient } from "../../../../test-utils"; +import MatrixClientContext from "../../../../../src/contexts/MatrixClientContext"; +import { UIFeature } from "../../../../../src/settings/UIFeature"; +import SettingsStore from "../../../../../src/settings/SettingsStore"; +import defaultDispatcher from "../../../../../src/dispatcher/dispatcher"; + +const mockGetAccessToken = jest.fn().mockResolvedValue("$$getAccessToken"); +jest.mock("../../../../../src/IdentityAuthClient", () => + jest.fn().mockImplementation(() => ({ + getAccessToken: mockGetAccessToken, + })), +); + +describe("DiscoverySettings", () => { + let client: MatrixClient; + + beforeEach(() => { + client = stubClient(); + }); + + afterEach(() => { + jest.restoreAllMocks(); + }); + + const DiscoveryWrapper = (props = {}) => ; + + it("is empty if 3pid features are disabled", async () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((key) => { + if (key === UIFeature.ThirdPartyID) return false; + }); + + const { container } = render(, { wrapper: DiscoveryWrapper }); + + expect(container).toBeEmptyDOMElement(); + }); + + it("displays alert if an identity server needs terms accepting", async () => { + mocked(client).getIdentityServerUrl.mockReturnValue("https://example.com"); + mocked(client).getTerms.mockResolvedValue({ + ["policies"]: { en: "No ball games" }, + }); + + render(, { wrapper: DiscoveryWrapper }); + + await expect(await screen.findByText("Let people find you")).toBeInTheDocument(); + }); + + it("button to accept terms is disabled if checkbox not checked", async () => { + mocked(client).getIdentityServerUrl.mockReturnValue("https://example.com"); + mocked(client).getTerms.mockResolvedValue({ + ["policies"]: { en: "No ball games" }, + }); + + render(, { wrapper: DiscoveryWrapper }); + + const acceptCheckbox = await screen.findByRole("checkbox", { name: "Accept" }); + const continueButton = screen.getByRole("button", { name: "Continue" }); + expect(acceptCheckbox).toBeInTheDocument(); + expect(continueButton).toHaveAttribute("aria-disabled", "true"); + + await userEvent.click(acceptCheckbox); + expect(continueButton).not.toHaveAttribute("aria-disabled", "true"); + }); + + it("updates if ID server is changed", async () => { + render(, { wrapper: DiscoveryWrapper }); + + mocked(client).getThreePids.mockClear(); + + act(() => { + defaultDispatcher.dispatch( + { + action: "id_server_changed", + }, + true, + ); + }); + + expect(client.getThreePids).toHaveBeenCalled(); + }); +}); diff --git a/test/components/views/settings/discovery/__snapshots__/EmailAddresses-test.tsx.snap b/test/components/views/settings/discovery/__snapshots__/EmailAddresses-test.tsx.snap index 275f864dfc..536c72e8eb 100644 --- a/test/components/views/settings/discovery/__snapshots__/EmailAddresses-test.tsx.snap +++ b/test/components/views/settings/discovery/__snapshots__/EmailAddresses-test.tsx.snap @@ -20,7 +20,7 @@ exports[` should handle no email addresses 1`] = `
- Discovery options will appear once you have added an email above. + Discovery options will appear once you have added an email.
diff --git a/test/components/views/settings/discovery/__snapshots__/PhoneNumbers-test.tsx.snap b/test/components/views/settings/discovery/__snapshots__/PhoneNumbers-test.tsx.snap index 00a136ca84..948ee105b0 100644 --- a/test/components/views/settings/discovery/__snapshots__/PhoneNumbers-test.tsx.snap +++ b/test/components/views/settings/discovery/__snapshots__/PhoneNumbers-test.tsx.snap @@ -83,7 +83,7 @@ exports[` should handle no numbers 1`] = `
- Discovery options will appear once you have added a phone number above. + Discovery options will appear once you have added a phone number.
diff --git a/test/components/views/settings/tabs/user/__snapshots__/GeneralUserSettingsTab-test.tsx.snap b/test/components/views/settings/tabs/user/__snapshots__/GeneralUserSettingsTab-test.tsx.snap index 04e786dc7d..8d15bf8e7e 100644 --- a/test/components/views/settings/tabs/user/__snapshots__/GeneralUserSettingsTab-test.tsx.snap +++ b/test/components/views/settings/tabs/user/__snapshots__/GeneralUserSettingsTab-test.tsx.snap @@ -42,14 +42,14 @@ exports[` 3pids should display 3pid email addresses an > @@ -150,14 +150,14 @@ exports[` 3pids should display 3pid email addresses an From 8ede89101af6efc8bd353001e13097598ec477fe Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 26 Jun 2024 15:17:12 +0100 Subject: [PATCH 24/63] Adjust room header hover transition from 300ms to 200ms (#12703) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/views/rooms/_RoomHeader.pcss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/css/views/rooms/_RoomHeader.pcss b/res/css/views/rooms/_RoomHeader.pcss index bc66cd2141..6a25ea7943 100644 --- a/res/css/views/rooms/_RoomHeader.pcss +++ b/res/css/views/rooms/_RoomHeader.pcss @@ -20,7 +20,7 @@ limitations under the License. padding: 0 var(--cpd-space-3x); border-bottom: 1px solid $separator; background-color: $background; - transition: all 0.3s ease; + transition: all 0.2s ease; } .mx_RoomHeader:hover { From 33a017b52876800728622b1b35247e25f4d7db46 Mon Sep 17 00:00:00 2001 From: Florian Duros Date: Wed, 26 Jun 2024 17:47:01 +0200 Subject: [PATCH 25/63] New theme ui in user settings (#12576) * Add hook to get the theme * Adapt subsection settings to new ui * WIP new theme subsection * Add theme selection * Fix test types * Disabled theme selector when system theme is used * Update compound to `4.4.1` * Add custom theme support * Remove old ThemChoicePanel * Fix QuickThemeSwitcher-test.tsx * Fix AppearanceUserSettingsTab-test.tsx * Update i18n * Fix ThemeChoicePanel-test.tsx * Update `@vector-im/compound-web` * Small tweaks * Fix CSS comments and use compound variable * Remove custom theme title * i18n: update * test: add tests to theme selection * test: update AppearanceUserSettingsTab-test snapshot * test: rework custom theme * playwright: fix audio-player.spec.ts * playwright: appearance tab * test: update snapshot * playright: add custom theme * i18n: use correct char for ellipsis * a11y: add missing aria-label to delete button * dialog: update close button tooltip * theme: remove local state and handle custom delete * theme: don't add twice the same custom theme * test: update snapshot * playwright: update snapshot * custom theme: add background to custom theme list * update compound web * Use new destructive property on `IconButton` of theme panel * test: update snapshots * rename new ui into legacy * remove wrong constructor doc * fix theme selector padding * theme selector: fix key * test: fix e2e --- .../e2e/audio-player/audio-player.spec.ts | 2 +- .../appearance-user-settings-tab.spec.ts | 96 ++- .../appearance-user-settings-tab/index.ts | 139 ++++ .../message-edit-history-dialog-linux.png | Bin 7854 -> 7313 bytes .../appearance-tab-linux.png | Bin 0 -> 49857 bytes .../theme-panel-custom-theme-added-linux.png | Bin 0 -> 17296 bytes .../theme-panel-custom-theme-linux.png | Bin 0 -> 14633 bytes .../theme-panel-dark-linux.png | Bin 0 -> 8711 bytes .../theme-panel-light-linux.png | Bin 0 -> 9167 bytes ...theme-panel-match-system-enabled-linux.png | Bin 0 -> 8367 bytes .../window-12px-linux.png | Bin 0 -> 65730 bytes res/css/_common.pcss | 14 +- .../settings/shared/_SettingsSubsection.pcss | 10 + res/css/views/settings/_ThemeChoicePanel.pcss | 96 ++- src/components/views/dialogs/BaseDialog.tsx | 3 +- .../views/settings/ThemeChoicePanel.tsx | 575 +++++++------ .../settings/shared/SettingsSubsection.tsx | 18 +- .../shared/SettingsSubsectionHeading.tsx | 26 +- .../tabs/user/AppearanceUserSettingsTab.tsx | 2 +- .../views/spaces/QuickThemeSwitcher.tsx | 8 +- src/hooks/useSettings.ts | 34 + src/hooks/useTheme.ts | 53 ++ src/i18n/strings/en_EN.json | 12 +- src/settings/SettingsStore.ts | 6 +- src/theme.ts | 2 +- .../views/settings/ThemeChoicePanel-test.tsx | 172 +++- .../ThemeChoicePanel-test.tsx.snap | 785 +++++++++++++++++- .../user/PreferencesUserSettingsTab-test.tsx | 9 +- .../AppearanceUserSettingsTab-test.tsx.snap | 147 +++- .../views/spaces/QuickThemeSwitcher-test.tsx | 17 +- 30 files changed, 1749 insertions(+), 477 deletions(-) rename playwright/e2e/settings/{ => appearance-user-settings-tab}/appearance-user-settings-tab.spec.ts (64%) create mode 100644 playwright/e2e/settings/appearance-user-settings-tab/index.ts create mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png create mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-custom-theme-added-linux.png create mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-custom-theme-linux.png create mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-dark-linux.png create mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-light-linux.png create mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-match-system-enabled-linux.png create mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/window-12px-linux.png create mode 100644 src/hooks/useTheme.ts diff --git a/playwright/e2e/audio-player/audio-player.spec.ts b/playwright/e2e/audio-player/audio-player.spec.ts index 4581801db5..e60d273299 100644 --- a/playwright/e2e/audio-player/audio-player.spec.ts +++ b/playwright/e2e/audio-player/audio-player.spec.ts @@ -160,7 +160,7 @@ test.describe("Audio player", () => { // Enable high contrast manually const settings = await app.settings.openUserSettings("Appearance"); - await settings.getByTestId("mx_ThemeChoicePanel").getByText("Use high contrast").click(); + await settings.getByRole("radio", { name: "High contrast" }).click(); await app.closeDialog(); diff --git a/playwright/e2e/settings/appearance-user-settings-tab.spec.ts b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts similarity index 64% rename from playwright/e2e/settings/appearance-user-settings-tab.spec.ts rename to playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts index 7e16d73955..efbdb777fd 100644 --- a/playwright/e2e/settings/appearance-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts @@ -14,8 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { test, expect } from "../../element-web-test"; -import { SettingLevel } from "../../../src/settings/SettingLevel"; +import { expect, test } from "."; test.describe("Appearance user settings tab", () => { test.use({ @@ -151,69 +150,68 @@ test.describe("Appearance user settings tab", () => { }); test.describe("Theme Choice Panel", () => { - test.beforeEach(async ({ app, user }) => { + test.beforeEach(async ({ app, user, util }) => { // Disable the default theme for consistency in case ThemeWatcher automatically chooses it - await app.settings.setValue("use_system_theme", null, SettingLevel.DEVICE, false); + await util.disableSystemTheme(); + await util.openAppearanceTab(); }); - test("should be rendered with the light theme selected", async ({ page, app }) => { - await app.settings.openUserSettings("Appearance"); - const themePanel = page.getByTestId("mx_ThemeChoicePanel"); - - const useSystemTheme = themePanel.getByTestId("checkbox-use-system-theme"); - await expect(useSystemTheme.getByText("Match system theme")).toBeVisible(); + test("should be rendered with the light theme selected", async ({ page, app, util }) => { // Assert that 'Match system theme' is not checked - // Note that mx_Checkbox_checkmark exists and is hidden by CSS if it is not checked - await expect(useSystemTheme.locator(".mx_Checkbox_checkmark")).not.toBeVisible(); + await expect(util.getMatchSystemThemeCheckbox()).not.toBeChecked(); - const selectors = themePanel.getByTestId("theme-choice-panel-selectors"); - await expect(selectors.locator(".mx_ThemeSelector_light")).toBeVisible(); - await expect(selectors.locator(".mx_ThemeSelector_dark")).toBeVisible(); // Assert that the light theme is selected - await expect(selectors.locator(".mx_ThemeSelector_light.mx_StyledRadioButton_enabled")).toBeVisible(); - // Assert that the buttons for the light and dark theme are not enabled - await expect(selectors.locator(".mx_ThemeSelector_light.mx_StyledRadioButton_disabled")).not.toBeVisible(); - await expect(selectors.locator(".mx_ThemeSelector_dark.mx_StyledRadioButton_disabled")).not.toBeVisible(); + await expect(util.getLightTheme()).toBeChecked(); + // Assert that the dark and high contrast themes are not selected + await expect(util.getDarkTheme()).not.toBeChecked(); + await expect(util.getHighContrastTheme()).not.toBeChecked(); - // Assert that the checkbox for the high contrast theme is rendered - await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).toBeVisible(); + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-light.png"); }); - test("should disable the labels for themes and the checkbox for the high contrast theme if the checkbox for the system theme is clicked", async ({ - page, - app, - }) => { - await app.settings.openUserSettings("Appearance"); - const themePanel = page.getByTestId("mx_ThemeChoicePanel"); + test("should disable the themes when the system theme is clicked", async ({ page, app, util }) => { + await util.getMatchSystemThemeCheckbox().click(); - await themePanel.locator(".mx_Checkbox", { hasText: "Match system theme" }).click(); + // Assert that the themes are disabled + await expect(util.getLightTheme()).toBeDisabled(); + await expect(util.getDarkTheme()).toBeDisabled(); + await expect(util.getHighContrastTheme()).toBeDisabled(); - // Assert that the labels for the light theme and dark theme are disabled - await expect(themePanel.locator(".mx_ThemeSelector_light.mx_StyledRadioButton_disabled")).toBeVisible(); - await expect(themePanel.locator(".mx_ThemeSelector_dark.mx_StyledRadioButton_disabled")).toBeVisible(); - - // Assert that there does not exist a label for an enabled theme - await expect(themePanel.locator("label.mx_StyledRadioButton_enabled")).not.toBeVisible(); - - // Assert that the checkbox and label to enable the high contrast theme should not exist - await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).not.toBeVisible(); + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-match-system-enabled.png"); }); - test("should not render the checkbox and the label for the high contrast theme if the dark theme is selected", async ({ - page, - app, - }) => { - await app.settings.openUserSettings("Appearance"); - const themePanel = page.getByTestId("mx_ThemeChoicePanel"); + test("should change the theme to dark", async ({ page, app, util }) => { + // Assert that the light theme is selected + await expect(util.getLightTheme()).toBeChecked(); - // Assert that the checkbox and the label to enable the high contrast theme should exist - await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).toBeVisible(); + await util.getDarkTheme().click(); - // Enable the dark theme - await themePanel.locator(".mx_ThemeSelector_dark").click(); + // Assert that the light and high contrast themes are not selected + await expect(util.getLightTheme()).not.toBeChecked(); + await expect(util.getDarkTheme()).toBeChecked(); + await expect(util.getHighContrastTheme()).not.toBeChecked(); - // Assert that the checkbox and the label should not exist - await expect(themePanel.locator(".mx_Checkbox", { hasText: "Use high contrast" })).not.toBeVisible(); + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-dark.png"); + }); + + test.describe("custom theme", () => { + test.use({ + labsFlags: ["feature_custom_themes"], + }); + + test("should render the custom theme section", async ({ page, app, util }) => { + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme.png"); + }); + + test("should be able to add and remove a custom theme", async ({ page, app, util }) => { + await util.addCustomTheme(); + + await expect(util.getCustomTheme()).not.toBeChecked(); + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme-added.png"); + + await util.removeCustomTheme(); + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-custom-theme.png"); + }); }); }); }); diff --git a/playwright/e2e/settings/appearance-user-settings-tab/index.ts b/playwright/e2e/settings/appearance-user-settings-tab/index.ts new file mode 100644 index 0000000000..6eabfe11ef --- /dev/null +++ b/playwright/e2e/settings/appearance-user-settings-tab/index.ts @@ -0,0 +1,139 @@ +/* + * 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 { ElementAppPage } from "../../../pages/ElementAppPage"; +import { test as base, expect } from "../../../element-web-test"; +import { SettingLevel } from "../../../../src/settings/SettingLevel"; + +export { expect }; + +/** + * Set up for the appearance tab test + */ +export const test = base.extend<{ + util: Helpers; +}>({ + util: async ({ page, app }, use) => { + await use(new Helpers(page, app)); + }, +}); + +/** + * A collection of helper functions for the appearance tab test + * The goal is to make easier to get and interact with the button, input, or other elements of the appearance tab + */ +class Helpers { + private CUSTOM_THEME_URL = "http://custom.theme"; + private CUSTOM_THEME = { + name: "Custom theme", + isDark: false, + colors: {}, + }; + + constructor( + private page: Page, + private app: ElementAppPage, + ) {} + + /** + * Open the appearance tab + */ + openAppearanceTab() { + return this.app.settings.openUserSettings("Appearance"); + } + + // Theme Panel + + /** + * Disable in the settings the system theme + */ + disableSystemTheme() { + return this.app.settings.setValue("use_system_theme", null, SettingLevel.DEVICE, false); + } + + /** + * Return the theme section + */ + getThemePanel() { + return this.page.getByTestId("themePanel"); + } + + /** + * Return the system theme toggle + */ + getMatchSystemThemeCheckbox() { + return this.getThemePanel().getByRole("checkbox"); + } + + /** + * Return the theme radio button + * @param theme - the theme to select + * @private + */ + private getThemeRadio(theme: string) { + return this.getThemePanel().getByRole("radio", { name: theme }); + } + + /** + * Return the light theme radio button + */ + getLightTheme() { + return this.getThemeRadio("Light"); + } + + /** + * Return the dark theme radio button + */ + getDarkTheme() { + return this.getThemeRadio("Dark"); + } + + /** + * Return the custom theme radio button + */ + getCustomTheme() { + return this.getThemeRadio(this.CUSTOM_THEME.name); + } + + /** + * Return the high contrast theme radio button + */ + getHighContrastTheme() { + return this.getThemeRadio("High contrast"); + } + + /** + * Add a custom theme + * Mock the request to the custom and return a fake local custom theme + */ + async addCustomTheme() { + await this.page.route(this.CUSTOM_THEME_URL, (route) => + route.fulfill({ body: JSON.stringify(this.CUSTOM_THEME) }), + ); + await this.page.getByRole("textbox", { name: "Add custom theme" }).fill(this.CUSTOM_THEME_URL); + await this.page.getByRole("button", { name: "Add custom theme" }).click(); + await this.page.unroute(this.CUSTOM_THEME_URL); + } + + /** + * Remove the custom theme + */ + removeCustomTheme() { + return this.getThemePanel().getByRole("listitem", { name: this.CUSTOM_THEME.name }).getByRole("button").click(); + } +} diff --git a/playwright/snapshots/editing/editing.spec.ts/message-edit-history-dialog-linux.png b/playwright/snapshots/editing/editing.spec.ts/message-edit-history-dialog-linux.png index 9f46fce516bd8ac7c168db853bcbef5bfb676172..bfbfccbaeba24ac1d62fd7060108b1834d576002 100644 GIT binary patch literal 7313 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 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..98ece4d4d925d1e663a21cd96a7dc48c38dcd2fe GIT binary patch literal 49857 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 literal 0 HcmV?d00001 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-custom-theme-added-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-custom-theme-added-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..ffde3eb92e20e60d9a6388d7e1f2febe8dc83072 GIT binary patch literal 17296 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 MRQ6*D(@-)efN?=OH2HKvi+hw%io zPY^F15D{PR34V?ss%K$Yswi!!&sizbhj=y0mTH%S3?NVLy!)-^s^YR#Q1tU#m6nxc z+-A&fe8IQxTx+yhXM>LWAp{Eceh>WGmEM~<$>~5{_u~>0EL#(>f!1|PRR4PByGfw_ ztGPOxBc6?(v*XRJ-EDqVQ=qxhv(gpPZ%l5<o*uZ-gf(`GCio%tNi?II#bi-SWc5R77mVvy1K2o!n3vaL_M-#7*M_sOeTA_ z&DV%+7XQ->J8st{{?3<+t||xeSSl z@`T3n^YMvz*dRLxkF$c}Bqd|QyUirOCMIgXe;?kC#F3Q^J3sehRO#l*C=B4YM2yk= z_{Ym-;vTV;?Ii~>Gdr_zuuog(A-BfH)NTEihG+{~o0A}Q+!ha2bnc&%Zv0=I4Mkh+^+zdOg!fMLwZ10LdOdC>#Q_Gl9AR!qj*rUlG(kqYGW z#C>&tPSe)hd(Cx2X6c)=aC#8jE=b&w#eG%NL$N!yJ)KM0w;2NF+}`JW_%v=2eJ~jh zjZI3@Sq%qz+fti*8k8W)Gqie?O!0Rd=PN$+?&dQt7hegSd{3I%6( zsNuGwkrCClBc2l8#zXg?%~nK!UR z===IM>FFUtzU%Q?A1W%b>}wqTVM%2Kc32T(7JV|+-hN7pho|Qe*$9R=8CbTTnf?)| z0csu#E_d_sg7VPN&@r@Z40SVjPsHW0>cL}D!HT~_-{~*(?%mrIG{f8mt7M4>UG713 z;1Zo*@VR+cTm3Is_H?Dy)ShK!G2gg&ny37$-wzulrKk(@&9!0^P|)pXIDEd|FJ^D- zcd)+|Jax43_5VGnl+qIAOdJq7rSElDe-ft&F$u|`cMHkzu!-`E&GpGv?!T_9O2cv? zuM7;uhAC^M(**eOllGrG^MAW#|G#x(S<}JylAf9UCF@Jxw5${(Ro%P^ms$PPf}Ss8 z8s@wj=A_nFO{GMDUEY6q&p^0M^-1*wb$`UBWW=Tz z85$122dLL~JC`-%ZUB3#76%1iXvy2TNPGO^q6wGw-``m92(4f^RR>1?I-e*a%d@9N`955 z7Y?``Q`v>IzE{$*`>fW9P5mg6g_WouMM4ttA^`E=kYOA*Mg2$G#2vH?`NYCCr|KkS}2U+amaS0 zRWHuVb3R?M@ZAv?A9sAzwqU{ouwN9ZDEmtVDXE*D{d4)44>}C7avVnGx9kqWspRv3 zA?p_|&vxC{Y`&gU=(6GCJw7|5V0P>u7|0ZL{$wy09X(vJ+N0uoy2C#%VKE~o`87B< zGXJ!F+Gc+)XrxxwSu`wBy!GlqSO|9%#A)GRw6roSBwJLG>3=@Imwo;ep?y z-QD&3b(MviYik6O!x_yZ^TWa*kjbp$%35UsJXuRCNcfe{>7F@irbf214I7`*jC^$! zr6&k(@w$F$nQsXczCGwA#hU}~8A1ZhNA^-kInz^)79f$N zoXuW059usWivjIU3(v`@<1hycpWj6e5`WLi0$I&>dF{_;ic(OKxG{(_S`W`Z2>EW@ z>bteQEtByr(JL~lm2wGGQ*x`7P#4f!u|7!BdmG?1+HqkJxX|D}O*2Gat=rq#@-tT9(q)K%>#C~0eif3iUAZsWH@Y;k+!cD>p8XN<}RIS-80`&@pPj9LmuZE?tF?PrbcDk;Cfttof3)t)_(*K5dJP5`KnnfT8 zC9UB2PhRjJbcLH+iBZ!rxb&P0Oh<`|P(M#ipY*VVQtNZ#@>|j$c9cDGSZ88iXB#{3(0he8R z-8*`cq#uci2?^X_7`ueATEXviLdlcU)0F1aRC4-QIbCh-{ZKn%8vQ@JYrw>;@B4c` z!Fm(0bg1}^ho`ojZ75TWHHf~JMVrKGKskOGzLG-DIyUaScF1op$iN`h^T5BQ^k@`7R1x5pdFFZ4b(ire1XZU_(2Xv*)?| zNAqaJ4rF`tH-hp=JglwHhpzl~a4bH7gdXy`1Cc)BgpZHULgKEMAV=U{vRX}~af@6F zW@&jpO=k!O!=-x`%Xn+lW5(^gk?hw1bF8nguQY7i*%bV23q3sRUYll~95&X~J-_sH zE7j&`fThLIfCM&9Qpi5l-m_M;#s^c1WJU#2Tk%6slr|@1C>HNGF+!&$TQ$gN{h*Hek=n&Z$?0{vzt;11>vj!0%HI*>o z%Gw$O9v#wD%DBzH-u^5T3llqu=F}n7F}i8qHsRE3;sLOXo7=!-=`^Fi@OqFRM%{|_ zwsd|;tN13*(?9?VOEYqOtY6~bcl_s$6}o#@GSV3pUZL5+S1B(jSomdE2G`2==G(-Z znP-rLwavxF?|bp70K{c6cY1PyzlUtz3d^5sxH*`e^}IZ(+ze{}s%K$p+Gg81t7H&p zRO7IIb8e8Dn#y~x(B9Uz!lYf8pB*;VVKzBn$)283lF_8FsZ23diGUu*SPtsgx$yg* z9O^?3thdzz0&XN)Tg^F*Zp{vV*bLk_ za(&GmK-Aa4`;+DHZYTK8j_i%WlM*(v}uOWAbm0QRsZ7dinpv6b~fop;^c zo|;CvdBxeL*3P>iH|feu<9f=7tc;{#I0q982~LQoCKVq8Kfjiv65iv?>gsG`sp-2T zzjO)1LkI{14&tOG^@R{A

)HwgMhnnoLY=E7n#ZpV+(sHL8(jzo=flI&TDkuuR(g z^$ZQ^2@@u5qoTe=Jd%|Pws*EhEsvfSPO{pG4Ik${m;4(0$(WZNkDq^1r2HBAmp8Q6 z09H+ihg;RA@0C$BQGWc=6(`3qy2)W{XLGW*SezZ1J<(kXk(a+O5g=w?bLMh zym`EvT_N+WcNLF{#{vc~wW~S+dgtelE>G|gpLl?WvUJl=kz2E{o*W6q;(LK!wGJl? zzhBHITX~T2&TMqm8pG6V<}s8qqmcA{fY{Q)!m!EzVhC|OP|*h;eicHS05bOy*f0wh z;uVEtKfYtbwdaQm*B6>ZQ|?$-h6e8k%ff#cv5KvD1Ci@Sb7HGC;0my|I--8;LRjXZ z5cWk1ufT``e8_f-1&jO%0Oeu40uEa|Hod(3!+k^AUgbZ22zGbBI@M6i)lpZEOHa?) z(|-`!4XfkZDWv}y+K_1V)-?V$nSsxBuOr8d-G8=J1VHw{w(xa*uYsvcqO`QM>>db` zF`|9GGH#qD?#Vx??mt7F%4OL5Kk*s=f$uIejTE|N<3dn*ZEdOP=gC>}IJTB{qYFLN z@u3TSQ&c;39R+J~G{3tQ1IaWwlsFA&lcTpHcg|y22s|EWNm=|-T8PQy zG0{+Jtx#|z6rxlXR6(`OQ-1n+(jCco;R6jJ5D&N~E`IOcJ#$gN&0U>al5lA}BP(-t z7J~b-UCAlr_BJk}V4F@}Zu$@|+>F%W_OnCRkCibcENyl7v23zExUvFcxz>JFTAIb? zbnV6- z5B;Rvp(_o}LY9m3EWSQ|K(WiEqn=VUqRVtE(q zS^?@lWKfYo<>TF4Ril|0N1*bfV)B9B_GG@0x{Xb#8}g? z!TcJwKp9`@ExOIb@^4CtAV<%rvC=gNWQCe7{YDF_nP`ce-wFF^E9is_%23A!364#8 z>0=c=mA`)+HnxIN2_t#*Ai{%#@XvjYJY}#o}w^J8}-2b z{?%+kWQ0eX*M&2jI$(x{CcIBoVuU}7+nv+C z6N#bb-a4#~mo()!aWLM_+}PT)v%NWzuKz5$Z(Y@U_sxwOeRAuq?#t(_u3j2!Bxm!r z4KiBKB>Vb{zAnAQwrdfQLW7i2xn-+}Q9=6y@1DYqC%uSp?xzVlFE)AF@8v7tM=Q7A zHhCicSk{-;jedy!z`6+fkgVcjp~%iy9-qX0jBK6X_3@v&UZu zC2JxdbkBAen3)8m%-3l$xRu%UAuhJOwgYu}c}ZjMAkIj<7yQG}e1peH0_MF+{)b#|8=e3QrlwZd z`H+nhvUW1pnHZPLpR!vub4!kwvIDH__ZaC|(_=jTr1tH-S1o;MAHVIAD#CBT& zRZ?zVQqJ3E1c3$1B<-p)JU0xu$w6xwpI@y&kTAvf%4GZl$c5IMI@|GXvuX!yAk}d_ zp86g9aCTOp{e_?H_Em8sNpnNex(xC7?)M$mbIlGkeJ%PB>E#_8#4ZxjW1Yb3kz+#B(>?R+IN zUm>YY&i`mqN5lRwcpytg#!A3l?}z%3V$|3L;?I>FL!3^f$>442j?3rkjD|7shV(fI z>Js}~D;V<$*|!{wePP(>;u?Z10;3j*Bo7v&jvv1u3PQC3_uAT|oabBk{X;PE0I9oc zWohZWcsWNJjIC#&X9P6rA6r-S(+YYH_3;VX7d>1LaitP%B$Diiem9f?Sz5Sy3N+iB zs^9$-9CptdMi-)(aS5wFl#|5{t1MLF77$phIfa-6&2a=-V5uhNgw@bkwUp0nt**V^ z;V z8%}cqPIC~)?WF@JQ`6x+mg?#xT)J=!L$z)hW*?ECJ6=|&>B1t?Gy2>3wh!wkTX&^- z#gSf*h>-Zj))A4U9N<97%{NzP?4(1691v&}9vu))b)}?&eRS@uzj*P&MJQb{@U{Dy z<(NW%QEPVR7ZG7$eSpQCMbzlB*>2|K{_cB89DAI zD%G&pTEUsw%hwb`t~0b_#nFp5*lZ-FDyW#OKUe59TY!L%g2MbIGjSax`_(o`7z zfUa^aI}fAw*y;P^H+}H{1$>^)Hv@mmLGjrn#T?V^O!DL7bEWBH13f!^LP45C*I*58 zZP;ls9xDi>qoT6?K^u+L7+XEM_mfsq&gD?8pc{@fVI#r*Mt*vQY6tmUmd%#2Gc#Y9 z^^tOObK~RV4<@PwAhckgg@dzTyjqu7-dc7o6tFL3_hBGjYD-HXifCBNCRl>M`uj1UTiEos-v9Yhho)X=aiQ1hR4Osqs@u=c7 ze0{@$;)V9HOgTM2fBjyW;zfX_mhgC?ijJCEbxqB|Xy@RsUmuVrR~*LI=lrjkoz?Xl zY^njxr%)vey}eM_*r=A4l#0j1%es&2&YT&ZM=Tcce4DE9i8vF+^*duVhoxb=w2T}xC0w9FHc%Q!Tl;aqrab- zl(T1cZqB6LHJ)G$sv(;%^YEh`^JTP;#cuS5i0?qOQ?Wf)nHE1OccgSqa9DKTZRw0P zz*JBOmhtnhQi=GV4DUBLgHftgA7K>JJ|4TNhg(NL=qH^ffb7NEG0F;*51_11w&(DGv9;?3Z<6yK>!=-h~M}^Tn&9 zFR^DETp!~-ju9c--(NV^-BP2>%QW6uRFEtX0@5Tq{rOT&O^uAlUlRbo4`ivAK^$UxRnlc!?r#}& zrl)kw;LP;{$mx|9@#mLqF}3mHG>1;m>l(kOC=v69t8Gh@nGzaiT?xEd+s}&(hYnWG_BG_X z#YYDaYWxg#<*yjp6!D|KlF@K=_0+`e;@jmi@6`d4*^fY3(O<=9} z4QoVq>1+XDu$ex8cnHusIG@P?C5s-%3b+(O`KQvm7+R2=pXnB*ggn-H>>|A zkg!^v+^`}-o+{|xtaUITq+LB8AucX1d31j=NK2H@F8^+JQ>vYm&Yh7DGyGTYFA81< zXLa*(t9!8n3_l*8(_ebP6>3P4HqhR#A8j>DPID;o#~qO9^2+m1A_YFeA2yd83H~P21()S7tT+Ty9lVUU!-4`ErS8g!3lY6c83A`?eqJgjnVzMmGT32YI^U4IA-u z5`bIF6jNDogWmXhmL3TqId%P)%^a*=w*&lrSy`E~y@Q1iC4SQ2`q9v(_u1w8rWQXn z-OhH~u(t zDKNwh8;P@*?*~hDlo-JPRdn$>l;2=hE+FwKKv&uvJ98o1+y(jhqX-D8U0dENs86(9 zJO-YpxOxsux#kvcr=aCZNMru*aZ#DuP<;-vB!z~fhYu#{Z zw`*@rXdt6<`rbJBXNHtQWoAGHvaxtVy%Cm3mL>)!VFAM}51>$}q8~K3s|GyI z%hQ&|JvRwkSgf{0wMhWUVqQS>!!RDfJXT|Ei{T3c_*&7tO@yEI%= z#qV~t%jW`k#kquq^B-#H@B=~}9~DjTh1p*IH5m2qDf!mH;^MbnRxsby9^!c1dT4BV z`pR>#=V-NOI8|KbC|@1O@u+zZ6aYamaDmhPvsI=XfkfL2K-TiN$nT~v7iPWKI5?~hWZq@eRMn&bdNaL3{`I|{ruuzdRn=ef z;^2dh&!LgXRzFTa3ph<`-JKtEJek2A+8-MmYivC4=#bnvnD==Ml-T6iUtGkvdb-00 z2h9(t@$l=bY97Z34L=bYbLJbrUGBtw%-W1gRLBJeI&(I)gjj4pdT(h_SXEU+aUELe zF^IP2hpNRrr7D>*1)=3N^@rBf@QAJt$MNF8O_Pwa&dls_x%2NZ?g&w z%Faaa{_r_EiGNqT)fc=!3)Sew54b{)PE3^5ZQfu%ZT8&FDJ<-r2Ov=-!JorrDL@j! zp%W08QfzK$5TNUt>H7)=lK*c6>V}48zwBQCx)D>Wqp4Hi`T+lim;dz*V3f^7r<#oT zIAb2c=jr;lv_N@|vX16WEY$TBc9cI-QDxvayLBo9m zCM=~jyinq+>%wvHcsm(iAEN;J&&}1-z-u2^gcc~2QhaM=tY*wJ#cnqy{ixY)pa*+OseR z8JQIvbPNLMxIKbDN%Hls_5r)-jGP?$4R#d3I>9qV+a0#e07Tf-B(l9trU)VBB+M^; zPE5Se=rh${S)+Ml#~ajke3Z6wth&2G{lO&$-h|IpE%a!X_r(6yZx4XH*tIqK^#&1BYc&3E7>TbFaQuzIHP- zHok2-O-s+nNbZDYh=N7@(ASrEY2{^Xm|5_f)XxqAqBg^4v$OiOR>LEswqEo*KOCmW z$;k;M@u?(4oc3(C&*NXKr1AKed3m8{Jt;CWG9Kbns{V5V_aDFj_1kG88IYEu0JS}6 z4{>#U5t*#f3-cE1-YkiK3t)w6a~jYyKsl3%e!(#ZRME|pBq(T3FlVdwr9WMSu0qaG zNbKQMpxWaQjcn-4+)8NI9LP18mcqUzjO;$%;GC^;b#HHLJv%`3vt7DQx~Ztd0HI)S zw$*xjCA6f32HEHio&UZR9F31(s*O2W_=X7Qyww9L_m&YN zrF%y_Y54of*a2YncpX7A9}D5})S#;{f({N=)<_YeT|tjGQaV6w=!nOI^Gj(N6N1QY zmc^TgqQWz}smJ6^41l#>D=BH6YRR*R^1mD(dDEU92@Kz6=Lz14`uO?Yw;_kja5X7X zprCYQA|-{q@ThhsH1u5~4{$>N{B3J*OF}}joYoG!{@;Sl|8_(FJAn4T@f{BA?6A)r zIbS${dHyWEQdKP~&+ixD^RIj+&}2NWd>YJZAx$Pf9$T& zU_BiTteMTfE*>X2d3(89mljopJvqb=|7N@8`}g6B+~v_u>@)LfT?fgp_6ofu(O!K3 zRR8$Um5;uuJ~BSCR-Eo{L2vR@FZ?$An*<7Qkv>%hqoQbBHb3_H|iD$I6#d5-hAGUI3N?K+(a}Y6mfy(QWpA z4ny>}I(Ve&5caqJ@ZYNv{tr~Of2XeazusadMNfF#iX)xdx%kB71QF?`&BVqMhkPr6 znB=W>vl=qcuXSaqV0DZQkmhYSX$v@OYqgqqX;z4$uHI`wA8MY5ST9Xc|^`EOo2Uz2k7ew7su`G9{U@= z0vBt_fsrd{JC97-HUOhqEgY6mQFL>wnw%K%&bUS=Ma?~sTm~xcG=)ph4FY$w59MaU zTd}1$x{O(wn1JVC!~F&|zQJ#3XR0?pCKh~&s?YbBaVtGmjN&wEw*6TNxrw>yRmlvv zyrz-$GhkQ3la%W=MeJcHJvrG}ICL87-g!NfefQ2pCji7POWqvXd+IW0Cn7z{FH=^q-1T?{8qF6UZD z<2L|mEiuF^pO{C5B=TLu{w#QVmfae=**(YvQGYg)unQ??g8|XQayOPLzH_-nURllm zij_yLUS)og0*wDq*4t~hYaUO6gcuCUcC=3_q1Mlzi+JXDYIPo-T#+%4OSj2kj5wb= zXlrfJ)YMcT=SeIxMnaNE(_j@Rxa$6A6?W70T&r4T4f6+@lM|)WHv{V>&KCjBL(rL= z95ZWKzl~V!S&oI2(pe`rv^ADZUWr(*p{C*WhU4r&x4Xb~ophmIZSe1BA>TIy5(i0! ztrla@r)Y+d`(f__&Q+_dx;xe*KLfI;Y4j;E32|{riPNQJN|LNKf}6F1<9T9!%X@=r zCYx2b0v_H8eyB8;I4f1dLjW@AIL+HSIp)i4O3}pvg$cXbm@5C}y+%LWAd@C#99PF} zwsHj61>;sKoz-e%^AlpVp5qC+Rn^qIo?aetql%^${S6<|ulFAQLX-5hJMP}^te8` z)}1l>xHOPB`|zMO>`rI9s*c9EZGpIjDza1%rP(|cG72b(N2b+srlzqK70SLc1$*k* zReL@AjjngvV5zo1r^+wHJDj(E%J-_7mR2Fk=3D$@<>o6P(_gbCrWp%kTgY%O;RK` z6Vj`#13;aHWiLV&&7!rgYVa_EjH(Muthz?>jht3F7`WKcso|NSKm%1CKtkDlaS=!R7_^Wl{I~r+uOc#`4Xt z;<-1mPquwF7dwZk{)VGeM}J8<1Bf=RN@gv>0sCshaluf)@hZ15Z_V@19IEXyZd-Md zD6j9pi1~)iJ8N ziI{`d%!=V&AKqF|kJN3s0zRuS0NVqSY7(qD%~=`_+!Jv(O$rZ zzFG+VCu$*x+W1IHb)U72>|H~Uqqf8TN()N$1&CMlHc)cpTd^CpzSf+42@u{)z_-OY zIV(FW4nHe<)s_w0yapGCWu$^j`-n7oBgCG$6_7-B`&^)spKMrLy$3Iq%&t2KVx6-w z2T;{EHKo3x9fAj`;HYV6?T-wz3yGBg6{UdPfTQJ*h&!UvnE2h7$t5>YDCFY!gPgKc zrZoL~pEMG3*ODZiX}1OMf}RTY4D;b`?W@KKO|6AF=mVNaLYxqqM~_sbvv#Mtjc!@Y zs*}5|6c|DX0P2&}ORQ-nIb(i~@=^G;swxw~qo)tU!l*&{rKPzg1L4hCv;;WjmGd8b z3ks~+jO!&B1!G`l&q!hk-gm>af*-MJ?Q5t87itv~YiVlE&(%v1dKu~zrU=6|howqA z4ElKld9~EkpgxRko`WPI1UjUf8rHW?n^O^b`ujwA6FspU>TBWOdHEx|MZClc>NF1z zZo+_L)@yr4Ij}i>Ut3!nz4`mQ9nEtrJ`T!_Z)JP+apGc4CtHj8CB*;OPcz{4RCb8~ zKlJWC{}fVCNX%|DqTZ}}2Jzd;;bY|+T2#@`y&Xpk1~d}Ef^Sd_KOcRWlLN0@_~WN$ zTHV%G0nvdN8!xbUQH($~znFkMy_^{daN0BLZyj z#R07wgzU`j?WE6bKiqalEt^Yz4JE5Ius-8Y^THV%U>ow*c>S%U5qf!wR&VH#f8YBf zunR)}4?o)*t6peg7rpVvh_4!N|21mD_!Mk?yEf?L!~=(}+(0<%=E^M%gDI<_S5eiX z2tzDsv6r9$qt=(O^e#^MF8|>tq~Bi5HwQU${@q*#dMQl7S+6k9?!3wE1j^I!jPCIX zzj~GbHd4D>52_03K!m{!th9$q>J3-|9p7l}uk#`HACBZr>`?N)!Fx_ZoFN>9nCvFo z&Ux-2`0@4K-%qlB$gvr>*tKSVx`k-;@O!XF;Wkjb8UG}O_zOCJS1JJM#lQXEwEsGW z{Qq10FaO~8UpI*m^R_Us+`y{%|1C`X*UylDuG4=C>c?X4Jt%kqx{jTZ1$x1H|4v!D JLh{4s{|hRrdD#E} literal 0 HcmV?d00001 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-dark-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-dark-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..3b9c2431380444bdb02f663c81b26952eff835ac GIT binary patch literal 8711 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 literal 0 HcmV?d00001 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-light-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-light-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..ca9091711668626ffd9ea0236617029c129d359e GIT binary patch literal 9167 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 literal 0 HcmV?d00001 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-match-system-enabled-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-match-system-enabled-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..1aed777c8d6ea4cdea34a050132ae3053f5e3fd0 GIT binary patch literal 8367 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 JrfB)*KLD9Zy#N3J literal 0 HcmV?d00001 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/window-12px-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/window-12px-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..a1ca72b398adfc83cf8cec159d2d9d8c5feb6ba3 GIT binary patch literal 65730 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 literal 0 HcmV?d00001 diff --git a/res/css/_common.pcss b/res/css/_common.pcss index 32a2610c1f..54dedf9199 100644 --- a/res/css/_common.pcss +++ b/res/css/_common.pcss @@ -604,7 +604,7 @@ legend { .mx_Dialog button:not(.mx_Dialog_nonDialogButton):not([class|="maplibregl"]):not(.mx_AccessibleButton):not( .mx_UserProfileSettings button - ), + ):not(.mx_ThemeChoicePanel_CustomTheme button), .mx_Dialog input[type="submit"], .mx_Dialog_buttons button:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton), .mx_Dialog_buttons input[type="submit"] { @@ -624,14 +624,14 @@ legend { .mx_Dialog button:not(.mx_Dialog_nonDialogButton):not([class|="maplibregl"]):not(.mx_AccessibleButton):not( .mx_UserProfileSettings button - ):last-child { + ):not(.mx_ThemeChoicePanel_CustomTheme button):last-child { margin-right: 0px; } .mx_Dialog button:not(.mx_Dialog_nonDialogButton):not([class|="maplibregl"]):not(.mx_AccessibleButton):not( .mx_UserProfileSettings button - ):focus, + ):not(.mx_ThemeChoicePanel_CustomTheme button):focus, .mx_Dialog input[type="submit"]:focus, .mx_Dialog_buttons button:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton):focus, .mx_Dialog_buttons input[type="submit"]:focus { @@ -643,7 +643,7 @@ legend { .mx_Dialog_buttons button.mx_Dialog_primary:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton):not( .mx_UserProfileSettings button - ), + ):not(.mx_ThemeChoicePanel_CustomTheme button), .mx_Dialog_buttons input[type="submit"].mx_Dialog_primary { color: var(--cpd-color-text-on-solid-primary); background-color: var(--cpd-color-bg-action-primary-rest); @@ -654,7 +654,9 @@ legend { .mx_Dialog button.danger:not(.mx_Dialog_nonDialogButton):not([class|="maplibregl"]), .mx_Dialog input[type="submit"].danger, .mx_Dialog_buttons - button.danger:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton):not(.mx_UserProfileSettings button), + button.danger:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton):not(.mx_UserProfileSettings button):not( + .mx_ThemeChoicePanel_CustomTheme button + ), .mx_Dialog_buttons input[type="submit"].danger { background-color: var(--cpd-color-bg-critical-primary); border: solid 1px var(--cpd-color-bg-critical-primary); @@ -670,7 +672,7 @@ legend { .mx_Dialog button:not(.mx_Dialog_nonDialogButton):not([class|="maplibregl"]):not(.mx_AccessibleButton):not( .mx_UserProfileSettings button - ):disabled, + ):not(.mx_ThemeChoicePanel_CustomTheme button):disabled, .mx_Dialog input[type="submit"]:disabled, .mx_Dialog_buttons button:not(.mx_Dialog_nonDialogButton):not(.mx_AccessibleButton):disabled, .mx_Dialog_buttons input[type="submit"]:disabled { diff --git a/res/css/components/views/settings/shared/_SettingsSubsection.pcss b/res/css/components/views/settings/shared/_SettingsSubsection.pcss index 44d0a34426..f0e31285cb 100644 --- a/res/css/components/views/settings/shared/_SettingsSubsection.pcss +++ b/res/css/components/views/settings/shared/_SettingsSubsection.pcss @@ -17,6 +17,12 @@ limitations under the License. .mx_SettingsSubsection { width: 100%; box-sizing: border-box; + + &.mx_SettingsSubsection_newUi { + display: flex; + flex-direction: column; + gap: var(--cpd-space-8x); + } } .mx_SettingsSubsection_description { @@ -54,4 +60,8 @@ limitations under the License. &.mx_SettingsSubsection_noHeading { margin-top: 0; } + &.mx_SettingsSubsection_content_newUi { + gap: var(--cpd-space-6x); + margin-top: 0; + } } diff --git a/res/css/views/settings/_ThemeChoicePanel.pcss b/res/css/views/settings/_ThemeChoicePanel.pcss index 8616668224..f70cdf92e3 100644 --- a/res/css/views/settings/_ThemeChoicePanel.pcss +++ b/res/css/views/settings/_ThemeChoicePanel.pcss @@ -14,48 +14,72 @@ See the License for the specific language governing permissions and limitations under the License. */ -.mx_ThemeChoicePanel_themeSelectors { - color: $primary-content; +.mx_ThemeChoicePanel_ThemeSelectors { display: flex; - flex-direction: row; flex-wrap: wrap; + /* Override form default style */ + flex-direction: row !important; + gap: var(--cpd-space-4x) !important; - > .mx_StyledRadioButton { - align-items: center; - padding: $font-16px; - box-sizing: border-box; - border-radius: 10px; - width: 180px; + .mx_ThemeChoicePanel_themeSelector { + border: 1px solid var(--cpd-color-border-interactive-secondary); + border-radius: var(--cpd-space-1-5x); + padding: var(--cpd-space-3x) var(--cpd-space-5x) var(--cpd-space-3x) var(--cpd-space-3x); + gap: var(--cpd-space-2x); + background-color: var(--cpd-color-bg-canvas-default); - background: $accent-200; - opacity: 0.4; - - flex-shrink: 1; - flex-grow: 0; - - margin-right: 15px; - margin-top: 10px; - - font-weight: var(--cpd-font-weight-semibold); - - > span { - justify-content: center; - } - } - - > .mx_StyledRadioButton_enabled { - opacity: 1; - - /* These colors need to be hardcoded because they don't change with the theme */ - &.mx_ThemeSelector_light { - background-color: #f3f8fd; - color: #2e2f32; + &.mx_ThemeChoicePanel_themeSelector_enabled { + border-color: var(--cpd-color-border-interactive-primary); } - &.mx_ThemeSelector_dark { - /* 5% lightened version of 181b21 */ - background-color: #25282e; - color: #f3f8fd; + &.mx_ThemeChoicePanel_themeSelector_disabled { + border-color: var(--cpd-color-border-disabled); + } + + .mx_ThemeChoicePanel_themeSelector_Label { + color: var(--cpd-color-text-primary); + font: var(--cpd-font-body-md-semibold); + } + } +} + +.mx_ThemeChoicePanel_CustomTheme { + width: 100%; + display: flex; + flex-direction: column; + gap: var(--cpd-space-4x); + + .mx_ThemeChoicePanel_CustomTheme_EditInPlace input:focus { + /* + * When the input is focused, the border is growing + * We need to move it a bit to avoid the left border to be under the left panel + */ + margin-left: var(--cpd-space-0-5x); + } + + .mx_ThemeChoicePanel_CustomThemeList { + display: flex; + flex-direction: column; + gap: var(--cpd-space-4x); + /* + * Override the default padding/margin of the list + */ + padding: 0; + margin: 0; + + .mx_ThemeChoicePanel_CustomThemeList_theme { + display: flex; + justify-content: space-between; + align-items: center; + background-color: var(--cpd-color-gray-200); + padding: var(--cpd-space-2x) var(--cpd-space-2x) var(--cpd-space-2x) var(--cpd-space-4x); + + .mx_ThemeChoicePanel_CustomThemeList_name { + font: var(--cpd-font-body-sm-semibold); + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + } } } } diff --git a/src/components/views/dialogs/BaseDialog.tsx b/src/components/views/dialogs/BaseDialog.tsx index 4ed8543ee2..653c6327fa 100644 --- a/src/components/views/dialogs/BaseDialog.tsx +++ b/src/components/views/dialogs/BaseDialog.tsx @@ -128,7 +128,8 @@ export default class BaseDialog extends React.Component { onClick={this.onCancelClick} className="mx_Dialog_cancelButton" aria-label={_t("dialog_close_label")} - title={_t("dialog_close_label")} + title={_t("action|close")} + placement="bottom" /> ); } diff --git a/src/components/views/settings/ThemeChoicePanel.tsx b/src/components/views/settings/ThemeChoicePanel.tsx index c7166fe829..e3df157d61 100644 --- a/src/components/views/settings/ThemeChoicePanel.tsx +++ b/src/components/views/settings/ThemeChoicePanel.tsx @@ -1,285 +1,340 @@ /* -Copyright 2021 The Matrix.org Foundation C.I.C. + * 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. + */ -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 React, { ChangeEvent, JSX, useCallback, useMemo, useRef, useState } from "react"; +import { + InlineField, + ToggleControl, + Label, + Root, + RadioControl, + EditInPlace, + IconButton, +} from "@vector-im/compound-web"; +import { Icon as DeleteIcon } from "@vector-im/compound-design-tokens/icons/delete.svg"; +import classNames from "classnames"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "../../../languageHandler"; -import SettingsStore from "../../../settings/SettingsStore"; -import { findHighContrastTheme, findNonHighContrastTheme, getOrderedThemes, isHighContrastTheme } from "../../../theme"; +import SettingsSubsection from "./shared/SettingsSubsection"; import ThemeWatcher from "../../../settings/watchers/ThemeWatcher"; -import AccessibleButton from "../elements/AccessibleButton"; +import SettingsStore from "../../../settings/SettingsStore"; +import { SettingLevel } from "../../../settings/SettingLevel"; import dis from "../../../dispatcher/dispatcher"; import { RecheckThemePayload } from "../../../dispatcher/payloads/RecheckThemePayload"; import { Action } from "../../../dispatcher/actions"; -import StyledCheckbox from "../elements/StyledCheckbox"; -import Field from "../elements/Field"; -import StyledRadioGroup from "../elements/StyledRadioGroup"; -import { SettingLevel } from "../../../settings/SettingLevel"; -import PosthogTrackers from "../../../PosthogTrackers"; -import SettingsSubsection from "./shared/SettingsSubsection"; +import { useTheme } from "../../../hooks/useTheme"; +import { findHighContrastTheme, getOrderedThemes, CustomTheme as CustomThemeType, ITheme } from "../../../theme"; +import { useSettingValue } from "../../../hooks/useSettings"; -interface IProps {} +/** + * Panel to choose the theme + */ +export function ThemeChoicePanel(): JSX.Element { + const themeState = useTheme(); + const themeWatcher = useRef(new ThemeWatcher()); + const customThemeEnabled = useSettingValue("feature_custom_themes"); -interface IThemeState { + return ( + + {themeWatcher.current.isSystemThemeSupported() && ( + + )} + + {customThemeEnabled && } + + ); +} + +/** + * Component to toggle the system theme + */ +interface SystemThemeProps { + /* Whether the system theme is activated */ + systemThemeActivated: boolean; +} + +/** + * Component to toggle the system theme + */ +function SystemTheme({ systemThemeActivated }: SystemThemeProps): JSX.Element { + return ( + { + const checked = new FormData(evt.currentTarget).get("systemTheme") === "on"; + await SettingsStore.setValue("use_system_theme", null, SettingLevel.DEVICE, checked); + dis.dispatch({ action: Action.RecheckTheme }); + }} + > + } + > + + + + ); +} + +/** + * Component to select the theme + */ +interface ThemeSelectorProps { + /* The current theme */ theme: string; - useSystemTheme: boolean; + /* The theme can't be selected */ + disabled: boolean; } -export interface CustomThemeMessage { - isError: boolean; - text: string; -} +/** + * Component to select the theme + */ +function ThemeSelectors({ theme, disabled }: ThemeSelectorProps): JSX.Element { + const themes = useThemes(); -interface IState extends IThemeState { - customThemeUrl: string; - customThemeMessage: CustomThemeMessage; -} + return ( + { + // We don't have any file in the form, we can cast it as string safely + const newTheme = new FormData(evt.currentTarget).get("themeSelector") as string | null; -export default class ThemeChoicePanel extends React.Component { - private themeTimer?: number; + // Do nothing if the same theme is selected + if (!newTheme || theme === newTheme) return; - public constructor(props: IProps) { - super(props); - - this.state = { - ...ThemeChoicePanel.calculateThemeState(), - customThemeUrl: "", - customThemeMessage: { isError: false, text: "" }, - }; - } - - public static calculateThemeState(): IThemeState { - // We have to mirror the logic from ThemeWatcher.getEffectiveTheme so we - // show the right values for things. - - const themeChoice: string = SettingsStore.getValue("theme"); - const systemThemeExplicit: boolean = SettingsStore.getValueAt( - SettingLevel.DEVICE, - "use_system_theme", - null, - false, - true, - ); - const themeExplicit: string = SettingsStore.getValueAt(SettingLevel.DEVICE, "theme", null, false, true); - - // If the user has enabled system theme matching, use that. - if (systemThemeExplicit) { - return { - theme: themeChoice, - useSystemTheme: true, - }; - } - - // If the user has set a theme explicitly, use that (no system theme matching) - if (themeExplicit) { - return { - theme: themeChoice, - useSystemTheme: false, - }; - } - - // Otherwise assume the defaults for the settings - return { - theme: themeChoice, - useSystemTheme: SettingsStore.getValueAt(SettingLevel.DEVICE, "use_system_theme"), - }; - } - - private onThemeChange = (newTheme: string): void => { - if (this.state.theme === newTheme) return; - - PosthogTrackers.trackInteraction("WebSettingsAppearanceTabThemeSelector"); - - // doing getValue in the .catch will still return the value we failed to set, - // so remember what the value was before we tried to set it so we can revert - const oldTheme: string = SettingsStore.getValue("theme"); - SettingsStore.setValue("theme", null, SettingLevel.DEVICE, newTheme).catch(() => { - dis.dispatch({ action: Action.RecheckTheme }); - this.setState({ theme: oldTheme }); - }); - this.setState({ theme: newTheme }); - // The settings watcher doesn't fire until the echo comes back from the - // server, so to make the theme change immediately we need to manually - // do the dispatch now - // XXX: The local echoed value appears to be unreliable, in particular - // when settings custom themes(!) so adding forceTheme to override - // the value from settings. - dis.dispatch({ action: Action.RecheckTheme, forceTheme: newTheme }); - }; - - private onUseSystemThemeChanged = (checked: boolean): void => { - this.setState({ useSystemTheme: checked }); - SettingsStore.setValue("use_system_theme", null, SettingLevel.DEVICE, checked); - dis.dispatch({ action: Action.RecheckTheme }); - }; - - private onAddCustomTheme = async (): Promise => { - let currentThemes: string[] = SettingsStore.getValue("custom_themes"); - if (!currentThemes) currentThemes = []; - currentThemes = currentThemes.map((c) => c); // cheap clone - - if (this.themeTimer) { - clearTimeout(this.themeTimer); - } - - try { - const r = await fetch(this.state.customThemeUrl); - // XXX: need some schema for this - const themeInfo = await r.json(); - if (!themeInfo || typeof themeInfo["name"] !== "string" || typeof themeInfo["colors"] !== "object") { - this.setState({ - customThemeMessage: { text: _t("settings|appearance|custom_theme_invalid"), isError: true }, + // doing getValue in the .catch will still return the value we failed to set, + SettingsStore.setValue("theme", null, SettingLevel.DEVICE, newTheme).catch(() => { + dis.dispatch({ action: Action.RecheckTheme }); }); - return; - } - currentThemes.push(themeInfo); - } catch (e) { - logger.error(e); - this.setState({ - customThemeMessage: { text: _t("settings|appearance|custom_theme_error_downloading"), isError: true }, - }); - return; // Don't continue on error - } - await SettingsStore.setValue("custom_themes", null, SettingLevel.ACCOUNT, currentThemes); - this.setState({ - customThemeUrl: "", - customThemeMessage: { text: _t("settings|appearance|custom_theme_success"), isError: false }, - }); - - this.themeTimer = window.setTimeout(() => { - this.setState({ customThemeMessage: { text: "", isError: false } }); - }, 3000); - }; - - private onCustomThemeChange = (e: React.ChangeEvent): void => { - this.setState({ customThemeUrl: e.target.value }); - }; - - private renderHighContrastCheckbox(): React.ReactElement | undefined { - if ( - !this.state.useSystemTheme && - (findHighContrastTheme(this.state.theme) || isHighContrastTheme(this.state.theme)) - ) { - return ( -

- this.highContrastThemeChanged(e.target.checked)} + // The settings watcher doesn't fire until the echo comes back from the + // server, so to make the theme change immediately we need to manually + // do the dispatch now + // XXX: The local echoed value appears to be unreliable, in particular + // when settings custom themes(!) so adding forceTheme to override + // the value from settings. + dis.dispatch({ action: Action.RecheckTheme, forceTheme: newTheme }); + }} + > + {themes.map((_theme) => { + const isChecked = theme === _theme.id; + return ( + + } > - {_t("settings|appearance|use_high_contrast")} - -
- ); - } - } + + + ); + })} + + ); +} - private highContrastThemeChanged(checked: boolean): void { - let newTheme: string | undefined; - if (checked) { - newTheme = findHighContrastTheme(this.state.theme); - } else { - newTheme = findNonHighContrastTheme(this.state.theme); - } - if (newTheme) { - this.onThemeChange(newTheme); - } - } - - public render(): React.ReactElement { - const themeWatcher = new ThemeWatcher(); - let systemThemeSection: JSX.Element | undefined; - if (themeWatcher.isSystemThemeSupported()) { - systemThemeSection = ( -
- this.onUseSystemThemeChanged(e.target.checked)} - > - {SettingsStore.getDisplayName("use_system_theme")} - -
- ); - } - - let customThemeForm: JSX.Element | undefined; - if (SettingsStore.getValue("feature_custom_themes")) { - let messageElement: JSX.Element | undefined; - if (this.state.customThemeMessage.text) { - if (this.state.customThemeMessage.isError) { - messageElement =
{this.state.customThemeMessage.text}
; - } else { - messageElement =
{this.state.customThemeMessage.text}
; - } - } - customThemeForm = ( -
-
- - - {_t("settings|appearance|custom_theme_add_button")} - - {messageElement} - -
- ); - } - - const orderedThemes = getOrderedThemes(); - return ( - - {systemThemeSection} -
- ({ - value: t.id, - label: t.name, - disabled: this.state.useSystemTheme, - className: "mx_ThemeSelector_" + t.id, - }))} - onChange={this.onThemeChange} - value={this.apparentSelectedThemeId()} - outlined - /> -
- {this.renderHighContrastCheckbox()} - {customThemeForm} -
+/** + * Return all the available themes + */ +function useThemes(): Array { + const customThemes = useSettingValue("custom_themes"); + return useMemo(() => { + // Put the custom theme into a map + // To easily find the theme by name when going through the themes list + const checkedCustomThemes = customThemes || []; + const customThemeMap = checkedCustomThemes.reduce( + (map, theme) => map.set(theme.name, theme), + new Map(), ); - } - public apparentSelectedThemeId(): string | undefined { - if (this.state.useSystemTheme) { - return undefined; - } - const nonHighContrast = findNonHighContrastTheme(this.state.theme); - return nonHighContrast ? nonHighContrast : this.state.theme; + const themes = getOrderedThemes(); + // Separate the built-in themes from the custom themes + // To insert the high contrast theme between them + const builtInThemes = themes.filter((theme) => !customThemeMap.has(theme.name)); + const otherThemes = themes.filter((theme) => customThemeMap.has(theme.name)); + + const highContrastTheme = makeHighContrastTheme(); + if (highContrastTheme) builtInThemes.push(highContrastTheme); + + const allThemes = builtInThemes.concat(otherThemes); + + // Check if the themes are dark + return allThemes.map((theme) => { + const customTheme = customThemeMap.get(theme.name); + const isDark = (customTheme ? customTheme.is_dark : theme.id.includes("dark")) || false; + return { ...theme, isDark }; + }); + }, [customThemes]); +} + +/** + * Create the light high contrast theme + */ +function makeHighContrastTheme(): ITheme | undefined { + const lightHighContrastId = findHighContrastTheme("light"); + if (lightHighContrastId) { + return { + name: _t("settings|appearance|high_contrast"), + id: lightHighContrastId, + }; } } + +interface CustomThemeProps { + /** + * The current theme + */ + theme: string; +} + +/** + * Add and manager custom themes + */ +function CustomTheme({ theme }: CustomThemeProps): JSX.Element { + const [customTheme, setCustomTheme] = useState(""); + const [error, setError] = useState(); + const clear = useCallback(() => { + setError(undefined); + setCustomTheme(""); + }, [setError, setCustomTheme]); + + return ( +
+ ) => { + setError(undefined); + setCustomTheme(e.target.value); + }} + onSave={async () => { + // The field empty is empty + if (!customTheme) return; + + // Get the custom themes and do a cheap clone + // To avoid to mutate the original array in the settings + const currentThemes = + SettingsStore.getValue("custom_themes").map((t) => t) || []; + + try { + const r = await fetch(customTheme); + // XXX: need some schema for this + const themeInfo = await r.json(); + if ( + !themeInfo || + typeof themeInfo["name"] !== "string" || + typeof themeInfo["colors"] !== "object" + ) { + setError(_t("settings|appearance|custom_theme_invalid")); + return; + } + + // Check if the theme is already existing + const isAlreadyExisting = Boolean(currentThemes.find((t) => t.name === themeInfo.name)); + if (isAlreadyExisting) { + clear(); + return; + } + + currentThemes.push(themeInfo); + } catch (e) { + logger.error(e); + setError(_t("settings|appearance|custom_theme_error_downloading")); + return; + } + + // Reset the error + clear(); + await SettingsStore.setValue("custom_themes", null, SettingLevel.ACCOUNT, currentThemes); + }} + onCancel={clear} + /> + +
+ ); +} + +interface CustomThemeListProps { + /* + * The current theme + */ + theme: string; +} + +/** + * List of the custom themes + */ +function CustomThemeList({ theme: currentTheme }: CustomThemeListProps): JSX.Element { + const customThemes = useSettingValue("custom_themes") || []; + + return ( +
    + {customThemes.map((theme) => { + return ( +
  • + {theme.name} + { + // Get the custom themes and do a cheap clone + // To avoid to mutate the original array in the settings + const currentThemes = + SettingsStore.getValue("custom_themes").map((t) => t) || []; + + // Remove the theme from the list + const newThemes = currentThemes.filter((t) => t.name !== theme.name); + await SettingsStore.setValue("custom_themes", null, SettingLevel.ACCOUNT, newThemes); + + // If the delete custom theme is the current theme, reset the theme to the default theme + // By settings the theme at null at the device level, we are getting the default theme + if (currentTheme === `custom-${theme.name}`) { + await SettingsStore.setValue("theme", null, SettingLevel.DEVICE, null); + dis.dispatch({ + action: Action.RecheckTheme, + }); + } + }} + > + + +
  • + ); + })} +
+ ); +} diff --git a/src/components/views/settings/shared/SettingsSubsection.tsx b/src/components/views/settings/shared/SettingsSubsection.tsx index 035306f5f3..afcf92dea3 100644 --- a/src/components/views/settings/shared/SettingsSubsection.tsx +++ b/src/components/views/settings/shared/SettingsSubsection.tsx @@ -16,6 +16,7 @@ limitations under the License. import classNames from "classnames"; import React, { HTMLAttributes } from "react"; +import { Separator } from "@vector-im/compound-web"; import { SettingsSubsectionHeading } from "./SettingsSubsectionHeading"; @@ -25,6 +26,11 @@ export interface SettingsSubsectionProps extends HTMLAttributes children?: React.ReactNode; // when true content will be justify-items: stretch, which will make items within the section stretch to full width. stretchContent?: boolean; + /* + * When true, the legacy UI style will be applied to the subsection. + * @default true + */ + legacy?: boolean; } export const SettingsSubsectionText: React.FC> = ({ children, ...rest }) => ( @@ -38,10 +44,16 @@ export const SettingsSubsection: React.FC = ({ description, children, stretchContent, + legacy = true, ...rest }) => ( -
- {typeof heading === "string" ? : <>{heading}} +
+ {typeof heading === "string" ? : <>{heading}} {!!description && (
{description} @@ -52,11 +64,13 @@ export const SettingsSubsection: React.FC = ({ className={classNames("mx_SettingsSubsection_content", { mx_SettingsSubsection_contentStretch: !!stretchContent, mx_SettingsSubsection_noHeading: !heading && !description, + mx_SettingsSubsection_content_newUi: !legacy, })} > {children}
)} + {!legacy && }
); diff --git a/src/components/views/settings/shared/SettingsSubsectionHeading.tsx b/src/components/views/settings/shared/SettingsSubsectionHeading.tsx index 262b9f4d37..936b11dc37 100644 --- a/src/components/views/settings/shared/SettingsSubsectionHeading.tsx +++ b/src/components/views/settings/shared/SettingsSubsectionHeading.tsx @@ -20,14 +20,24 @@ import Heading from "../../typography/Heading"; export interface SettingsSubsectionHeadingProps extends HTMLAttributes { heading: string; + legacy?: boolean; children?: React.ReactNode; } -export const SettingsSubsectionHeading: React.FC = ({ heading, children, ...rest }) => ( -
- - {heading} - - {children} -
-); +export const SettingsSubsectionHeading: React.FC = ({ + heading, + legacy = true, + children, + ...rest +}) => { + const size = legacy ? "4" : "3"; + + return ( +
+ + {heading} + + {children} +
+ ); +}; diff --git a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx index 99f5a51c3b..cc76a7b2c1 100644 --- a/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/AppearanceUserSettingsTab.tsx @@ -28,7 +28,7 @@ import { UIFeature } from "../../../../../settings/UIFeature"; import { Layout } from "../../../../../settings/enums/Layout"; import LayoutSwitcher from "../../LayoutSwitcher"; import FontScalingPanel from "../../FontScalingPanel"; -import ThemeChoicePanel from "../../ThemeChoicePanel"; +import { ThemeChoicePanel } from "../../ThemeChoicePanel"; import ImageSizePanel from "../../ImageSizePanel"; import SettingsTab from "../SettingsTab"; import { SettingsSection } from "../../shared/SettingsSection"; diff --git a/src/components/views/spaces/QuickThemeSwitcher.tsx b/src/components/views/spaces/QuickThemeSwitcher.tsx index 66f3d2c040..1a6ee738ba 100644 --- a/src/components/views/spaces/QuickThemeSwitcher.tsx +++ b/src/components/views/spaces/QuickThemeSwitcher.tsx @@ -20,13 +20,13 @@ import { _t } from "../../../languageHandler"; import { Action } from "../../../dispatcher/actions"; import { findNonHighContrastTheme, getOrderedThemes } from "../../../theme"; import Dropdown from "../elements/Dropdown"; -import ThemeChoicePanel from "../settings/ThemeChoicePanel"; import SettingsStore from "../../../settings/SettingsStore"; import { SettingLevel } from "../../../settings/SettingLevel"; import dis from "../../../dispatcher/dispatcher"; import { RecheckThemePayload } from "../../../dispatcher/payloads/RecheckThemePayload"; import PosthogTrackers from "../../../PosthogTrackers"; import { NonEmptyArray } from "../../../@types/common"; +import { useTheme } from "../../../hooks/useTheme"; type Props = { requestClose: () => void; @@ -37,10 +37,10 @@ const MATCH_SYSTEM_THEME_ID = "MATCH_SYSTEM_THEME_ID"; const QuickThemeSwitcher: React.FC = ({ requestClose }) => { const orderedThemes = useMemo(getOrderedThemes, []); - const themeState = ThemeChoicePanel.calculateThemeState(); + const themeState = useTheme(); const nonHighContrast = findNonHighContrastTheme(themeState.theme); const theme = nonHighContrast ? nonHighContrast : themeState.theme; - const { useSystemTheme } = themeState; + const { systemThemeActivated } = themeState; const themeOptions = [ { @@ -50,7 +50,7 @@ const QuickThemeSwitcher: React.FC = ({ requestClose }) => { ...orderedThemes, ]; - const selectedTheme = useSystemTheme ? MATCH_SYSTEM_THEME_ID : theme; + const selectedTheme = systemThemeActivated ? MATCH_SYSTEM_THEME_ID : theme; const onOptionChange = async (newTheme: string): Promise => { PosthogTrackers.trackInteraction("WebQuickSettingsThemeDropdown"); diff --git a/src/hooks/useSettings.ts b/src/hooks/useSettings.ts index cabd4cbee9..23ce891b1e 100644 --- a/src/hooks/useSettings.ts +++ b/src/hooks/useSettings.ts @@ -17,6 +17,7 @@ limitations under the License. import { useEffect, useState } from "react"; import SettingsStore from "../settings/SettingsStore"; +import { SettingLevel } from "../settings/SettingLevel"; // Hook to fetch the value of a setting and dynamically update when it changes export const useSettingValue = (settingName: string, roomId: string | null = null, excludeDefault = false): T => { @@ -35,6 +36,39 @@ export const useSettingValue = (settingName: string, roomId: string | null = return value; }; +/** + * Hook to fetch the value of a setting at a specific level and dynamically update when it changes + * @see SettingsStore.getValueAt + * @param level + * @param settingName + * @param roomId + * @param explicit + * @param excludeDefault + */ +export const useSettingValueAt = ( + level: SettingLevel, + settingName: string, + roomId: string | null = null, + explicit = false, + excludeDefault = false, +): T => { + const [value, setValue] = useState( + SettingsStore.getValueAt(level, settingName, roomId, explicit, excludeDefault), + ); + + useEffect(() => { + const ref = SettingsStore.watchSetting(settingName, roomId, () => { + setValue(SettingsStore.getValueAt(level, settingName, roomId, explicit, excludeDefault)); + }); + // clean-up + return () => { + SettingsStore.unwatchSetting(ref); + }; + }, [level, settingName, roomId, explicit, excludeDefault]); + + return value; +}; + // Hook to fetch whether a feature is enabled and dynamically update when that changes export const useFeatureEnabled = (featureName: string, roomId: string | null = null): boolean => { const [enabled, setEnabled] = useState(SettingsStore.getValue(featureName, roomId)); diff --git a/src/hooks/useTheme.ts b/src/hooks/useTheme.ts new file mode 100644 index 0000000000..fcf77d4c67 --- /dev/null +++ b/src/hooks/useTheme.ts @@ -0,0 +1,53 @@ +/* + * 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 { SettingLevel } from "../settings/SettingLevel"; +import { useSettingValue, useSettingValueAt } from "./useSettings"; + +/** + * Hook to fetch the current theme and whether system theme matching is enabled. + */ +export function useTheme(): { theme: string; systemThemeActivated: boolean } { + // We have to mirror the logic from ThemeWatcher.getEffectiveTheme so we + // show the right values for things. + + const themeChoice = useSettingValue("theme"); + const systemThemeExplicit = useSettingValueAt(SettingLevel.DEVICE, "use_system_theme", null, false, true); + const themeExplicit = useSettingValueAt(SettingLevel.DEVICE, "theme", null, false, true); + const systemThemeActivated = useSettingValue("use_system_theme"); + + // If the user has enabled system theme matching, use that. + if (systemThemeExplicit) { + return { + theme: themeChoice, + systemThemeActivated: true, + }; + } + + // If the user has set a theme explicitly, use that (no system theme matching) + if (themeExplicit) { + return { + theme: themeChoice, + systemThemeActivated: false, + }; + } + + // Otherwise assume the defaults for the settings + return { + theme: themeChoice, + systemThemeActivated, + }; +} diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 06d0d1d449..de8e33927f 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -2420,21 +2420,21 @@ "custom_font_description": "Set the name of a font installed on your system & %(brand)s will attempt to use it.", "custom_font_name": "System font name", "custom_font_size": "Use custom size", - "custom_theme_add_button": "Add theme", - "custom_theme_error_downloading": "Error downloading theme information.", + "custom_theme_add": "Add custom theme", + "custom_theme_downloading": "Downloading custom theme…", + "custom_theme_error_downloading": "Error downloading theme", + "custom_theme_help": "Enter the URL of a custom theme you want to apply.", "custom_theme_invalid": "Invalid theme schema.", - "custom_theme_success": "Theme added!", - "custom_theme_url": "Custom theme URL", "dialog_title": "Settings: Appearance", "font_size": "Font size", "font_size_default": "%(fontSize)s (default)", + "high_contrast": "High contrast", "image_size_default": "Default", "image_size_large": "Large", "layout_bubbles": "Message bubbles", "layout_irc": "IRC (Experimental)", "match_system_theme": "Match system theme", - "timeline_image_size": "Image size in the timeline", - "use_high_contrast": "Use high contrast" + "timeline_image_size": "Image size in the timeline" }, "automatic_language_detection_syntax_highlight": "Enable automatic language detection for syntax highlighting", "autoplay_gifs": "Autoplay GIFs", diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index 2a52021618..276f00282b 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -355,7 +355,7 @@ export default class SettingsStore { const setting = SETTINGS[settingName]; const levelOrder = getLevelOrder(setting); - return SettingsStore.getValueAt(levelOrder[0], settingName, roomId, false, excludeDefault); + return SettingsStore.getValueAt(levelOrder[0], settingName, roomId, false, excludeDefault); } /** @@ -369,13 +369,13 @@ export default class SettingsStore { * @param {boolean} excludeDefault True to disable using the default value. * @return {*} The value, or null if not found. */ - public static getValueAt( + public static getValueAt( level: SettingLevel, settingName: string, roomId: string | null = null, explicit = false, excludeDefault = false, - ): any { + ): T { // Verify that the setting is actually a setting const setting = SETTINGS[settingName]; if (!setting) { diff --git a/src/theme.ts b/src/theme.ts index 8e2e893334..3245d72b76 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -103,7 +103,7 @@ export function enumerateThemes(): { [key: string]: string } { return Object.assign({}, customThemeNames, BUILTIN_THEMES); } -interface ITheme { +export interface ITheme { id: string; name: string; } diff --git a/test/components/views/settings/ThemeChoicePanel-test.tsx b/test/components/views/settings/ThemeChoicePanel-test.tsx index 03bbdbafdb..6c5482a553 100644 --- a/test/components/views/settings/ThemeChoicePanel-test.tsx +++ b/test/components/views/settings/ThemeChoicePanel-test.tsx @@ -15,15 +15,177 @@ limitations under the License. */ import React from "react"; -import { render } from "@testing-library/react"; +import { act, render, screen, waitFor } from "@testing-library/react"; +import { mocked, MockedObject } from "jest-mock"; +import userEvent from "@testing-library/user-event"; +import fetchMock from "fetch-mock-jest"; -import * as TestUtils from "../../../test-utils"; -import ThemeChoicePanel from "../../../../src/components/views/settings/ThemeChoicePanel"; +import { ThemeChoicePanel } from "../../../../src/components/views/settings/ThemeChoicePanel"; +import SettingsStore from "../../../../src/settings/SettingsStore"; +import ThemeWatcher from "../../../../src/settings/watchers/ThemeWatcher"; +import { SettingLevel } from "../../../../src/settings/SettingLevel"; + +jest.mock("../../../../src/settings/watchers/ThemeWatcher"); + +describe("", () => { + /** + * Enable or disable the system theme + * @param enable + */ + async function enableSystemTheme(enable: boolean) { + await SettingsStore.setValue("use_system_theme", null, SettingLevel.DEVICE, enable); + } + + /** + * Set the theme + * @param theme + */ + async function setTheme(theme: string) { + await SettingsStore.setValue("theme", null, SettingLevel.DEVICE, theme); + } + + beforeEach(async () => { + mocked(ThemeWatcher).mockImplementation(() => { + return { + isSystemThemeSupported: jest.fn().mockReturnValue(true), + } as unknown as MockedObject; + }); + + await enableSystemTheme(false); + await setTheme("light"); + }); -describe("ThemeChoicePanel", () => { it("renders the theme choice UI", () => { - TestUtils.stubClient(); const { asFragment } = render(); expect(asFragment()).toMatchSnapshot(); }); + + describe("theme selection", () => { + describe("system theme", () => { + it("should disable Match system theme", async () => { + render(); + expect(screen.getByRole("checkbox", { name: "Match system theme" })).not.toBeChecked(); + }); + + it("should enable Match system theme", async () => { + await enableSystemTheme(true); + + render(); + expect(screen.getByRole("checkbox", { name: "Match system theme" })).toBeChecked(); + }); + + it("should change the system theme when clicked", async () => { + jest.spyOn(SettingsStore, "setValue"); + + render(); + act(() => screen.getByRole("checkbox", { name: "Match system theme" }).click()); + + // The system theme should be enabled + expect(screen.getByRole("checkbox", { name: "Match system theme" })).toBeChecked(); + expect(SettingsStore.setValue).toHaveBeenCalledWith("use_system_theme", null, "device", true); + }); + }); + + describe("theme selection", () => { + it("should disable theme selection when system theme is enabled", async () => { + await enableSystemTheme(true); + render(); + + // We expect all the themes to be disabled + const themes = screen.getAllByRole("radio"); + themes.forEach((theme) => { + expect(theme).toBeDisabled(); + }); + }); + + it("should enable theme selection when system theme is disabled", async () => { + render(); + + // We expect all the themes to be disabled + const themes = screen.getAllByRole("radio"); + themes.forEach((theme) => { + expect(theme).not.toBeDisabled(); + }); + }); + + it("should have light theme selected", async () => { + render(); + + // We expect the light theme to be selected + const lightTheme = screen.getByRole("radio", { name: "Light" }); + expect(lightTheme).toBeChecked(); + + // And the dark theme shouldn't be selected + const darkTheme = screen.getByRole("radio", { name: "Dark" }); + expect(darkTheme).not.toBeChecked(); + }); + + it("should switch to dark theme", async () => { + jest.spyOn(SettingsStore, "setValue"); + + render(); + + const darkTheme = screen.getByRole("radio", { name: "Dark" }); + const lightTheme = screen.getByRole("radio", { name: "Light" }); + expect(darkTheme).not.toBeChecked(); + + // Switch to the dark theme + act(() => darkTheme.click()); + expect(SettingsStore.setValue).toHaveBeenCalledWith("theme", null, "device", "dark"); + + // Dark theme is now selected + await waitFor(() => expect(darkTheme).toBeChecked()); + // Light theme is not selected anymore + expect(lightTheme).not.toBeChecked(); + // The setting should be updated + expect(SettingsStore.setValue).toHaveBeenCalledWith("theme", null, "device", "dark"); + }); + }); + }); + + describe("custom theme", () => { + const aliceTheme = { name: "Alice theme", is_dark: true, colors: {} }; + const bobTheme = { name: "Bob theme", is_dark: false, colors: {} }; + + beforeEach(async () => { + await SettingsStore.setValue("feature_custom_themes", null, SettingLevel.DEVICE, true); + await SettingsStore.setValue("custom_themes", null, SettingLevel.DEVICE, [aliceTheme]); + }); + + it("should render the custom theme section", () => { + const { asFragment } = render(); + expect(asFragment()).toMatchSnapshot(); + }); + + it("should add a custom theme", async () => { + jest.spyOn(SettingsStore, "setValue"); + // Respond to the theme request + fetchMock.get("http://bob.theme", { + body: bobTheme, + }); + + render(); + + // Add the new custom theme + const customThemeInput = screen.getByRole("textbox", { name: "Add custom theme" }); + await userEvent.type(customThemeInput, "http://bob.theme"); + screen.getByRole("button", { name: "Add custom theme" }).click(); + + // The new custom theme is added to the user's themes + await waitFor(() => + expect(SettingsStore.setValue).toHaveBeenCalledWith("custom_themes", null, "account", [ + aliceTheme, + bobTheme, + ]), + ); + }); + + it("should display custom theme", () => { + const { asFragment } = render(); + + expect(screen.getByRole("radio", { name: aliceTheme.name })).toBeInTheDocument(); + expect(screen.getByRole("listitem", { name: aliceTheme.name })).toBeInTheDocument(); + expect(asFragment()).toMatchSnapshot(); + }); + }); }); diff --git a/test/components/views/settings/__snapshots__/ThemeChoicePanel-test.tsx.snap b/test/components/views/settings/__snapshots__/ThemeChoicePanel-test.tsx.snap index dad019c6c5..ecbd1e38a4 100644 --- a/test/components/views/settings/__snapshots__/ThemeChoicePanel-test.tsx.snap +++ b/test/components/views/settings/__snapshots__/ThemeChoicePanel-test.tsx.snap @@ -1,73 +1,774 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`ThemeChoicePanel renders the theme choice UI 1`] = ` +exports[` custom theme should display custom theme 1`] = `

Theme

-
-