From a4f82bb2dcc35635f7cb56d83a0dc2f52e156d6f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 9 Jul 2024 13:21:45 +0100 Subject: [PATCH 01/59] Specify node version --- package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/package.json b/package.json index 9741734d06..435e60ca3a 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,9 @@ "package.json", ".stylelintrc.js" ], + "engines": { + "node": ">=20.0.0" + }, "main": "./src/index.ts", "matrix_src_main": "./src/index.ts", "matrix_lib_main": "./lib/index.ts", From 28916792206a008fe0ae76226745131be47454d0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:54:50 +0100 Subject: [PATCH 02/59] Update dependency typescript to v5.5.3 (#12748) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 39 ++++++++++++++++++++++++++++++++------- 2 files changed, 33 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index 435e60ca3a..d8ad3e7390 100644 --- a/package.json +++ b/package.json @@ -229,7 +229,7 @@ "stylelint-config-standard": "^36.0.0", "stylelint-scss": "^6.0.0", "ts-node": "^10.9.1", - "typescript": "5.5.2", + "typescript": "5.5.3", "web-streams-polyfill": "^4.0.0" }, "peerDependencies": { diff --git a/yarn.lock b/yarn.lock index 4d94c1aedb..3ca6746e08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -8476,7 +8476,16 @@ string-length@^4.0.1: char-regex "^1.0.2" strip-ansi "^6.0.0" -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8563,7 +8572,14 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -9015,10 +9031,10 @@ typed-array-length@^1.0.6: is-typed-array "^1.1.13" possible-typed-array-names "^1.0.0" -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== +typescript@5.5.3: + version "5.5.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.5.3.tgz#e1b0a3c394190838a0b168e771b0ad56a0af0faa" + integrity sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ== ua-parser-js@^1.0.2: version "1.0.38" @@ -9362,7 +9378,7 @@ which@^2.0.1: dependencies: isexe "^2.0.0" -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -9380,6 +9396,15 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From 9be495af4c65548ba35a25db7ecdfaa26998fc34 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:55:07 +0100 Subject: [PATCH 03/59] Update all non-major dependencies (#12744) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- playwright/Dockerfile | 2 +- yarn.lock | 78 +++++++++++++++++++++++-------------------- 3 files changed, 44 insertions(+), 38 deletions(-) diff --git a/package.json b/package.json index d8ad3e7390..2c04337b4f 100644 --- a/package.json +++ b/package.json @@ -121,7 +121,7 @@ "opus-recorder": "^8.0.3", "pako": "^2.0.3", "png-chunks-extract": "^1.0.0", - "posthog-js": "1.141.3", + "posthog-js": "1.144.2", "qrcode": "1.5.3", "re-resizable": "^6.9.0", "react": "17.0.2", diff --git a/playwright/Dockerfile b/playwright/Dockerfile index f20a77b952..c5a9cdbb81 100644 --- a/playwright/Dockerfile +++ b/playwright/Dockerfile @@ -1,4 +1,4 @@ -FROM mcr.microsoft.com/playwright:v1.45.0-jammy +FROM mcr.microsoft.com/playwright:v1.45.1-jammy WORKDIR /work/matrix-react-sdk VOLUME ["/work/element-web/node_modules"] diff --git a/yarn.lock b/yarn.lock index 3ca6746e08..ca517c5ee5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2684,9 +2684,9 @@ integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ== "@types/lodash@^4.14.168": - version "4.17.5" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.5.tgz#e6c29b58e66995d57cd170ce3e2a61926d55ee04" - integrity sha512-MBIOHVZqVqgfro1euRDWX7OO0fBVUUMrN6Pwm8LQsz8cWhEpihlvR70ENj3f40j58TNxZaWv2ndSkInykNBBJw== + version "4.17.6" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.6.tgz#193ced6a40c8006cfc1ca3f4553444fb38f0e543" + integrity sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA== "@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.2": version "0.1.4" @@ -5201,9 +5201,9 @@ foreachasync@^3.0.0: integrity sha512-J+ler7Ta54FwwNcx6wQRDhTIbNeyDcARMkOcguEqnEdtm0jKvN3Li3PDAb2Du3ubJYEWfYL83XMROXdsXAXycw== foreground-child@^3.1.0: - version "3.1.1" - resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.1.1.tgz#1d173e776d75d2772fed08efe4a0de1ea1b12d0d" - integrity sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg== + version "3.2.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.2.1.tgz#767004ccf3a5b30df39bed90718bab43fe0a59f7" + integrity sha512-PXUUyLqrR2XCWICfv6ukppP96sdFwWbNEnfEMt7jNsISjMsvaLNinAHNDYyvkyU+SZG2BTSbT5NjG+vZslfGTA== dependencies: cross-spawn "^7.0.0" signal-exit "^4.0.1" @@ -5356,15 +5356,16 @@ glob-to-regexp@^0.4.0, glob-to-regexp@^0.4.1: integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== glob@^10.3.7: - version "10.3.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.3.15.tgz#e72bc61bc3038c90605f5dd48543dc67aaf3b50d" - integrity sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw== + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== dependencies: foreground-child "^3.1.0" - jackspeak "^2.3.6" - minimatch "^9.0.1" - minipass "^7.0.4" - path-scurry "^1.11.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: version "7.2.3" @@ -6044,10 +6045,10 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jackspeak@^2.3.6: - version "2.3.6" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-2.3.6.tgz#647ecc472238aee4b06ac0e461acc21a8c505ca8" - integrity sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ== +jackspeak@^3.1.2: + version "3.4.2" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.2.tgz#c3d1e00071d52dba8b0dac17cd2a12d0187d2989" + integrity sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: @@ -6587,9 +6588,9 @@ jwt-decode@4.0.0, jwt-decode@^4.0.0: integrity sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA== katex@^0.16.0: - version "0.16.10" - resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.10.tgz#6f81b71ac37ff4ec7556861160f53bc5f058b185" - integrity sha512-ZiqaC04tp2O5utMsl2TEZTXxa6WSC4yo0fv5ML++D3QZv/vx2Mct0mTlRx3O+uUkjfuAgOkzsCmq5MiUEsDDdA== + version "0.16.11" + resolved "https://registry.yarnpkg.com/katex/-/katex-0.16.11.tgz#4bc84d5584f996abece5f01c6ad11304276a33f5" + integrity sha512-RQrI8rlHY92OLf3rho/Ts8i/XvjgguEjOkO1BEXcU3N8BqPpSzBNwV/G0Ukr+P/l3ivvJUE/Fa/CwbS6HesGNQ== dependencies: commander "^8.3.0" @@ -6766,9 +6767,9 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: js-tokens "^3.0.0 || ^4.0.0" lru-cache@^10.2.0: - version "10.2.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.2.tgz#48206bc114c1252940c41b25b41af5b545aca878" - integrity sha512-9hp3Vp2/hFQUiIwKo8XCeFVnrg8Pk3TYNPIR7tJADKi5YfcF7vEaK7avFHTlSy3kOKYaJQaalfEo6YuXdceBOQ== + version "10.4.2" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.2.tgz#78c38f194b747174cff90e60afabcae40c3619f2" + integrity sha512-voV4dDrdVZVNz84n39LFKDaRzfwhdzJ7akpyXfTMxCgRUp07U3lcJUXRlhTKP17rgt09sUzLi5iCitpEAr+6ug== lru-cache@^5.1.1: version "5.1.1" @@ -7012,7 +7013,7 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^9.0.1, minimatch@^9.0.4: +minimatch@^9.0.4: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== @@ -7024,10 +7025,10 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8, minimist@~1. resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4: - version "7.1.1" - resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.1.tgz#f7f85aff59aa22f110b20e27692465cf3bf89481" - integrity sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== mkdirp@1.0.4, mkdirp@^1.0.4: version "1.0.4" @@ -7328,6 +7329,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== +package-json-from-dist@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.0.tgz#e501cd3094b278495eb4258d4c9f6d5ac3019f00" + integrity sha512-dATvCeZN/8wQsGywez1mzHtTlP22H8OEfPrVMLNr4/eGa+ijtLn/6M5f0dY8UKNrC2O9UCU6SSoG3qRKnt7STw== + pako@^2.0.3: version "2.1.0" resolved "https://registry.yarnpkg.com/pako/-/pako-2.1.0.tgz#266cc37f98c7d883545d11335c00fbd4062c9a86" @@ -7402,7 +7408,7 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.11.0: +path-scurry@^1.11.1: version "1.11.1" resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== @@ -7559,10 +7565,10 @@ postcss@^8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" -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== +posthog-js@1.144.2: + version "1.144.2" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.144.2.tgz#be9dbc126bff2ef1bba17f546f2a591cd08f1ec0" + integrity sha512-Kgq8/bJvrTbDDsfSqAURIiYdkJ5tPegR2JC6pqIeoFjnTx/Rrq0j4n3vDW7K1nCapBch7G5gTZdaK7O6t+rI9A== dependencies: fflate "^0.4.8" preact "^10.19.3" @@ -8119,9 +8125,9 @@ rimraf@^3.0.2: glob "^7.1.3" rimraf@^5.0.0: - version "5.0.7" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.7.tgz#27bddf202e7d89cb2e0381656380d1734a854a74" - integrity sha512-nV6YcJo5wbLW77m+8KjH8aB/7/rxQy9SZ0HY5shnwULfS+9nmTtVXAJET5NdZmCzA4fPI/Hm1wo/Po/4mopOdg== + version "5.0.9" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.9.tgz#c3baa1b886eadc2ec7981a06a593c3d01134ffe9" + integrity sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA== dependencies: glob "^10.3.7" From f4aec6a0fe15e5f937a7209c229a4a3519e49e89 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:56:30 +0000 Subject: [PATCH 04/59] Update dependency @vector-im/compound-design-tokens to v1.4.0 (#12750) 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 ca517c5ee5..30c862eed0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3034,9 +3034,9 @@ integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== "@vector-im/compound-design-tokens@^1.2.0": - version "1.3.0" - resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-1.3.0.tgz#1d04f006a9e56b920432095d08d7c84c0933ebc7" - integrity sha512-RXcyEAdxNzekMhVuvxtLPt9zb6yT2N+5cnb2Hul9zwRiF7+XEHpD36+IF6V0QOXk2pkN0wOr3jCvc9eOWOq9SQ== + version "1.4.0" + resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-1.4.0.tgz#a76cf2df3c64b273117f726851fc2b9fd9833b80" + integrity sha512-C3i1656SAQl2/F9qL8wDP8n690eJdFTYIJFMO4Qh3YALjVclRgjmTZvkR4gp6ylS5+AB/dU1dTRIW6KD+I8b0A== dependencies: svg2vectordrawable "^2.9.1" From d053cd26f86f44238e02035688e38be41a6ee6ca Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 14:58:15 +0000 Subject: [PATCH 05/59] Update dependency @playwright/test to v1.45.1 (#12746) 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 30c862eed0..791a3517d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1957,11 +1957,11 @@ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@playwright/test@^1.40.1": - version "1.45.0" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.45.0.tgz#790a66165a46466c0d7099dd260881802f5aba7e" - integrity sha512-TVYsfMlGAaxeUllNkywbwek67Ncf8FRGn8ZlRdO291OL3NjG9oMbfVhyP82HQF0CZLMrYsvesqoUekxdWuF9Qw== + version "1.45.1" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.45.1.tgz#819b90fa43d17000fce5ebd127043fd661938b7a" + integrity sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA== dependencies: - playwright "1.45.0" + playwright "1.45.1" "@radix-ui/primitive@1.0.1": version "1.0.1" @@ -7473,17 +7473,17 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -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-core@1.45.1: + version "1.45.1" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.45.1.tgz#549a2701556b58245cc75263f9fc2795c1158dc1" + integrity sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg== -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== +playwright@1.45.1: + version "1.45.1" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.45.1.tgz#aaa6b0d6db14796b599d80c6679e63444e942534" + integrity sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg== dependencies: - playwright-core "1.45.0" + playwright-core "1.45.1" optionalDependencies: fsevents "2.3.2" From 7ceb151761ed864ddccdebad4fe4c8965362a84c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:22:40 +0000 Subject: [PATCH 06/59] Update dependency @sentry/browser to v8.15.0 (#12749) * Update dependency @sentry/browser to v8.15.0 * Fix type import Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- src/sentry.ts | 2 +- yarn.lock | 110 +++++++++++++++++++++++++------------------------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/src/sentry.ts b/src/sentry.ts index 4540708f8e..2660649891 100644 --- a/src/sentry.ts +++ b/src/sentry.ts @@ -16,7 +16,7 @@ limitations under the License. import * as Sentry from "@sentry/browser"; import { MatrixClient } from "matrix-js-sdk/src/matrix"; -import { type Integration } from "@sentry/types/types/integration"; +import { type Integration } from "@sentry/types/build/types/integration"; import SdkConfig from "./SdkConfig"; import { MatrixClientPeg } from "./MatrixClientPeg"; diff --git a/yarn.lock b/yarn.lock index 791a3517d7..850503d79c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2295,76 +2295,76 @@ 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" - resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.12.0.tgz#ddea4b1ed1ee798beccf71b5b531928f7bdfd082" - integrity sha512-h7HRqED15Qa+DRt8iZGna24Z331nglgjPzdFn4+u+jvnZrehUjH0vjsfuj7qhwSUNZu8Rxi1ZlUYFURjLDTKCA== +"@sentry-internal/browser-utils@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.15.0.tgz#d78646d02d76445ba71c7ed423d749b192ef010c" + integrity sha512-DquySUQRnmMyRbfHH9t/JDwPMsVaCOCzV/6XmMb7s4FDYTWSCSpumJEYfiyJCuI9NeebPHZWF7LZCHH4glSAJQ== dependencies: - "@sentry/core" "8.12.0" - "@sentry/types" "8.12.0" - "@sentry/utils" "8.12.0" + "@sentry/core" "8.15.0" + "@sentry/types" "8.15.0" + "@sentry/utils" "8.15.0" -"@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== +"@sentry-internal/feedback@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.15.0.tgz#c28a176208dd53025c7aff4eb4df0fa19f48e0c4" + integrity sha512-W6XiLpw7fL1A0KaHxIH45nbC2M8uagrMoBnMZ1NcqE4AoSe7VtoDqPsLvQ7MgMXwsBYiPu2AItRnKoGFS/dUBA== dependencies: - "@sentry/core" "8.12.0" - "@sentry/types" "8.12.0" - "@sentry/utils" "8.12.0" + "@sentry/core" "8.15.0" + "@sentry/types" "8.15.0" + "@sentry/utils" "8.15.0" -"@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== +"@sentry-internal/replay-canvas@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.15.0.tgz#0201eaae000678bdb0b054cd558f5c1bb0882454" + integrity sha512-gfezIuvf94wY748l5wSy4pRm+45GjiBm0Q/KLnXROLZKmbI7MTJrdQXA2Oxut848iISTQo4/LimecFnBDiaGtw== dependencies: - "@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.15.0" + "@sentry/core" "8.15.0" + "@sentry/types" "8.15.0" + "@sentry/utils" "8.15.0" -"@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== +"@sentry-internal/replay@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.15.0.tgz#5382790b9c5b0d223aebdf50ad84135463eecd32" + integrity sha512-d4cA8pjr0CGHkTe8ulqMROYCX3bMHBAi/7DJBr11i4MdNCUl+/pndA9C5TiFv0sFzk/hDZQZS3J+MfGp56ZQHw== dependencies: - "@sentry-internal/browser-utils" "8.12.0" - "@sentry/core" "8.12.0" - "@sentry/types" "8.12.0" - "@sentry/utils" "8.12.0" + "@sentry-internal/browser-utils" "8.15.0" + "@sentry/core" "8.15.0" + "@sentry/types" "8.15.0" + "@sentry/utils" "8.15.0" "@sentry/browser@^8.0.0": - version "8.12.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.12.0.tgz#12dba1c7c54d74bba6830e6625f851d55c56bce8" - integrity sha512-H82dmr7KQWoS2DQc5dJko5wNepltcEro1EM4mBeL2YmVbNRtoZzD3HQTpbxJJuFsTvEMZevvez5HFlpUgxmIwQ== + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.15.0.tgz#81223a4ee448c7ffed662301314132c3f442ec08" + integrity sha512-Tx4eFgAqa8tedg30+Cgr7qFocWHise8p3jb/RSNs+TCEBXLVtQidHHVZMO71FWUAC86D7woo5hMKTt+UmB8pgg== dependencies: - "@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-internal/browser-utils" "8.15.0" + "@sentry-internal/feedback" "8.15.0" + "@sentry-internal/replay" "8.15.0" + "@sentry-internal/replay-canvas" "8.15.0" + "@sentry/core" "8.15.0" + "@sentry/types" "8.15.0" + "@sentry/utils" "8.15.0" -"@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== +"@sentry/core@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.15.0.tgz#a8df0a6bfeedad090c7b5ac3f76656f8ed28ac70" + integrity sha512-RjuEq/34VjNmxlfzq+485jG63/Vst90svQapLwVgBZWgM8jxrLyCRXHU0wfBc7/1IhV/T9GYAplrJQAkG4J9Ow== dependencies: - "@sentry/types" "8.12.0" - "@sentry/utils" "8.12.0" + "@sentry/types" "8.15.0" + "@sentry/utils" "8.15.0" -"@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/types@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.15.0.tgz#bcf1eca41bccbc6eb434cc14ab7364eed41a8c17" + integrity sha512-AZc9nSHKuNH8P/7ihmq5fbZBiQ7Gr35kJq9Tad9eVuOgL8D+2b6Vqu/61ljVVlMFI0tBGFsSkWJ/00PfBcVKWg== -"@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== +"@sentry/utils@8.15.0": + version "8.15.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.15.0.tgz#31890e97e77bd27484c0831402e1666d3e289b03" + integrity sha512-1ISmyYFuRHJbGun0gUYscyz1aP6RfILUldNAUwQwF0Ycu8YOi4n8uwJRN0aov6cCi41tnZWOMBagSeLxbJiJgQ== dependencies: - "@sentry/types" "8.12.0" + "@sentry/types" "8.15.0" "@sinclair/typebox@^0.27.8": version "0.27.8" From feb5a491ef2ae4968b7029b630c45fd047137a9f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:53:02 +0000 Subject: [PATCH 07/59] Update dependency rimraf to v6 (#12754) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 61 +++++++++++++++++++++++++++++----------------------- 2 files changed, 35 insertions(+), 28 deletions(-) diff --git a/package.json b/package.json index 2c04337b4f..c0ee0665cd 100644 --- a/package.json +++ b/package.json @@ -224,7 +224,7 @@ "postcss-scss": "^4.0.4", "prettier": "3.3.2", "raw-loader": "^4.0.2", - "rimraf": "^5.0.0", + "rimraf": "^6.0.0", "stylelint": "^16.1.0", "stylelint-config-standard": "^36.0.0", "stylelint-scss": "^6.0.0", diff --git a/yarn.lock b/yarn.lock index 850503d79c..f8d7a6514a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5355,17 +5355,17 @@ glob-to-regexp@^0.4.0, glob-to-regexp@^0.4.1: resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e" integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw== -glob@^10.3.7: - version "10.4.5" - resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" - integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== +glob@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-11.0.0.tgz#6031df0d7b65eaa1ccb9b29b5ced16cea658e77e" + integrity sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g== dependencies: foreground-child "^3.1.0" - jackspeak "^3.1.2" - minimatch "^9.0.4" + jackspeak "^4.0.1" + minimatch "^10.0.0" minipass "^7.1.2" package-json-from-dist "^1.0.0" - path-scurry "^1.11.1" + path-scurry "^2.0.0" glob@^7.1.3, glob@^7.1.4, glob@^7.2.0: version "7.2.3" @@ -6045,10 +6045,10 @@ iterator.prototype@^1.1.2: reflect.getprototypeof "^1.0.4" set-function-name "^2.0.1" -jackspeak@^3.1.2: - version "3.4.2" - resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.2.tgz#c3d1e00071d52dba8b0dac17cd2a12d0187d2989" - integrity sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q== +jackspeak@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-4.0.1.tgz#9fca4ce961af6083e259c376e9e3541431f5287b" + integrity sha512-cub8rahkh0Q/bw1+GxP7aeSe29hHHn2V4m29nnDlvCdlgU+3UGxkZp7Z53jLUdpX3jdTO0nJZUDl3xvbWc2Xog== dependencies: "@isaacs/cliui" "^8.0.2" optionalDependencies: @@ -6766,10 +6766,10 @@ loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" -lru-cache@^10.2.0: - version "10.4.2" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.2.tgz#78c38f194b747174cff90e60afabcae40c3619f2" - integrity sha512-voV4dDrdVZVNz84n39LFKDaRzfwhdzJ7akpyXfTMxCgRUp07U3lcJUXRlhTKP17rgt09sUzLi5iCitpEAr+6ug== +lru-cache@^11.0.0: + version "11.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-11.0.0.tgz#15d93a196f189034d7166caf9fe55e7384c98a21" + integrity sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA== lru-cache@^5.1.1: version "5.1.1" @@ -7006,6 +7006,13 @@ min-indent@^1.0.0: resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869" integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg== +minimatch@^10.0.0: + version "10.0.1" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-10.0.1.tgz#ce0521856b453c86e25f2c4c0d03e6ff7ddc440b" + integrity sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ== + dependencies: + brace-expansion "^2.0.1" + minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -7025,7 +7032,7 @@ minimist@^1.2.0, minimist@^1.2.5, minimist@^1.2.6, minimist@^1.2.8, minimist@~1. resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== -"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: +minipass@^7.1.2: version "7.1.2" resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== @@ -7408,13 +7415,13 @@ path-parse@^1.0.7: resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== -path-scurry@^1.11.1: - version "1.11.1" - resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" - integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== +path-scurry@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-2.0.0.tgz#9f052289f23ad8bf9397a2a0425e7b8615c58580" + integrity sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg== dependencies: - lru-cache "^10.2.0" - minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + lru-cache "^11.0.0" + minipass "^7.1.2" path-to-regexp@0.1.7: version "0.1.7" @@ -8124,12 +8131,12 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" -rimraf@^5.0.0: - version "5.0.9" - resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-5.0.9.tgz#c3baa1b886eadc2ec7981a06a593c3d01134ffe9" - integrity sha512-3i7b8OcswU6CpU8Ej89quJD4O98id7TtVM5U4Mybh84zQXdrFmDLouWBEEaD/QfO3gDDfH+AGFCGsR7kngzQnA== +rimraf@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-6.0.0.tgz#503bb3d9283272384c121792d40e7ee3ab763cde" + integrity sha512-u+yqhM92LW+89cxUQK0SRyvXYQmyuKHx0jkx4W7KfwLGLqJnQM5031Uv1trE4gB9XEXBM/s6MxKlfW95IidqaA== dependencies: - glob "^10.3.7" + glob "^11.0.0" run-parallel@^1.1.9: version "1.2.0" From 07f78326e6d07e2e3c1c73376e6c6aa6f29e0344 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 15:54:02 +0000 Subject: [PATCH 08/59] Update typescript-eslint monorepo to v7.15.0 (#12752) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- yarn.lock | 108 +++++++++++++++++++++++++++--------------------------- 1 file changed, 54 insertions(+), 54 deletions(-) diff --git a/yarn.lock b/yarn.lock index f8d7a6514a..d5d672b2f8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1439,9 +1439,9 @@ eslint-visitor-keys "^3.3.0" "@eslint-community/regexpp@^4.10.0": - version "4.10.1" - resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.1.tgz#361461e5cb3845d874e61731c11cfedd664d83a0" - integrity sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA== + version "4.11.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.11.0.tgz#b0ffd0312b4a3fd2d6f77237e7248a5ad3a680ae" + integrity sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A== "@eslint-community/regexpp@^4.6.1": version "4.8.0" @@ -2903,29 +2903,29 @@ "@types/yargs-parser" "*" "@typescript-eslint/eslint-plugin@^7.0.0": - 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== + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz#b3563927341eca15124a18c6f94215f779f5c02a" + integrity sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw== dependencies: "@eslint-community/regexpp" "^4.10.0" - "@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" + "@typescript-eslint/scope-manager" "7.16.0" + "@typescript-eslint/type-utils" "7.16.0" + "@typescript-eslint/utils" "7.16.0" + "@typescript-eslint/visitor-keys" "7.16.0" 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.14.1" - resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.14.1.tgz#13d97f357aed3c5719f259a6cc3d1a1f065d3692" - integrity sha512-8lKUOebNLcR0D7RvlcloOacTOWzOqemWEWkKSVpMZVF/XVcwjPR+3MD08QzbW9TCGJ+DwIc6zUSGZ9vd8cO1IA== + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-7.16.0.tgz#53fae8112f8c912024aea7b499cf7374487af6d8" + integrity sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw== dependencies: - "@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" + "@typescript-eslint/scope-manager" "7.16.0" + "@typescript-eslint/types" "7.16.0" + "@typescript-eslint/typescript-estree" "7.16.0" + "@typescript-eslint/visitor-keys" "7.16.0" debug "^4.3.4" "@typescript-eslint/scope-manager@7.13.0": @@ -2936,21 +2936,21 @@ "@typescript-eslint/types" "7.13.0" "@typescript-eslint/visitor-keys" "7.13.0" -"@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== +"@typescript-eslint/scope-manager@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz#eb0757af5720c9c53c8010d7a0355ae27e17b7e5" + integrity sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw== dependencies: - "@typescript-eslint/types" "7.14.1" - "@typescript-eslint/visitor-keys" "7.14.1" + "@typescript-eslint/types" "7.16.0" + "@typescript-eslint/visitor-keys" "7.16.0" -"@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== +"@typescript-eslint/type-utils@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz#ec52b1932b8fb44a15a3e20208e0bd49d0b6bd00" + integrity sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg== dependencies: - "@typescript-eslint/typescript-estree" "7.14.1" - "@typescript-eslint/utils" "7.14.1" + "@typescript-eslint/typescript-estree" "7.16.0" + "@typescript-eslint/utils" "7.16.0" debug "^4.3.4" ts-api-utils "^1.3.0" @@ -2959,10 +2959,10 @@ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.13.0.tgz#0cca95edf1f1fdb0cfe1bb875e121b49617477c5" integrity sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA== -"@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/types@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-7.16.0.tgz#60a19d7e7a6b1caa2c06fac860829d162a036ed2" + integrity sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw== "@typescript-eslint/typescript-estree@7.13.0": version "7.13.0" @@ -2978,13 +2978,13 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@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== +"@typescript-eslint/typescript-estree@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz#98ac779d526fab2a781e5619c9250f3e33867c09" + integrity sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw== dependencies: - "@typescript-eslint/types" "7.14.1" - "@typescript-eslint/visitor-keys" "7.14.1" + "@typescript-eslint/types" "7.16.0" + "@typescript-eslint/visitor-keys" "7.16.0" debug "^4.3.4" globby "^11.1.0" is-glob "^4.0.3" @@ -2992,15 +2992,15 @@ semver "^7.6.0" ts-api-utils "^1.3.0" -"@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== +"@typescript-eslint/utils@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-7.16.0.tgz#b38dc0ce1778e8182e227c98d91d3418449aa17f" + integrity sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA== dependencies: "@eslint-community/eslint-utils" "^4.4.0" - "@typescript-eslint/scope-manager" "7.14.1" - "@typescript-eslint/types" "7.14.1" - "@typescript-eslint/typescript-estree" "7.14.1" + "@typescript-eslint/scope-manager" "7.16.0" + "@typescript-eslint/types" "7.16.0" + "@typescript-eslint/typescript-estree" "7.16.0" "@typescript-eslint/utils@^6.0.0 || ^7.0.0": version "7.13.0" @@ -3020,12 +3020,12 @@ "@typescript-eslint/types" "7.13.0" eslint-visitor-keys "^3.4.3" -"@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== +"@typescript-eslint/visitor-keys@7.16.0": + version "7.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz#a1d99fa7a3787962d6e0efd436575ef840e23b06" + integrity sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg== dependencies: - "@typescript-eslint/types" "7.14.1" + "@typescript-eslint/types" "7.16.0" eslint-visitor-keys "^3.4.3" "@ungap/structured-clone@^1.2.0": @@ -7021,9 +7021,9 @@ minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: brace-expansion "^1.1.7" minimatch@^9.0.4: - version "9.0.4" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" - integrity sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw== + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== dependencies: brace-expansion "^2.0.1" From 93d5d2b39baad1b098a6ba37fb44829876ba40e7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:02:37 +0000 Subject: [PATCH 09/59] Update dependency @vector-im/compound-design-tokens to v1.5.0 (#12758) 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 d5d672b2f8..11aa09df08 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3034,9 +3034,9 @@ integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== "@vector-im/compound-design-tokens@^1.2.0": - version "1.4.0" - resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-1.4.0.tgz#a76cf2df3c64b273117f726851fc2b9fd9833b80" - integrity sha512-C3i1656SAQl2/F9qL8wDP8n690eJdFTYIJFMO4Qh3YALjVclRgjmTZvkR4gp6ylS5+AB/dU1dTRIW6KD+I8b0A== + version "1.5.0" + resolved "https://registry.yarnpkg.com/@vector-im/compound-design-tokens/-/compound-design-tokens-1.5.0.tgz#6c8ed8eb0ddbb1fd8f8e6025d66b856dee8b5677" + integrity sha512-G1EvLJ2lyWjd2esKqlJjQl7KXrCfQNKZUdtW68y2aQi8EvVMOpVvCNXGf0HwRmdXGGy2FhBIOufVTgx39I7juw== dependencies: svg2vectordrawable "^2.9.1" From 454e9346a2756600e08db2b5e2082b10eaa8ea6c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 18:39:26 +0100 Subject: [PATCH 10/59] Update all non-major dependencies (#12756) * Update all non-major dependencies * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 4 +- .../views/elements/SyntaxHighlight-test.tsx | 2 +- yarn.lock | 173 +++++------------- 3 files changed, 48 insertions(+), 131 deletions(-) diff --git a/package.json b/package.json index c0ee0665cd..89a9946811 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,7 @@ "emojibase-regex": "15.3.2", "escape-html": "^1.0.3", "file-saver": "^2.0.5", - "filesize": "10.1.2", + "filesize": "10.1.4", "github-markdown-css": "^5.5.1", "glob-to-regexp": "^0.4.1", "highlight.js": "^11.3.1", @@ -121,7 +121,7 @@ "opus-recorder": "^8.0.3", "pako": "^2.0.3", "png-chunks-extract": "^1.0.0", - "posthog-js": "1.144.2", + "posthog-js": "1.145.0", "qrcode": "1.5.3", "re-resizable": "^6.9.0", "react": "17.0.2", diff --git a/test/components/views/elements/SyntaxHighlight-test.tsx b/test/components/views/elements/SyntaxHighlight-test.tsx index 2f8c751fd7..3c59c6df46 100644 --- a/test/components/views/elements/SyntaxHighlight-test.tsx +++ b/test/components/views/elements/SyntaxHighlight-test.tsx @@ -35,6 +35,6 @@ describe("", () => { await waitFor(() => expect(container.querySelector(`.language-${lang}`)).toBeTruthy()); const [_lang, opts] = mock.mock.lastCall!; - expect((opts as HighlightOptions)["language"]).toBe(lang); + expect((opts as unknown as HighlightOptions)["language"]).toBe(lang); }); }); diff --git a/yarn.lock b/yarn.lock index 11aa09df08..43e689dc1b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -55,7 +55,7 @@ "@nicolo-ribaudo/chokidar-2" "2.1.8-no-fsevents.3" chokidar "^3.4.0" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.24.7": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.22.13", "@babel/code-frame@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== @@ -63,7 +63,7 @@ "@babel/highlight" "^7.24.7" picocolors "^1.0.0" -"@babel/code-frame@^7.10.4", "@babel/code-frame@^7.22.13": +"@babel/code-frame@^7.10.4": version "7.23.5" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== @@ -79,14 +79,6 @@ "@babel/highlight" "^7.22.13" chalk "^2.4.2" -"@babel/code-frame@^7.23.5": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.2.tgz#718b4b19841809a58b29b68cde80bc5e1aa6d9ae" - integrity sha512-y5+tLQyV8pg3fsiln67BVLD1P13Eg4lh5RW9mF0zUuvLrv9uIQ4MCL+CRT+FTsBlBjcIan6PGsLcBN0m3ClUyQ== - dependencies: - "@babel/highlight" "^7.24.2" - picocolors "^1.0.0" - "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.7.tgz#d23bbea508c3883ba8251fb4164982c36ea577ed" @@ -160,17 +152,7 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" -"@babel/generator@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.3.tgz#86e6e83d95903fbe7613f448613b8b319f330a8e" - integrity sha512-keeZWAV4LU3tW0qRi19HRpabC/ilM0HRBBzf9/k8FFiG4KVpiv0FIy4hHfLfFQZNhziCTPTmd59zoyv6DNISzg== - dependencies: - "@babel/types" "^7.23.3" - "@jridgewell/gen-mapping" "^0.3.2" - "@jridgewell/trace-mapping" "^0.3.17" - jsesc "^2.5.1" - -"@babel/generator@^7.24.7": +"@babel/generator@^7.23.3", "@babel/generator@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.24.7.tgz#1654d01de20ad66b4b4d99c135471bc654c55e6d" integrity sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA== @@ -252,27 +234,14 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" -"@babel/helper-environment-visitor@^7.22.20": - version "7.22.20" - resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" - integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== - -"@babel/helper-environment-visitor@^7.24.7": +"@babel/helper-environment-visitor@^7.22.20", "@babel/helper-environment-visitor@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz#4b31ba9551d1f90781ba83491dd59cf9b269f7d9" integrity sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ== dependencies: "@babel/types" "^7.24.7" -"@babel/helper-function-name@^7.23.0": - version "7.23.0" - resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" - integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== - dependencies: - "@babel/template" "^7.22.15" - "@babel/types" "^7.23.0" - -"@babel/helper-function-name@^7.24.7": +"@babel/helper-function-name@^7.23.0", "@babel/helper-function-name@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz#75f1e1725742f39ac6584ee0b16d94513da38dd2" integrity sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA== @@ -280,14 +249,7 @@ "@babel/template" "^7.24.7" "@babel/types" "^7.24.7" -"@babel/helper-hoist-variables@^7.22.5": - version "7.22.5" - resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" - integrity sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw== - dependencies: - "@babel/types" "^7.22.5" - -"@babel/helper-hoist-variables@^7.24.7": +"@babel/helper-hoist-variables@^7.22.5", "@babel/helper-hoist-variables@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz#b4ede1cde2fd89436397f30dc9376ee06b0f25ee" integrity sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ== @@ -392,36 +354,19 @@ "@babel/traverse" "^7.24.7" "@babel/types" "^7.24.7" -"@babel/helper-split-export-declaration@^7.22.6": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.5.tgz#b9a67f06a46b0b339323617c8c6213b9055a78b6" - integrity sha512-5CHncttXohrHk8GWOFCcCl4oRD9fKosWlIRgWm4ql9VYioKm52Mk2xsmoohvm7f3JoiLSM5ZgJuRaf5QZZYd3Q== - dependencies: - "@babel/types" "^7.24.5" - -"@babel/helper-split-export-declaration@^7.24.7": +"@babel/helper-split-export-declaration@^7.22.6", "@babel/helper-split-export-declaration@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz#83949436890e07fa3d6873c61a96e3bbf692d856" integrity sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA== dependencies: "@babel/types" "^7.24.7" -"@babel/helper-string-parser@^7.22.5": - version "7.23.4" - resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" - integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== - -"@babel/helper-string-parser@^7.24.1", "@babel/helper-string-parser@^7.24.7": +"@babel/helper-string-parser@^7.22.5", "@babel/helper-string-parser@^7.24.1", "@babel/helper-string-parser@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz#4d2d0f14820ede3b9807ea5fc36dfc8cd7da07f2" integrity sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg== -"@babel/helper-validator-identifier@^7.22.20": - version "7.24.5" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62" - integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA== - -"@babel/helper-validator-identifier@^7.24.5", "@babel/helper-validator-identifier@^7.24.7": +"@babel/helper-validator-identifier@^7.22.20", "@babel/helper-validator-identifier@^7.24.5", "@babel/helper-validator-identifier@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== @@ -467,17 +412,7 @@ chalk "^2.4.2" js-tokens "^4.0.0" -"@babel/highlight@^7.23.4": - version "7.24.2" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.2.tgz#3f539503efc83d3c59080a10e6634306e0370d26" - integrity sha512-Yac1ao4flkTxTteCDZLEvdxg2fZfz1v8M4QpaGypq/WPDqg3ijHYbDfs+LG5hvzSoqaSZ9/Z9lKSP3CjZjv+pA== - dependencies: - "@babel/helper-validator-identifier" "^7.22.20" - chalk "^2.4.2" - js-tokens "^4.0.0" - picocolors "^1.0.0" - -"@babel/highlight@^7.24.2", "@babel/highlight@^7.24.7": +"@babel/highlight@^7.23.4", "@babel/highlight@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== @@ -487,7 +422,7 @@ js-tokens "^4.0.0" picocolors "^1.0.0" -"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.14.7", "@babel/parser@^7.18.5", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16", "@babel/parser@^7.23.3", "@babel/parser@^7.24.0", "@babel/parser@^7.24.7": +"@babel/parser@^7.1.0", "@babel/parser@^7.12.11", "@babel/parser@^7.14.7", "@babel/parser@^7.18.5", "@babel/parser@^7.20.7", "@babel/parser@^7.22.15", "@babel/parser@^7.22.16", "@babel/parser@^7.23.3", "@babel/parser@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.7.tgz#9a5226f92f0c5c8ead550b750f5608e766c8ce85" integrity sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw== @@ -1290,16 +1225,7 @@ 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" - integrity sha512-Bkf2q8lMB0AFpX0NFEqSbx1OkTHf0f+0j82mkw+ZpzBnkk7e9Ql0891vlfgi+kHwOk8tQjiQHpqh4LaSa0fKEA== - dependencies: - "@babel/code-frame" "^7.23.5" - "@babel/parser" "^7.24.0" - "@babel/types" "^7.24.0" - -"@babel/template@^7.24.7": +"@babel/template@^7.22.15", "@babel/template@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.7.tgz#02efcee317d0609d2c07117cb70ef8fb17ab7315" integrity sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig== @@ -1317,23 +1243,7 @@ "@babel/parser" "^7.22.15" "@babel/types" "^7.22.15" -"@babel/traverse@^7.18.5", "@babel/traverse@^7.22.15", "@babel/traverse@^7.22.20": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.3.tgz#26ee5f252e725aa7aca3474aa5b324eaf7908b5b" - integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ== - dependencies: - "@babel/code-frame" "^7.22.13" - "@babel/generator" "^7.23.3" - "@babel/helper-environment-visitor" "^7.22.20" - "@babel/helper-function-name" "^7.23.0" - "@babel/helper-hoist-variables" "^7.22.5" - "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.23.3" - "@babel/types" "^7.23.3" - debug "^4.1.0" - globals "^11.1.0" - -"@babel/traverse@^7.24.7": +"@babel/traverse@^7.18.5", "@babel/traverse@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.7.tgz#de2b900163fa741721ba382163fe46a936c40cf5" integrity sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA== @@ -1349,6 +1259,22 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.22.15", "@babel/traverse@^7.22.20": + version "7.23.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.3.tgz#26ee5f252e725aa7aca3474aa5b324eaf7908b5b" + integrity sha512-+K0yF1/9yR0oHdE0StHuEj3uTPzwwbrLGfNOndVJVV2TqA5+j3oljJUb4nmB954FLGjNem976+B+eDuLIjesiQ== + dependencies: + "@babel/code-frame" "^7.22.13" + "@babel/generator" "^7.23.3" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" + "@babel/helper-hoist-variables" "^7.22.5" + "@babel/helper-split-export-declaration" "^7.22.6" + "@babel/parser" "^7.23.3" + "@babel/types" "^7.23.3" + debug "^4.1.0" + globals "^11.1.0" + "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.3.3": version "7.23.0" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.0.tgz#8c1f020c9df0e737e4e247c0619f58c68458aaeb" @@ -1358,7 +1284,7 @@ "@babel/helper-validator-identifier" "^7.22.20" to-fast-properties "^2.0.0" -"@babel/types@^7.22.15", "@babel/types@^7.22.19", "@babel/types@^7.23.0", "@babel/types@^7.24.0", "@babel/types@^7.24.5": +"@babel/types@^7.22.15", "@babel/types@^7.22.19": version "7.24.5" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.5.tgz#7661930afc638a5383eb0c4aee59b74f38db84d7" integrity sha512-6mQNsaLeXTw0nxYUYu+NSa4Hx4BlF1x1x8/PMFbiR+GBSr+2DkECc69b8hgy2frEodNcvPffeH8YfWd3LI6jhQ== @@ -1367,7 +1293,7 @@ "@babel/helper-validator-identifier" "^7.24.5" to-fast-properties "^2.0.0" -"@babel/types@^7.22.5", "@babel/types@^7.24.7", "@babel/types@^7.4.4": +"@babel/types@^7.23.0", "@babel/types@^7.23.3", "@babel/types@^7.24.0", "@babel/types@^7.24.5", "@babel/types@^7.24.7", "@babel/types@^7.4.4": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.7.tgz#6027fe12bc1aa724cd32ab113fb7f1988f1f66f2" integrity sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q== @@ -1376,15 +1302,6 @@ "@babel/helper-validator-identifier" "^7.24.7" to-fast-properties "^2.0.0" -"@babel/types@^7.23.3": - version "7.23.3" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.3.tgz#d5ea892c07f2ec371ac704420f4dcdb07b5f9598" - integrity sha512-OZnvoH2l8PK5eUvEcUyCt/sXgr/h+UWpVuBbOljwcrAgUl6lpchoQ++PHGyQy1AtYnVA6CEq3y5xeEI10brpXw== - dependencies: - "@babel/helper-string-parser" "^7.22.5" - "@babel/helper-validator-identifier" "^7.22.20" - to-fast-properties "^2.0.0" - "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -5098,10 +5015,10 @@ file-saver@^2.0.5: resolved "https://registry.yarnpkg.com/file-saver/-/file-saver-2.0.5.tgz#d61cfe2ce059f414d899e9dd6d4107ee25670c38" integrity sha512-P9bmyZ3h/PRG+Nzga+rbdI4OEpNDzAVyy74uVO9ATgzLK6VtAsYybF/+TOCvrc0MO793d6+42lLyZTw7/ArVzA== -filesize@10.1.2: - version "10.1.2" - resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.2.tgz#33bb71c5c134102499f1bc36e6f2863137f6cb0c" - integrity sha512-Dx770ai81ohflojxhU+oG+Z2QGvKdYxgEr9OSA8UVrqhwNHjfH9A8f5NKfg83fEH8ZFA5N5llJo5T3PIoZ4CRA== +filesize@10.1.4: + version "10.1.4" + resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.4.tgz#184f256063a201f08b6e6b3cc47d21b60f5b8d89" + integrity sha512-ryBwPIIeErmxgPnm6cbESAzXjuEFubs+yKYLBZvg3CaiNcmkJChoOGcBSrZ6IwkMwPABwPpVXE6IlNdGJJrvEg== fill-range@^7.1.1: version "7.1.1" @@ -5506,9 +5423,9 @@ hasown@^2.0.0, hasown@^2.0.1, hasown@^2.0.2: function-bind "^1.1.2" highlight.js@^11.3.1: - version "11.9.0" - resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.9.0.tgz#04ab9ee43b52a41a047432c8103e2158a1b8b5b0" - integrity sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw== + version "11.10.0" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-11.10.0.tgz#6e3600dc4b33d6dc23d5bd94fbf72405f5892b92" + integrity sha512-SYVnVFswQER+zu1laSya563s+F8VDGt7o35d4utbamowvUNLLMovFqwCLSocpZTz3MgaSRA1IbqRWZv97dtErQ== hoist-non-react-statics@^3.3.0, hoist-non-react-statics@^3.3.2: version "3.3.2" @@ -6889,9 +6806,9 @@ matrix-events-sdk@0.0.1: uuid "10" matrix-web-i18n@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/matrix-web-i18n/-/matrix-web-i18n-3.2.1.tgz#34e6b66bec71a52fddbe72db56d9e35dabbaff59" - integrity sha512-pBklE6Q6mAwG6N3Qtpu/e+qX0XuWEdrs4SZ+QmYJWfyLNtKAB6XcSpE5m7aBW/+11ejg8ua8Q5bNcDV2b7C9lg== + version "3.3.0" + resolved "https://registry.yarnpkg.com/matrix-web-i18n/-/matrix-web-i18n-3.3.0.tgz#a9f9d87d18ef96f75171883abbf201952cbfbe22" + integrity sha512-bJPJrBGrCdslkf2wMVHWyZlAEx9zSKnOsJ9rILaaEy195yyNLpXrYoyRIXEk8YWsdwtaK1ImE+r/Gh43J/I4ow== dependencies: "@babel/parser" "^7.18.5" "@babel/traverse" "^7.18.5" @@ -7572,10 +7489,10 @@ postcss@^8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" -posthog-js@1.144.2: - version "1.144.2" - resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.144.2.tgz#be9dbc126bff2ef1bba17f546f2a591cd08f1ec0" - integrity sha512-Kgq8/bJvrTbDDsfSqAURIiYdkJ5tPegR2JC6pqIeoFjnTx/Rrq0j4n3vDW7K1nCapBch7G5gTZdaK7O6t+rI9A== +posthog-js@1.145.0: + version "1.145.0" + resolved "https://registry.yarnpkg.com/posthog-js/-/posthog-js-1.145.0.tgz#5159459f02988b74407a1dd2b19469c422b31feb" + integrity sha512-LQdH6S2Ks3mnCI0q9aD5SZS0Uujc/90nuJuEeGDeGkWkVkYOSQJt4n0UHrIWEsZdmIKZf0a6OIBhTmO+yUiY3w== dependencies: fflate "^0.4.8" preact "^10.19.3" From fff0985bf4a24cc07696a003f3f43b3dcb8a8ced Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 9 Jul 2024 17:40:06 +0000 Subject: [PATCH 11/59] Update dependency @sentry/browser to v8.16.0 (#12757) 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 43e689dc1b..8e702d5d2a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2212,76 +2212,76 @@ 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.15.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.15.0.tgz#d78646d02d76445ba71c7ed423d749b192ef010c" - integrity sha512-DquySUQRnmMyRbfHH9t/JDwPMsVaCOCzV/6XmMb7s4FDYTWSCSpumJEYfiyJCuI9NeebPHZWF7LZCHH4glSAJQ== +"@sentry-internal/browser-utils@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/browser-utils/-/browser-utils-8.16.0.tgz#182931f169a586dde50cf255237b129aad00dde7" + integrity sha512-40lzNy5F6dUFCN85AGThBxHPQLSwoNhZM2hWqhAR5rZ3Yed0uBaKlm4aNJCeeUB9l4kd0sH0In+i9Nqu6TGKrw== dependencies: - "@sentry/core" "8.15.0" - "@sentry/types" "8.15.0" - "@sentry/utils" "8.15.0" + "@sentry/core" "8.16.0" + "@sentry/types" "8.16.0" + "@sentry/utils" "8.16.0" -"@sentry-internal/feedback@8.15.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.15.0.tgz#c28a176208dd53025c7aff4eb4df0fa19f48e0c4" - integrity sha512-W6XiLpw7fL1A0KaHxIH45nbC2M8uagrMoBnMZ1NcqE4AoSe7VtoDqPsLvQ7MgMXwsBYiPu2AItRnKoGFS/dUBA== +"@sentry-internal/feedback@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/feedback/-/feedback-8.16.0.tgz#dc8a3b807a37d0df136e62937e87ac23ce2ce6a8" + integrity sha512-BmRazZKl6iiVSg6eybUNOI1ve4eZqYpJYjkX48Jedn+7iZg7z12MNYl6IWPFBcN+sg+clf4wiKDr/SYS0yNemQ== dependencies: - "@sentry/core" "8.15.0" - "@sentry/types" "8.15.0" - "@sentry/utils" "8.15.0" + "@sentry/core" "8.16.0" + "@sentry/types" "8.16.0" + "@sentry/utils" "8.16.0" -"@sentry-internal/replay-canvas@8.15.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.15.0.tgz#0201eaae000678bdb0b054cd558f5c1bb0882454" - integrity sha512-gfezIuvf94wY748l5wSy4pRm+45GjiBm0Q/KLnXROLZKmbI7MTJrdQXA2Oxut848iISTQo4/LimecFnBDiaGtw== +"@sentry-internal/replay-canvas@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay-canvas/-/replay-canvas-8.16.0.tgz#c6501dd9f7e5dac1399978cc9e2797eb281a8f70" + integrity sha512-Bjh6pCDLZIPAPU2dNvJfI7BQV16rsRtYcylJgkGamjf8IcaBu7r/Whsvt1q34xO29xc0ISlp+0xG+YAdN1690Q== dependencies: - "@sentry-internal/replay" "8.15.0" - "@sentry/core" "8.15.0" - "@sentry/types" "8.15.0" - "@sentry/utils" "8.15.0" + "@sentry-internal/replay" "8.16.0" + "@sentry/core" "8.16.0" + "@sentry/types" "8.16.0" + "@sentry/utils" "8.16.0" -"@sentry-internal/replay@8.15.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.15.0.tgz#5382790b9c5b0d223aebdf50ad84135463eecd32" - integrity sha512-d4cA8pjr0CGHkTe8ulqMROYCX3bMHBAi/7DJBr11i4MdNCUl+/pndA9C5TiFv0sFzk/hDZQZS3J+MfGp56ZQHw== +"@sentry-internal/replay@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry-internal/replay/-/replay-8.16.0.tgz#5bf564d7293d4fb4993327567e9ad12079ceb951" + integrity sha512-JT/wmYU2JPtl8Ldl9oml/25Yz6C5wG+SpylDeUx4mPh728E/iI9vesIc2652J/0xots/DZXe4K6K5nYjdFtEcQ== dependencies: - "@sentry-internal/browser-utils" "8.15.0" - "@sentry/core" "8.15.0" - "@sentry/types" "8.15.0" - "@sentry/utils" "8.15.0" + "@sentry-internal/browser-utils" "8.16.0" + "@sentry/core" "8.16.0" + "@sentry/types" "8.16.0" + "@sentry/utils" "8.16.0" "@sentry/browser@^8.0.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.15.0.tgz#81223a4ee448c7ffed662301314132c3f442ec08" - integrity sha512-Tx4eFgAqa8tedg30+Cgr7qFocWHise8p3jb/RSNs+TCEBXLVtQidHHVZMO71FWUAC86D7woo5hMKTt+UmB8pgg== + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-8.16.0.tgz#af9b7b7556198d6de03cbc41b7abb5a16ecfc342" + integrity sha512-8Fxmk2aFWRixi2IKixiJR10Du34yb13HYr2iRw1haPKb5ZKa6CFA+XAnSzwpPZxO0RSHuPQR06YNkXaQ8fRAQQ== dependencies: - "@sentry-internal/browser-utils" "8.15.0" - "@sentry-internal/feedback" "8.15.0" - "@sentry-internal/replay" "8.15.0" - "@sentry-internal/replay-canvas" "8.15.0" - "@sentry/core" "8.15.0" - "@sentry/types" "8.15.0" - "@sentry/utils" "8.15.0" + "@sentry-internal/browser-utils" "8.16.0" + "@sentry-internal/feedback" "8.16.0" + "@sentry-internal/replay" "8.16.0" + "@sentry-internal/replay-canvas" "8.16.0" + "@sentry/core" "8.16.0" + "@sentry/types" "8.16.0" + "@sentry/utils" "8.16.0" -"@sentry/core@8.15.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.15.0.tgz#a8df0a6bfeedad090c7b5ac3f76656f8ed28ac70" - integrity sha512-RjuEq/34VjNmxlfzq+485jG63/Vst90svQapLwVgBZWgM8jxrLyCRXHU0wfBc7/1IhV/T9GYAplrJQAkG4J9Ow== +"@sentry/core@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry/core/-/core-8.16.0.tgz#cf2f4e572240983ec7e9fa083cc1ffce3147f20b" + integrity sha512-l9mQgm5OqnykvZMh6PmJ/9ygW4qLyEFop+pQH/uM5zQCZQvEa7rvAd9QXKHdbVKq1CxJa/nJiByc8wPWxsftGQ== dependencies: - "@sentry/types" "8.15.0" - "@sentry/utils" "8.15.0" + "@sentry/types" "8.16.0" + "@sentry/utils" "8.16.0" -"@sentry/types@8.15.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.15.0.tgz#bcf1eca41bccbc6eb434cc14ab7364eed41a8c17" - integrity sha512-AZc9nSHKuNH8P/7ihmq5fbZBiQ7Gr35kJq9Tad9eVuOgL8D+2b6Vqu/61ljVVlMFI0tBGFsSkWJ/00PfBcVKWg== +"@sentry/types@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry/types/-/types-8.16.0.tgz#a9ae39cffd50a0bdba0556a1596fb135d035cf26" + integrity sha512-cIRsn7gWGVaWHgCniBWA0N8PNwzDYibhjyjPRTMxUjuZCT37i7zxByKKmd9u4TpRIJ64MyirNyM0O6T0A26fpg== -"@sentry/utils@8.15.0": - version "8.15.0" - resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.15.0.tgz#31890e97e77bd27484c0831402e1666d3e289b03" - integrity sha512-1ISmyYFuRHJbGun0gUYscyz1aP6RfILUldNAUwQwF0Ycu8YOi4n8uwJRN0aov6cCi41tnZWOMBagSeLxbJiJgQ== +"@sentry/utils@8.16.0": + version "8.16.0" + resolved "https://registry.yarnpkg.com/@sentry/utils/-/utils-8.16.0.tgz#5d1c9fb6cd562660b507c6647e6437282bef939a" + integrity sha512-tltCf2DVzz5TiYjxu/Rxbc9Qmm04893MFshV97jOTBcQeO2AAZBEl5rAoTCv1P08y7Yg+KiVwCx9Zj2x5U80/g== dependencies: - "@sentry/types" "8.15.0" + "@sentry/types" "8.16.0" "@sinclair/typebox@^0.27.8": version "0.27.8" From 2712803bbb334b907df53451ec2572fdc8c2a53f Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 10 Jul 2024 07:24:03 +0100 Subject: [PATCH 12/59] [create-pull-request] automated change (#12759) 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 0385f64d03..8562ec32ae 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:db5f8e8ca4a903379ea18b010ac3360bd843c9ac7eb2e73ad89f5059d01f8104"; +const DOCKER_TAG = "develop@sha256:e5f6da1f643417a60f0d398546f9e8a28c51fe743f2562c132f8f99dcce0266d"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From c894bebaa076fb392700cd5c4be3d39f16116142 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 10 Jul 2024 10:06:13 +0100 Subject: [PATCH 13/59] Split up slow Playwright tests (#12741) * Split up slow Playwright tests To optimise parallelism Deals with: ``` Slow test file: read-receipts/redactions.spec.ts (5.4m) Slow test file: read-receipts/new-messages.spec.ts (3.9m) Slow test file: read-receipts/high-level.spec.ts (3.6m) Slow test file: read-receipts/editing-messages.spec.ts (3.1m) Slow test file: read-receipts/reactions.spec.ts (2.2m) Slow test file: crypto/crypto.spec.ts (2.4m) Slow test file: settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts (1.2m) Slow test file: composer/composer.spec.ts (1.1m) Slow test file: crypto/verification.spec.ts (1.1m) ``` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Move around snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- playwright/e2e/composer/CIDER.spec.ts | 106 ++++ .../{composer.spec.ts => RTE.spec.ts} | 70 --- playwright/e2e/crypto/crypto.spec.ts | 558 +----------------- .../decryption-failure-messages.spec.ts | 302 ++++++++++ ...on.spec.ts => device-verification.spec.ts} | 143 +---- playwright/e2e/crypto/event-shields.spec.ts | 269 +++++++++ .../e2e/crypto/user-verification.spec.ts | 145 +++++ playwright/e2e/crypto/utils.ts | 66 +++ .../editing-messages-in-threads.spec.ts | 191 ++++++ .../editing-messages-main-timeline.spec.ts | 180 ++++++ .../editing-messages-thread-roots.spec.ts | 179 ++++++ .../read-receipts/editing-messages.spec.ts | 504 ---------------- .../e2e/read-receipts/high-level.spec.ts | 146 ----- .../read-receipts/message-ordering.spec.ts | 92 +++ ...pec.ts => new-messages-in-threads.spec.ts} | 240 -------- .../new-messages-main-timeline.spec.ts | 168 ++++++ .../new-messages-thread-roots.spec.ts | 118 ++++ .../e2e/read-receipts/notifications.spec.ts | 56 ++ ...s.spec.ts => reactions-in-threads.spec.ts} | 168 ------ .../reactions-main-timeline.spec.ts | 99 ++++ .../reactions-thread-roots.spec.ts | 115 ++++ ....spec.ts => redactions-in-threads.spec.ts} | 517 ---------------- .../redactions-main-timeline.spec.ts | 331 +++++++++++ .../redactions-thread-roots.spec.ts | 232 ++++++++ .../e2e/read-receipts/room-list-order.spec.ts | 61 ++ .../appearance-user-settings-tab.spec.ts | 109 ---- .../message-layout-panel.ts | 66 +++ .../theme-choice-panel.spec.ts | 89 +++ .../theme-panel-custom-theme-added-linux.png | Bin .../theme-panel-custom-theme-linux.png | Bin .../theme-panel-dark-linux.png | Bin .../theme-panel-light-linux.png | Bin ...theme-panel-match-system-enabled-linux.png | Bin 33 files changed, 2868 insertions(+), 2452 deletions(-) create mode 100644 playwright/e2e/composer/CIDER.spec.ts rename playwright/e2e/composer/{composer.spec.ts => RTE.spec.ts} (80%) create mode 100644 playwright/e2e/crypto/decryption-failure-messages.spec.ts rename playwright/e2e/crypto/{verification.spec.ts => device-verification.spec.ts} (67%) create mode 100644 playwright/e2e/crypto/event-shields.spec.ts create mode 100644 playwright/e2e/crypto/user-verification.spec.ts create mode 100644 playwright/e2e/read-receipts/editing-messages-in-threads.spec.ts create mode 100644 playwright/e2e/read-receipts/editing-messages-main-timeline.spec.ts create mode 100644 playwright/e2e/read-receipts/editing-messages-thread-roots.spec.ts delete mode 100644 playwright/e2e/read-receipts/editing-messages.spec.ts create mode 100644 playwright/e2e/read-receipts/message-ordering.spec.ts rename playwright/e2e/read-receipts/{new-messages.spec.ts => new-messages-in-threads.spec.ts} (55%) create mode 100644 playwright/e2e/read-receipts/new-messages-main-timeline.spec.ts create mode 100644 playwright/e2e/read-receipts/new-messages-thread-roots.spec.ts create mode 100644 playwright/e2e/read-receipts/notifications.spec.ts rename playwright/e2e/read-receipts/{reactions.spec.ts => reactions-in-threads.spec.ts} (56%) create mode 100644 playwright/e2e/read-receipts/reactions-main-timeline.spec.ts create mode 100644 playwright/e2e/read-receipts/reactions-thread-roots.spec.ts rename playwright/e2e/read-receipts/{redactions.spec.ts => redactions-in-threads.spec.ts} (52%) create mode 100644 playwright/e2e/read-receipts/redactions-main-timeline.spec.ts create mode 100644 playwright/e2e/read-receipts/redactions-thread-roots.spec.ts create mode 100644 playwright/e2e/read-receipts/room-list-order.spec.ts create mode 100644 playwright/e2e/settings/appearance-user-settings-tab/message-layout-panel.ts create mode 100644 playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts rename playwright/snapshots/settings/appearance-user-settings-tab/{appearance-user-settings-tab.spec.ts => theme-choice-panel.spec.ts}/theme-panel-custom-theme-added-linux.png (100%) rename playwright/snapshots/settings/appearance-user-settings-tab/{appearance-user-settings-tab.spec.ts => theme-choice-panel.spec.ts}/theme-panel-custom-theme-linux.png (100%) rename playwright/snapshots/settings/appearance-user-settings-tab/{appearance-user-settings-tab.spec.ts => theme-choice-panel.spec.ts}/theme-panel-dark-linux.png (100%) rename playwright/snapshots/settings/appearance-user-settings-tab/{appearance-user-settings-tab.spec.ts => theme-choice-panel.spec.ts}/theme-panel-light-linux.png (100%) rename playwright/snapshots/settings/appearance-user-settings-tab/{appearance-user-settings-tab.spec.ts => theme-choice-panel.spec.ts}/theme-panel-match-system-enabled-linux.png (100%) diff --git a/playwright/e2e/composer/CIDER.spec.ts b/playwright/e2e/composer/CIDER.spec.ts new file mode 100644 index 0000000000..779babdaf2 --- /dev/null +++ b/playwright/e2e/composer/CIDER.spec.ts @@ -0,0 +1,106 @@ +/* +Copyright 2022 - 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { test, expect } from "../../element-web-test"; +import { SettingLevel } from "../../../src/settings/SettingLevel"; + +const CtrlOrMeta = process.platform === "darwin" ? "Meta" : "Control"; + +test.describe("Composer", () => { + test.use({ + displayName: "Janet", + }); + + test.use({ + room: async ({ app, user }, use) => { + const roomId = await app.client.createRoom({ name: "Composing Room" }); + await app.viewRoomByName("Composing Room"); + await use({ roomId }); + }, + }); + + test.beforeEach(async ({ room }) => {}); // trigger room fixture + + test.describe("CIDER", () => { + test("sends a message when you click send or press Enter", async ({ page }) => { + const composer = page.getByRole("textbox", { name: "Send a message…" }); + + // Type a message + await composer.pressSequentially("my message 0"); + // It has not been sent yet + await expect(page.locator(".mx_EventTile_body", { hasText: "my message 0" })).not.toBeVisible(); + + // Click send + await page.getByRole("button", { name: "Send message" }).click(); + // It has been sent + await expect( + page.locator(".mx_EventTile_last .mx_EventTile_body", { hasText: "my message 0" }), + ).toBeVisible(); + + // Type another and press Enter afterward + await composer.pressSequentially("my message 1"); + await composer.press("Enter"); + // It was sent + await expect( + page.locator(".mx_EventTile_last .mx_EventTile_body", { hasText: "my message 1" }), + ).toBeVisible(); + }); + + test("can write formatted text", async ({ page }) => { + const composer = page.getByRole("textbox", { name: "Send a message…" }); + + await composer.pressSequentially("my bold"); + await composer.press(`${CtrlOrMeta}+KeyB`); + await composer.pressSequentially(" message"); + await page.getByRole("button", { name: "Send message" }).click(); + // Note: both "bold" and "message" are bold, which is probably surprising + await expect(page.locator(".mx_EventTile_body strong", { hasText: "bold message" })).toBeVisible(); + }); + + test("should allow user to input emoji via graphical picker", async ({ page, app }) => { + await app.getComposer(false).getByRole("button", { name: "Emoji" }).click(); + + await page.getByTestId("mx_EmojiPicker").locator(".mx_EmojiPicker_item", { hasText: "😇" }).click(); + + await page.locator(".mx_ContextualMenu_background").click(); // Close emoji picker + await page.getByRole("textbox", { name: "Send a message…" }).press("Enter"); // Send message + + await expect(page.locator(".mx_EventTile_body", { hasText: "😇" })).toBeVisible(); + }); + + test.describe("when Control+Enter is required to send", () => { + test.beforeEach(async ({ app }) => { + await app.settings.setValue("MessageComposerInput.ctrlEnterToSend", null, SettingLevel.ACCOUNT, true); + }); + + test("only sends when you press Control+Enter", async ({ page }) => { + const composer = page.getByRole("textbox", { name: "Send a message…" }); + // Type a message and press Enter + await composer.pressSequentially("my message 3"); + await composer.press("Enter"); + // It has not been sent yet + await expect(page.locator(".mx_EventTile_body", { hasText: "my message 3" })).not.toBeVisible(); + + // Press Control+Enter + await composer.press(`${CtrlOrMeta}+Enter`); + // It was sent + await expect( + page.locator(".mx_EventTile_last .mx_EventTile_body", { hasText: "my message 3" }), + ).toBeVisible(); + }); + }); + }); +}); diff --git a/playwright/e2e/composer/composer.spec.ts b/playwright/e2e/composer/RTE.spec.ts similarity index 80% rename from playwright/e2e/composer/composer.spec.ts rename to playwright/e2e/composer/RTE.spec.ts index e7be457f83..53599d5320 100644 --- a/playwright/e2e/composer/composer.spec.ts +++ b/playwright/e2e/composer/RTE.spec.ts @@ -34,76 +34,6 @@ test.describe("Composer", () => { test.beforeEach(async ({ room }) => {}); // trigger room fixture - test.describe("CIDER", () => { - test("sends a message when you click send or press Enter", async ({ page }) => { - const composer = page.getByRole("textbox", { name: "Send a message…" }); - - // Type a message - await composer.pressSequentially("my message 0"); - // It has not been sent yet - await expect(page.locator(".mx_EventTile_body", { hasText: "my message 0" })).not.toBeVisible(); - - // Click send - await page.getByRole("button", { name: "Send message" }).click(); - // It has been sent - await expect( - page.locator(".mx_EventTile_last .mx_EventTile_body", { hasText: "my message 0" }), - ).toBeVisible(); - - // Type another and press Enter afterward - await composer.pressSequentially("my message 1"); - await composer.press("Enter"); - // It was sent - await expect( - page.locator(".mx_EventTile_last .mx_EventTile_body", { hasText: "my message 1" }), - ).toBeVisible(); - }); - - test("can write formatted text", async ({ page }) => { - const composer = page.getByRole("textbox", { name: "Send a message…" }); - - await composer.pressSequentially("my bold"); - await composer.press(`${CtrlOrMeta}+KeyB`); - await composer.pressSequentially(" message"); - await page.getByRole("button", { name: "Send message" }).click(); - // Note: both "bold" and "message" are bold, which is probably surprising - await expect(page.locator(".mx_EventTile_body strong", { hasText: "bold message" })).toBeVisible(); - }); - - test("should allow user to input emoji via graphical picker", async ({ page, app }) => { - await app.getComposer(false).getByRole("button", { name: "Emoji" }).click(); - - await page.getByTestId("mx_EmojiPicker").locator(".mx_EmojiPicker_item", { hasText: "😇" }).click(); - - await page.locator(".mx_ContextualMenu_background").click(); // Close emoji picker - await page.getByRole("textbox", { name: "Send a message…" }).press("Enter"); // Send message - - await expect(page.locator(".mx_EventTile_body", { hasText: "😇" })).toBeVisible(); - }); - - test.describe("when Control+Enter is required to send", () => { - test.beforeEach(async ({ app }) => { - await app.settings.setValue("MessageComposerInput.ctrlEnterToSend", null, SettingLevel.ACCOUNT, true); - }); - - test("only sends when you press Control+Enter", async ({ page }) => { - const composer = page.getByRole("textbox", { name: "Send a message…" }); - // Type a message and press Enter - await composer.pressSequentially("my message 3"); - await composer.press("Enter"); - // It has not been sent yet - await expect(page.locator(".mx_EventTile_body", { hasText: "my message 3" })).not.toBeVisible(); - - // Press Control+Enter - await composer.press(`${CtrlOrMeta}+Enter`); - // It was sent - await expect( - page.locator(".mx_EventTile_last .mx_EventTile_body", { hasText: "my message 3" }), - ).toBeVisible(); - }); - }); - }); - test.describe("Rich text editor", () => { test.use({ labsFlags: ["feature_wysiwyg_composer"], diff --git a/playwright/e2e/crypto/crypto.spec.ts b/playwright/e2e/crypto/crypto.spec.ts index 98f75d54e1..30301270ac 100644 --- a/playwright/e2e/crypto/crypto.spec.ts +++ b/playwright/e2e/crypto/crypto.spec.ts @@ -15,29 +15,10 @@ limitations under the License. */ import type { Page } from "@playwright/test"; -import type { EmittedEvents, Preset } from "matrix-js-sdk/src/matrix"; import { expect, test } from "../../element-web-test"; -import { - copyAndContinue, - createRoom, - createSharedRoomWithUser, - doTwoWaySasVerification, - enableKeyBackup, - logIntoElement, - logOutOfElement, - sendMessageInCurrentRoom, - verifySession, - waitForVerificationRequest, -} from "./utils"; +import { autoJoin, copyAndContinue, createSharedRoomWithUser, enableKeyBackup, verify } from "./utils"; import { Bot } from "../../pages/bot"; import { ElementAppPage } from "../../pages/ElementAppPage"; -import { Client } from "../../pages/client"; -import { isDendrite } from "../../plugins/homeserver/dendrite"; - -const openRoomInfo = async (page: Page) => { - await page.getByRole("button", { name: "Room info" }).click(); - return page.locator(".mx_RightPanel"); -}; const checkDMRoom = async (page: Page) => { const body = page.locator(".mx_RoomView_body"); @@ -88,38 +69,6 @@ const bobJoin = async (page: Page, bob: Bot) => { return roomId; }; -/** configure the given MatrixClient to auto-accept any invites */ -async function autoJoin(client: Client) { - await client.evaluate((cli) => { - cli.on(window.matrixcs.RoomMemberEvent.Membership, (event, member) => { - if (member.membership === "invite" && member.userId === cli.getUserId()) { - cli.joinRoom(member.roomId); - } - }); - }); -} - -const verify = async (page: Page, bob: Bot) => { - const bobsVerificationRequestPromise = waitForVerificationRequest(bob); - - const roomInfo = await openRoomInfo(page); - await page.locator(".mx_RightPanelTabs").getByText("People").click(); - await roomInfo.getByText("Bob").click(); - await roomInfo.getByRole("button", { name: "Verify" }).click(); - await roomInfo.getByRole("button", { name: "Start Verification" }).click(); - - // this requires creating a DM, so can take a while. Give it a longer timeout. - await roomInfo.getByRole("button", { name: "Verify by emoji" }).click({ timeout: 30000 }); - - const request = await bobsVerificationRequestPromise; - // the bot user races with the Element user to hit the "verify by emoji" button - const verifier = await request.evaluateHandle((request) => request.startVerification("m.sas.v1")); - await doTwoWaySasVerification(page, verifier); - await roomInfo.getByRole("button", { name: "They match" }).click(); - await expect(roomInfo.getByText("You've successfully verified Bob!")).toBeVisible(); - await roomInfo.getByRole("button", { name: "Got it" }).click(); -}; - test.describe("Cryptography", function () { test.use({ displayName: "Alice", @@ -299,509 +248,4 @@ test.describe("Cryptography", function () { await createSharedRoomWithUser(app, bob.credentials.userId); await verify(page, bob); }); - - test.describe("event shields", () => { - let testRoomId: string; - - test.beforeEach(async ({ page, bot: bob, user: aliceCredentials, app }) => { - await app.client.bootstrapCrossSigning(aliceCredentials); - await autoJoin(bob); - - // create an encrypted room - testRoomId = await createSharedRoomWithUser(app, bob.credentials.userId, { - name: "TestRoom", - initial_state: [ - { - type: "m.room.encryption", - state_key: "", - content: { - algorithm: "m.megolm.v1.aes-sha2", - }, - }, - ], - }); - }); - - test("should show the correct shield on e2e events", async ({ page, app, bot: bob, homeserver }) => { - // Bob has a second, not cross-signed, device - const bobSecondDevice = new Bot(page, homeserver, { - bootstrapSecretStorage: false, - bootstrapCrossSigning: false, - }); - bobSecondDevice.setCredentials( - await homeserver.loginUser(bob.credentials.userId, bob.credentials.password), - ); - await bobSecondDevice.prepareClient(); - - await bob.sendEvent(testRoomId, null, "m.room.encrypted", { - algorithm: "m.megolm.v1.aes-sha2", - ciphertext: "the bird is in the hand", - }); - - const last = page.locator(".mx_EventTile_last"); - await expect(last).toContainText("Unable to decrypt message"); - const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon"); - await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_decryption_failure/); - await lastE2eIcon.focus(); - await expect(page.getByRole("tooltip")).toContainText("This message could not be decrypted"); - - /* Should show a red padlock for an unencrypted message in an e2e room */ - await bob.evaluate( - (cli, testRoomId) => - cli.http.authedRequest( - window.matrixcs.Method.Put, - `/rooms/${encodeURIComponent(testRoomId)}/send/m.room.message/test_txn_1`, - undefined, - { - msgtype: "m.text", - body: "test unencrypted", - }, - ), - testRoomId, - ); - - await expect(last).toContainText("test unencrypted"); - await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/); - await lastE2eIcon.focus(); - await expect(page.getByRole("tooltip")).toContainText("Not encrypted"); - - /* Should show no padlock for an unverified user */ - // bob sends a valid event - await bob.sendMessage(testRoomId, "test encrypted 1"); - - // the message should appear, decrypted, with no warning, but also no "verified" - const lastTile = page.locator(".mx_EventTile_last"); - const lastTileE2eIcon = lastTile.locator(".mx_EventTile_e2eIcon"); - await expect(lastTile).toContainText("test encrypted 1"); - // no e2e icon - await expect(lastTileE2eIcon).not.toBeVisible(); - - /* Now verify Bob */ - await verify(page, bob); - - /* Existing message should be updated when user is verified. */ - await expect(last).toContainText("test encrypted 1"); - // still no e2e icon - await expect(last.locator(".mx_EventTile_e2eIcon")).not.toBeVisible(); - - /* should show no padlock, and be verified, for a message from a verified device */ - await bob.sendMessage(testRoomId, "test encrypted 2"); - - await expect(lastTile).toContainText("test encrypted 2"); - // no e2e icon - await expect(lastTileE2eIcon).not.toBeVisible(); - - /* should show red padlock for a message from an unverified device */ - await bobSecondDevice.sendMessage(testRoomId, "test encrypted from unverified"); - await expect(lastTile).toContainText("test encrypted from unverified"); - await expect(lastTileE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/); - await lastTileE2eIcon.focus(); - await expect(page.getByRole("tooltip")).toContainText("Encrypted by a device not verified by its owner."); - - /* Should show a grey padlock for a message from an unknown device */ - // bob deletes his second device - await bobSecondDevice.evaluate((cli) => cli.logout(true)); - - // wait for the logout to propagate. Workaround for https://github.com/vector-im/element-web/issues/26263 by repeatedly closing and reopening Bob's user info. - async function awaitOneDevice(iterations = 1) { - const rightPanel = page.locator(".mx_RightPanel"); - await rightPanel.getByRole("button", { name: "Room members" }).click(); - await rightPanel.getByText("Bob").click(); - const sessionCountText = await rightPanel - .locator(".mx_UserInfo_devices") - .getByText(" session", { exact: false }) - .textContent(); - // cf https://github.com/vector-im/element-web/issues/26279: Element-R uses the wrong text here - if (sessionCountText != "1 session" && sessionCountText != "1 verified session") { - if (iterations >= 10) { - throw new Error(`Bob still has ${sessionCountText} after 10 iterations`); - } - await awaitOneDevice(iterations + 1); - } - } - - await awaitOneDevice(); - - // close and reopen the room, to get the shield to update. - await app.viewRoomByName("Bob"); - await app.viewRoomByName("TestRoom"); - - await expect(last).toContainText("test encrypted from unverified"); - await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/); - await lastE2eIcon.focus(); - await expect(page.getByRole("tooltip")).toContainText("Encrypted by an unknown or deleted device."); - }); - - test("Should show a grey padlock for a key restored from backup", async ({ - page, - app, - bot: bob, - homeserver, - user: aliceCredentials, - }) => { - test.slow(); - const securityKey = await enableKeyBackup(app); - - // bob sends a valid event - await bob.sendMessage(testRoomId, "test encrypted 1"); - - const lastTile = page.locator(".mx_EventTile_last"); - const lastTileE2eIcon = lastTile.locator(".mx_EventTile_e2eIcon"); - await expect(lastTile).toContainText("test encrypted 1"); - // no e2e icon - await expect(lastTileE2eIcon).not.toBeVisible(); - - // Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for - // the key to be backed up. - await page.waitForTimeout(10000); - - /* log out, and back in */ - await logOutOfElement(page); - // Reload to work around a Rust crypto bug where it can hold onto the indexeddb even after logout - // https://github.com/element-hq/element-web/issues/25779 - await page.addInitScript(() => { - // When we reload, the initScript created by the `user`/`pageWithCredentials` fixtures - // will re-inject the original credentials into localStorage, which we don't want. - // To work around, we add a second initScript which will clear localStorage again. - window.localStorage.clear(); - }); - await page.reload(); - await logIntoElement(page, homeserver, aliceCredentials, securityKey); - - /* go back to the test room and find Bob's message again */ - await app.viewRoomById(testRoomId); - await expect(lastTile).toContainText("test encrypted 1"); - // The gray shield would be a mx_EventTile_e2eIcon_normal. The red shield would be a mx_EventTile_e2eIcon_warning. - // No shield would have no div mx_EventTile_e2eIcon at all. - await expect(lastTileE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_normal/); - await lastTileE2eIcon.hover(); - // The key is coming from backup, so it is not anymore possible to establish if the claimed device - // creator of this key is authentic. The tooltip should be "The authenticity of this encrypted message can't be guaranteed on this device." - // It is not "Encrypted by an unknown or deleted device." even if the claimed device is actually deleted. - await expect(page.getByRole("tooltip")).toContainText( - "The authenticity of this encrypted message can't be guaranteed on this device.", - ); - }); - - test("should show the correct shield on edited e2e events", async ({ page, app, bot: bob, homeserver }) => { - // bob has a second, not cross-signed, device - const bobSecondDevice = new Bot(page, homeserver, { - bootstrapSecretStorage: false, - bootstrapCrossSigning: false, - }); - bobSecondDevice.setCredentials( - await homeserver.loginUser(bob.credentials.userId, bob.credentials.password), - ); - await bobSecondDevice.prepareClient(); - - // verify Bob - await verify(page, bob); - - // bob sends a valid event - const testEvent = await bob.sendMessage(testRoomId, "Hoo!"); - - // the message should appear, decrypted, with no warning - await expect( - page.locator(".mx_EventTile", { hasText: "Hoo!" }).locator(".mx_EventTile_e2eIcon_warning"), - ).not.toBeVisible(); - - // bob sends an edit to the first message with his unverified device - await bobSecondDevice.sendMessage(testRoomId, { - "m.new_content": { - msgtype: "m.text", - body: "Haa!", - }, - "m.relates_to": { - rel_type: "m.replace", - event_id: testEvent.event_id, - }, - }); - - // the edit should have a warning - await expect( - page.locator(".mx_EventTile", { hasText: "Haa!" }).locator(".mx_EventTile_e2eIcon_warning"), - ).toBeVisible(); - - // a second edit from the verified device should be ok - await bob.sendMessage(testRoomId, { - "m.new_content": { - msgtype: "m.text", - body: "Hee!", - }, - "m.relates_to": { - rel_type: "m.replace", - event_id: testEvent.event_id, - }, - }); - - await expect( - page.locator(".mx_EventTile", { hasText: "Hee!" }).locator(".mx_EventTile_e2eIcon_warning"), - ).not.toBeVisible(); - }); - }); - - test.describe("decryption failure messages", () => { - test("should handle device-relative historical messages", async ({ - homeserver, - page, - app, - credentials, - user, - }) => { - test.setTimeout(60000); - - // Start with a logged-in session, without key backup, and send a message. - await createRoom(page, "Test room", true); - await sendMessageInCurrentRoom(page, "test test"); - - // Log out, discarding the key for the sent message. - await logOutOfElement(page, true); - - // Log in again, and see how the message looks. - await logIntoElement(page, homeserver, credentials); - await app.viewRoomByName("Test room"); - const lastTile = page.locator(".mx_EventTile").last(); - await expect(lastTile).toContainText("Historical messages are not available on this device"); - await expect(lastTile.locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); - - // Now, we set up key backup, and then send another message. - const secretStorageKey = await enableKeyBackup(app); - await app.viewRoomByName("Test room"); - await sendMessageInCurrentRoom(page, "test2 test2"); - - // Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for - // the key to be backed up. - await page.waitForTimeout(10000); - - // Finally, log out again, and back in, skipping verification for now, and see what we see. - await logOutOfElement(page); - await logIntoElement(page, homeserver, credentials); - await page.locator(".mx_AuthPage").getByRole("button", { name: "Skip verification for now" }).click(); - await page.locator(".mx_AuthPage").getByRole("button", { name: "I'll verify later" }).click(); - await app.viewRoomByName("Test room"); - - // There should be two historical events in the timeline - const tiles = await page.locator(".mx_EventTile").all(); - expect(tiles.length).toBeGreaterThanOrEqual(2); - // look at the last two tiles only - for (const tile of tiles.slice(-2)) { - await expect(tile).toContainText("You need to verify this device for access to historical messages"); - await expect(tile.locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); - } - - // Now verify our device (setting up key backup), and check what happens - await verifySession(app, secretStorageKey); - const tilesAfterVerify = (await page.locator(".mx_EventTile").all()).slice(-2); - - // The first message still cannot be decrypted, because it was never backed up. It's now a regular UTD though. - await expect(tilesAfterVerify[0]).toContainText("Unable to decrypt message"); - await expect(tilesAfterVerify[0].locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); - - // The second message should now be decrypted, with a grey shield - await expect(tilesAfterVerify[1]).toContainText("test2 test2"); - await expect(tilesAfterVerify[1].locator(".mx_EventTile_e2eIcon_normal")).toBeVisible(); - }); - - test.describe("non-joined historical messages", () => { - test.skip(isDendrite, "does not yet support membership on events"); - - test("should display undecryptable non-joined historical messages with a different message", async ({ - homeserver, - page, - app, - credentials: aliceCredentials, - user: alice, - bot: bob, - }) => { - // Bob creates an encrypted room and sends a message to it. He then invites Alice - const roomId = await bob.evaluate( - async (client, { alice }) => { - const encryptionStatePromise = new Promise((resolve) => { - client.on("RoomState.events" as EmittedEvents, (event, _state, _lastStateEvent) => { - if (event.getType() === "m.room.encryption") { - resolve(); - } - }); - }); - - const { room_id: roomId } = await client.createRoom({ - initial_state: [ - { - type: "m.room.encryption", - content: { - algorithm: "m.megolm.v1.aes-sha2", - }, - }, - ], - name: "Test room", - preset: "private_chat" as Preset, - }); - - // wait for m.room.encryption event, so that when we send a - // message, it will be encrypted - await encryptionStatePromise; - - await client.sendTextMessage(roomId, "This should be undecryptable"); - - await client.invite(roomId, alice.userId); - - return roomId; - }, - { alice }, - ); - - // Alice accepts the invite - await expect( - page.getByRole("group", { name: "Invites" }).locator(".mx_RoomSublist_tiles").getByRole("treeitem"), - ).toHaveCount(1); - await page.getByRole("treeitem", { name: "Test room" }).click(); - await page.locator(".mx_RoomView").getByRole("button", { name: "Accept" }).click(); - - // Bob sends an encrypted event and an undecryptable event - await bob.evaluate( - async (client, { roomId }) => { - await client.sendTextMessage(roomId, "This should be decryptable"); - await client.sendEvent( - roomId, - "m.room.encrypted" as any, - { - algorithm: "m.megolm.v1.aes-sha2", - ciphertext: "this+message+will+be+undecryptable", - device_id: client.getDeviceId()!, - sender_key: (await client.getCrypto()!.getOwnDeviceKeys()).ed25519, - session_id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - } as any, - ); - }, - { roomId }, - ); - - // We wait for the event tiles that we expect from the messages that - // Bob sent, in sequence. - await expect( - page.locator(`.mx_EventTile`).getByText("You don't have access to this message"), - ).toBeVisible(); - await expect(page.locator(`.mx_EventTile`).getByText("This should be decryptable")).toBeVisible(); - await expect(page.locator(`.mx_EventTile`).getByText("Unable to decrypt message")).toBeVisible(); - - // And then we ensure that they are where we expect them to be - // Alice should see these event tiles: - // - first message sent by Bob (undecryptable) - // - Bob invited Alice - // - Alice joined the room - // - second message sent by Bob (decryptable) - // - third message sent by Bob (undecryptable) - const tiles = await page.locator(".mx_EventTile").all(); - expect(tiles.length).toBeGreaterThanOrEqual(5); - - // The first message from Bob was sent before Alice was in the room, so should - // be different from the standard UTD message - await expect(tiles[tiles.length - 5]).toContainText("You don't have access to this message"); - await expect(tiles[tiles.length - 5].locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); - - // The second message from Bob should be decryptable - await expect(tiles[tiles.length - 2]).toContainText("This should be decryptable"); - // this tile won't have an e2e icon since we got the key from the sender - - // The third message from Bob is undecryptable, but was sent while Alice was - // in the room and is expected to be decryptable, so this should have the - // standard UTD message - await expect(tiles[tiles.length - 1]).toContainText("Unable to decrypt message"); - await expect(tiles[tiles.length - 1].locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); - }); - - test("should be able to jump to a message sent before our last join event", async ({ - homeserver, - page, - app, - credentials: aliceCredentials, - user: alice, - bot: bob, - }) => { - // Bob: - // - creates an encrypted room, - // - invites Alice, - // - sends a message to it, - // - kicks Alice, - // - sends a bunch more events - // - invites Alice again - // In this way, there will be an event that Alice can decrypt, - // followed by a bunch of undecryptable events which Alice shouldn't - // expect to be able to decrypt. The old code would have hidden all - // the events, even the decryptable event (which it wouldn't have - // even tried to fetch, if it was far enough back). - const { roomId, eventId } = await bob.evaluate( - async (client, { alice }) => { - const { room_id: roomId } = await client.createRoom({ - initial_state: [ - { - type: "m.room.encryption", - content: { - algorithm: "m.megolm.v1.aes-sha2", - }, - }, - ], - name: "Test room", - preset: "private_chat" as Preset, - }); - - // invite Alice - const inviteAlicePromise = new Promise((resolve) => { - client.on("RoomMember.membership" as EmittedEvents, (_event, member, _oldMembership?) => { - if (member.userId === alice.userId && member.membership === "invite") { - resolve(); - } - }); - }); - await client.invite(roomId, alice.userId); - // wait for the invite to come back so that we encrypt to Alice - await inviteAlicePromise; - - // send a message that Alice should be able to decrypt - const { event_id: eventId } = await client.sendTextMessage( - roomId, - "This should be decryptable", - ); - - // kick Alice - const kickAlicePromise = new Promise((resolve) => { - client.on("RoomMember.membership" as EmittedEvents, (_event, member, _oldMembership?) => { - if (member.userId === alice.userId && member.membership === "leave") { - resolve(); - } - }); - }); - await client.kick(roomId, alice.userId); - await kickAlicePromise; - - // send a bunch of messages that Alice won't be able to decrypt - for (let i = 0; i < 20; i++) { - await client.sendTextMessage(roomId, `${i}`); - } - - // invite Alice again - await client.invite(roomId, alice.userId); - - return { roomId, eventId }; - }, - { alice }, - ); - - // Alice accepts the invite - await expect( - page.getByRole("group", { name: "Invites" }).locator(".mx_RoomSublist_tiles").getByRole("treeitem"), - ).toHaveCount(1); - await page.getByRole("treeitem", { name: "Test room" }).click(); - await page.locator(".mx_RoomView").getByRole("button", { name: "Accept" }).click(); - - // wait until we're joined and see the timeline - await expect(page.locator(`.mx_EventTile`).getByText("Alice joined the room")).toBeVisible(); - - // we should be able to jump to the decryptable message that Bob sent - await page.goto(`#/room/${roomId}/${eventId}`); - - await expect(page.locator(`.mx_EventTile`).getByText("This should be decryptable")).toBeVisible(); - }); - }); - }); }); diff --git a/playwright/e2e/crypto/decryption-failure-messages.spec.ts b/playwright/e2e/crypto/decryption-failure-messages.spec.ts new file mode 100644 index 0000000000..bcefa947ad --- /dev/null +++ b/playwright/e2e/crypto/decryption-failure-messages.spec.ts @@ -0,0 +1,302 @@ +/* +Copyright 2022-2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import type { EmittedEvents, Preset } from "matrix-js-sdk/src/matrix"; +import { expect, test } from "../../element-web-test"; +import { + createRoom, + enableKeyBackup, + logIntoElement, + logOutOfElement, + sendMessageInCurrentRoom, + verifySession, +} from "./utils"; +import { isDendrite } from "../../plugins/homeserver/dendrite"; + +test.describe("Cryptography", function () { + test.use({ + displayName: "Alice", + botCreateOpts: { + displayName: "Bob", + autoAcceptInvites: false, + }, + }); + + test.describe("decryption failure messages", () => { + test("should handle device-relative historical messages", async ({ + homeserver, + page, + app, + credentials, + user, + }) => { + test.setTimeout(60000); + + // Start with a logged-in session, without key backup, and send a message. + await createRoom(page, "Test room", true); + await sendMessageInCurrentRoom(page, "test test"); + + // Log out, discarding the key for the sent message. + await logOutOfElement(page, true); + + // Log in again, and see how the message looks. + await logIntoElement(page, homeserver, credentials); + await app.viewRoomByName("Test room"); + const lastTile = page.locator(".mx_EventTile").last(); + await expect(lastTile).toContainText("Historical messages are not available on this device"); + await expect(lastTile.locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); + + // Now, we set up key backup, and then send another message. + const secretStorageKey = await enableKeyBackup(app); + await app.viewRoomByName("Test room"); + await sendMessageInCurrentRoom(page, "test2 test2"); + + // Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for + // the key to be backed up. + await page.waitForTimeout(10000); + + // Finally, log out again, and back in, skipping verification for now, and see what we see. + await logOutOfElement(page); + await logIntoElement(page, homeserver, credentials); + await page.locator(".mx_AuthPage").getByRole("button", { name: "Skip verification for now" }).click(); + await page.locator(".mx_AuthPage").getByRole("button", { name: "I'll verify later" }).click(); + await app.viewRoomByName("Test room"); + + // There should be two historical events in the timeline + const tiles = await page.locator(".mx_EventTile").all(); + expect(tiles.length).toBeGreaterThanOrEqual(2); + // look at the last two tiles only + for (const tile of tiles.slice(-2)) { + await expect(tile).toContainText("You need to verify this device for access to historical messages"); + await expect(tile.locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); + } + + // Now verify our device (setting up key backup), and check what happens + await verifySession(app, secretStorageKey); + const tilesAfterVerify = (await page.locator(".mx_EventTile").all()).slice(-2); + + // The first message still cannot be decrypted, because it was never backed up. It's now a regular UTD though. + await expect(tilesAfterVerify[0]).toContainText("Unable to decrypt message"); + await expect(tilesAfterVerify[0].locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); + + // The second message should now be decrypted, with a grey shield + await expect(tilesAfterVerify[1]).toContainText("test2 test2"); + await expect(tilesAfterVerify[1].locator(".mx_EventTile_e2eIcon_normal")).toBeVisible(); + }); + + test.describe("non-joined historical messages", () => { + test.skip(isDendrite, "does not yet support membership on events"); + + test("should display undecryptable non-joined historical messages with a different message", async ({ + homeserver, + page, + app, + credentials: aliceCredentials, + user: alice, + bot: bob, + }) => { + // Bob creates an encrypted room and sends a message to it. He then invites Alice + const roomId = await bob.evaluate( + async (client, { alice }) => { + const encryptionStatePromise = new Promise((resolve) => { + client.on("RoomState.events" as EmittedEvents, (event, _state, _lastStateEvent) => { + if (event.getType() === "m.room.encryption") { + resolve(); + } + }); + }); + + const { room_id: roomId } = await client.createRoom({ + initial_state: [ + { + type: "m.room.encryption", + content: { + algorithm: "m.megolm.v1.aes-sha2", + }, + }, + ], + name: "Test room", + preset: "private_chat" as Preset, + }); + + // wait for m.room.encryption event, so that when we send a + // message, it will be encrypted + await encryptionStatePromise; + + await client.sendTextMessage(roomId, "This should be undecryptable"); + + await client.invite(roomId, alice.userId); + + return roomId; + }, + { alice }, + ); + + // Alice accepts the invite + await expect( + page.getByRole("group", { name: "Invites" }).locator(".mx_RoomSublist_tiles").getByRole("treeitem"), + ).toHaveCount(1); + await page.getByRole("treeitem", { name: "Test room" }).click(); + await page.locator(".mx_RoomView").getByRole("button", { name: "Accept" }).click(); + + // Bob sends an encrypted event and an undecryptable event + await bob.evaluate( + async (client, { roomId }) => { + await client.sendTextMessage(roomId, "This should be decryptable"); + await client.sendEvent( + roomId, + "m.room.encrypted" as any, + { + algorithm: "m.megolm.v1.aes-sha2", + ciphertext: "this+message+will+be+undecryptable", + device_id: client.getDeviceId()!, + sender_key: (await client.getCrypto()!.getOwnDeviceKeys()).ed25519, + session_id: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + } as any, + ); + }, + { roomId }, + ); + + // We wait for the event tiles that we expect from the messages that + // Bob sent, in sequence. + await expect( + page.locator(`.mx_EventTile`).getByText("You don't have access to this message"), + ).toBeVisible(); + await expect(page.locator(`.mx_EventTile`).getByText("This should be decryptable")).toBeVisible(); + await expect(page.locator(`.mx_EventTile`).getByText("Unable to decrypt message")).toBeVisible(); + + // And then we ensure that they are where we expect them to be + // Alice should see these event tiles: + // - first message sent by Bob (undecryptable) + // - Bob invited Alice + // - Alice joined the room + // - second message sent by Bob (decryptable) + // - third message sent by Bob (undecryptable) + const tiles = await page.locator(".mx_EventTile").all(); + expect(tiles.length).toBeGreaterThanOrEqual(5); + + // The first message from Bob was sent before Alice was in the room, so should + // be different from the standard UTD message + await expect(tiles[tiles.length - 5]).toContainText("You don't have access to this message"); + await expect(tiles[tiles.length - 5].locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); + + // The second message from Bob should be decryptable + await expect(tiles[tiles.length - 2]).toContainText("This should be decryptable"); + // this tile won't have an e2e icon since we got the key from the sender + + // The third message from Bob is undecryptable, but was sent while Alice was + // in the room and is expected to be decryptable, so this should have the + // standard UTD message + await expect(tiles[tiles.length - 1]).toContainText("Unable to decrypt message"); + await expect(tiles[tiles.length - 1].locator(".mx_EventTile_e2eIcon_decryption_failure")).toBeVisible(); + }); + + test("should be able to jump to a message sent before our last join event", async ({ + homeserver, + page, + app, + credentials: aliceCredentials, + user: alice, + bot: bob, + }) => { + // Bob: + // - creates an encrypted room, + // - invites Alice, + // - sends a message to it, + // - kicks Alice, + // - sends a bunch more events + // - invites Alice again + // In this way, there will be an event that Alice can decrypt, + // followed by a bunch of undecryptable events which Alice shouldn't + // expect to be able to decrypt. The old code would have hidden all + // the events, even the decryptable event (which it wouldn't have + // even tried to fetch, if it was far enough back). + const { roomId, eventId } = await bob.evaluate( + async (client, { alice }) => { + const { room_id: roomId } = await client.createRoom({ + initial_state: [ + { + type: "m.room.encryption", + content: { + algorithm: "m.megolm.v1.aes-sha2", + }, + }, + ], + name: "Test room", + preset: "private_chat" as Preset, + }); + + // invite Alice + const inviteAlicePromise = new Promise((resolve) => { + client.on("RoomMember.membership" as EmittedEvents, (_event, member, _oldMembership?) => { + if (member.userId === alice.userId && member.membership === "invite") { + resolve(); + } + }); + }); + await client.invite(roomId, alice.userId); + // wait for the invite to come back so that we encrypt to Alice + await inviteAlicePromise; + + // send a message that Alice should be able to decrypt + const { event_id: eventId } = await client.sendTextMessage( + roomId, + "This should be decryptable", + ); + + // kick Alice + const kickAlicePromise = new Promise((resolve) => { + client.on("RoomMember.membership" as EmittedEvents, (_event, member, _oldMembership?) => { + if (member.userId === alice.userId && member.membership === "leave") { + resolve(); + } + }); + }); + await client.kick(roomId, alice.userId); + await kickAlicePromise; + + // send a bunch of messages that Alice won't be able to decrypt + for (let i = 0; i < 20; i++) { + await client.sendTextMessage(roomId, `${i}`); + } + + // invite Alice again + await client.invite(roomId, alice.userId); + + return { roomId, eventId }; + }, + { alice }, + ); + + // Alice accepts the invite + await expect( + page.getByRole("group", { name: "Invites" }).locator(".mx_RoomSublist_tiles").getByRole("treeitem"), + ).toHaveCount(1); + await page.getByRole("treeitem", { name: "Test room" }).click(); + await page.locator(".mx_RoomView").getByRole("button", { name: "Accept" }).click(); + + // wait until we're joined and see the timeline + await expect(page.locator(`.mx_EventTile`).getByText("Alice joined the room")).toBeVisible(); + + // we should be able to jump to the decryptable message that Bob sent + await page.goto(`#/room/${roomId}/${eventId}`); + + await expect(page.locator(`.mx_EventTile`).getByText("This should be decryptable")).toBeVisible(); + }); + }); + }); +}); diff --git a/playwright/e2e/crypto/verification.spec.ts b/playwright/e2e/crypto/device-verification.spec.ts similarity index 67% rename from playwright/e2e/crypto/verification.spec.ts rename to playwright/e2e/crypto/device-verification.spec.ts index 167c302b47..929da09106 100644 --- a/playwright/e2e/crypto/verification.spec.ts +++ b/playwright/e2e/crypto/device-verification.spec.ts @@ -15,19 +15,18 @@ limitations under the License. */ import jsQR from "jsqr"; -import { type Preset, type Visibility } from "matrix-js-sdk/src/matrix"; import type { JSHandle, Locator, Page } from "@playwright/test"; -import type { VerificationRequest, Verifier } from "matrix-js-sdk/src/crypto-api"; +import type { VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { test, expect } from "../../element-web-test"; import { + awaitVerifier, checkDeviceIsConnectedKeyBackup, checkDeviceIsCrossSigned, doTwoWaySasVerification, logIntoElement, waitForVerificationRequest, } from "./utils"; -import { Client } from "../../pages/client"; import { Bot } from "../../pages/bot"; test.describe("Device verification", () => { @@ -235,112 +234,6 @@ test.describe("Device verification", () => { }); }); -test.describe("User verification", () => { - // note that there are other tests that check user verification works in `crypto.spec.ts`. - - test.use({ - displayName: "Alice", - botCreateOpts: { displayName: "Bob", autoAcceptInvites: true, userIdPrefix: "bob_" }, - room: async ({ page, app, bot: bob, user: aliceCredentials }, use) => { - await app.client.bootstrapCrossSigning(aliceCredentials); - - // the other user creates a DM - const dmRoomId = await createDMRoom(bob, aliceCredentials.userId); - - // accept the DM - await app.viewRoomByName("Bob"); - await page.getByRole("button", { name: "Start chatting" }).click(); - await use({ roomId: dmRoomId }); - }, - }); - - test("can receive a verification request when there is no existing DM", async ({ - page, - bot: bob, - user: aliceCredentials, - toasts, - room: { roomId: dmRoomId }, - }) => { - // once Alice has joined, Bob starts the verification - const bobVerificationRequest = await bob.evaluateHandle( - async (client, { dmRoomId, aliceCredentials }) => { - const room = client.getRoom(dmRoomId); - while (room.getMember(aliceCredentials.userId)?.membership !== "join") { - await new Promise((resolve) => { - room.once(window.matrixcs.RoomStateEvent.Members, resolve); - }); - } - - return client.getCrypto().requestVerificationDM(aliceCredentials.userId, dmRoomId); - }, - { dmRoomId, aliceCredentials }, - ); - - // there should also be a toast - const toast = await toasts.getToast("Verification requested"); - // it should contain the details of the requesting user - await expect(toast.getByText(`Bob (${bob.credentials.userId})`)).toBeVisible(); - // Accept - await toast.getByRole("button", { name: "Verify User" }).click(); - - // request verification by emoji - await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click(); - - /* on the bot side, wait for the verifier to exist ... */ - const botVerifier = await awaitVerifier(bobVerificationRequest); - // ... confirm ... - botVerifier.evaluate((verifier) => verifier.verify()); - // ... and then check the emoji match - await doTwoWaySasVerification(page, botVerifier); - - await page.getByRole("button", { name: "They match" }).click(); - await expect(page.getByText("You've successfully verified Bob!")).toBeVisible(); - await page.getByRole("button", { name: "Got it" }).click(); - }); - - test("can abort emoji verification when emoji mismatch", async ({ - page, - bot: bob, - user: aliceCredentials, - toasts, - room: { roomId: dmRoomId }, - }) => { - // once Alice has joined, Bob starts the verification - const bobVerificationRequest = await bob.evaluateHandle( - async (client, { dmRoomId, aliceCredentials }) => { - const room = client.getRoom(dmRoomId); - while (room.getMember(aliceCredentials.userId)?.membership !== "join") { - await new Promise((resolve) => { - room.once(window.matrixcs.RoomStateEvent.Members, resolve); - }); - } - - return client.getCrypto().requestVerificationDM(aliceCredentials.userId, dmRoomId); - }, - { dmRoomId, aliceCredentials }, - ); - - // Accept verification via toast - const toast = await toasts.getToast("Verification requested"); - await toast.getByRole("button", { name: "Verify User" }).click(); - - // request verification by emoji - await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click(); - - /* on the bot side, wait for the verifier to exist ... */ - const botVerifier = await awaitVerifier(bobVerificationRequest); - // ... confirm ... - botVerifier.evaluate((verifier) => verifier.verify()).catch(() => {}); - // ... and abort the verification - await page.getByRole("button", { name: "They don't match" }).click(); - - const dialog = page.locator(".mx_Dialog"); - await expect(dialog.getByText("Your messages are not secure")).toBeVisible(); - await dialog.getByRole("button", { name: "OK" }).click(); - await expect(dialog).not.toBeVisible(); - }); -}); - /** Extract the qrcode out of an on-screen html element */ async function readQrCode(base: Locator) { const qrCode = base.locator('[alt="QR Code"]'); @@ -372,35 +265,3 @@ async function readQrCode(base: Locator) { const result = jsQR(new Uint8ClampedArray(imageData.buffer), imageData.width, imageData.height); return new Uint8Array(result.binaryData); } - -async function createDMRoom(client: Client, userId: string): Promise { - return client.createRoom({ - preset: "trusted_private_chat" as Preset, - visibility: "private" as Visibility, - invite: [userId], - is_direct: true, - initial_state: [ - { - type: "m.room.encryption", - state_key: "", - content: { - algorithm: "m.megolm.v1.aes-sha2", - }, - }, - ], - }); -} - -/** - * Wait for a verifier to exist for a VerificationRequest - * - * @param botVerificationRequest - */ -async function awaitVerifier(botVerificationRequest: JSHandle): Promise> { - return botVerificationRequest.evaluateHandle(async (verificationRequest) => { - while (!verificationRequest.verifier) { - await new Promise((r) => verificationRequest.once("change" as any, r)); - } - return verificationRequest.verifier; - }); -} diff --git a/playwright/e2e/crypto/event-shields.spec.ts b/playwright/e2e/crypto/event-shields.spec.ts new file mode 100644 index 0000000000..0de678c17c --- /dev/null +++ b/playwright/e2e/crypto/event-shields.spec.ts @@ -0,0 +1,269 @@ +/* +Copyright 2022-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 { expect, test } from "../../element-web-test"; +import { autoJoin, createSharedRoomWithUser, enableKeyBackup, logIntoElement, logOutOfElement, verify } from "./utils"; +import { Bot } from "../../pages/bot"; + +test.describe("Cryptography", function () { + test.use({ + displayName: "Alice", + botCreateOpts: { + displayName: "Bob", + autoAcceptInvites: false, + }, + }); + + test.describe("event shields", () => { + let testRoomId: string; + + test.beforeEach(async ({ page, bot: bob, user: aliceCredentials, app }) => { + await app.client.bootstrapCrossSigning(aliceCredentials); + await autoJoin(bob); + + // create an encrypted room + testRoomId = await createSharedRoomWithUser(app, bob.credentials.userId, { + name: "TestRoom", + initial_state: [ + { + type: "m.room.encryption", + state_key: "", + content: { + algorithm: "m.megolm.v1.aes-sha2", + }, + }, + ], + }); + }); + + test("should show the correct shield on e2e events", async ({ page, app, bot: bob, homeserver }) => { + // Bob has a second, not cross-signed, device + const bobSecondDevice = new Bot(page, homeserver, { + bootstrapSecretStorage: false, + bootstrapCrossSigning: false, + }); + bobSecondDevice.setCredentials( + await homeserver.loginUser(bob.credentials.userId, bob.credentials.password), + ); + await bobSecondDevice.prepareClient(); + + await bob.sendEvent(testRoomId, null, "m.room.encrypted", { + algorithm: "m.megolm.v1.aes-sha2", + ciphertext: "the bird is in the hand", + }); + + const last = page.locator(".mx_EventTile_last"); + await expect(last).toContainText("Unable to decrypt message"); + const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon"); + await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_decryption_failure/); + await lastE2eIcon.focus(); + await expect(page.getByRole("tooltip")).toContainText("This message could not be decrypted"); + + /* Should show a red padlock for an unencrypted message in an e2e room */ + await bob.evaluate( + (cli, testRoomId) => + cli.http.authedRequest( + window.matrixcs.Method.Put, + `/rooms/${encodeURIComponent(testRoomId)}/send/m.room.message/test_txn_1`, + undefined, + { + msgtype: "m.text", + body: "test unencrypted", + }, + ), + testRoomId, + ); + + await expect(last).toContainText("test unencrypted"); + await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/); + await lastE2eIcon.focus(); + await expect(page.getByRole("tooltip")).toContainText("Not encrypted"); + + /* Should show no padlock for an unverified user */ + // bob sends a valid event + await bob.sendMessage(testRoomId, "test encrypted 1"); + + // the message should appear, decrypted, with no warning, but also no "verified" + const lastTile = page.locator(".mx_EventTile_last"); + const lastTileE2eIcon = lastTile.locator(".mx_EventTile_e2eIcon"); + await expect(lastTile).toContainText("test encrypted 1"); + // no e2e icon + await expect(lastTileE2eIcon).not.toBeVisible(); + + /* Now verify Bob */ + await verify(page, bob); + + /* Existing message should be updated when user is verified. */ + await expect(last).toContainText("test encrypted 1"); + // still no e2e icon + await expect(last.locator(".mx_EventTile_e2eIcon")).not.toBeVisible(); + + /* should show no padlock, and be verified, for a message from a verified device */ + await bob.sendMessage(testRoomId, "test encrypted 2"); + + await expect(lastTile).toContainText("test encrypted 2"); + // no e2e icon + await expect(lastTileE2eIcon).not.toBeVisible(); + + /* should show red padlock for a message from an unverified device */ + await bobSecondDevice.sendMessage(testRoomId, "test encrypted from unverified"); + await expect(lastTile).toContainText("test encrypted from unverified"); + await expect(lastTileE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/); + await lastTileE2eIcon.focus(); + await expect(page.getByRole("tooltip")).toContainText("Encrypted by a device not verified by its owner."); + + /* Should show a grey padlock for a message from an unknown device */ + // bob deletes his second device + await bobSecondDevice.evaluate((cli) => cli.logout(true)); + + // wait for the logout to propagate. Workaround for https://github.com/vector-im/element-web/issues/26263 by repeatedly closing and reopening Bob's user info. + async function awaitOneDevice(iterations = 1) { + const rightPanel = page.locator(".mx_RightPanel"); + await rightPanel.getByRole("button", { name: "Room members" }).click(); + await rightPanel.getByText("Bob").click(); + const sessionCountText = await rightPanel + .locator(".mx_UserInfo_devices") + .getByText(" session", { exact: false }) + .textContent(); + // cf https://github.com/vector-im/element-web/issues/26279: Element-R uses the wrong text here + if (sessionCountText != "1 session" && sessionCountText != "1 verified session") { + if (iterations >= 10) { + throw new Error(`Bob still has ${sessionCountText} after 10 iterations`); + } + await awaitOneDevice(iterations + 1); + } + } + + await awaitOneDevice(); + + // close and reopen the room, to get the shield to update. + await app.viewRoomByName("Bob"); + await app.viewRoomByName("TestRoom"); + + await expect(last).toContainText("test encrypted from unverified"); + await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/); + await lastE2eIcon.focus(); + await expect(page.getByRole("tooltip")).toContainText("Encrypted by an unknown or deleted device."); + }); + + test("Should show a grey padlock for a key restored from backup", async ({ + page, + app, + bot: bob, + homeserver, + user: aliceCredentials, + }) => { + test.slow(); + const securityKey = await enableKeyBackup(app); + + // bob sends a valid event + await bob.sendMessage(testRoomId, "test encrypted 1"); + + const lastTile = page.locator(".mx_EventTile_last"); + const lastTileE2eIcon = lastTile.locator(".mx_EventTile_e2eIcon"); + await expect(lastTile).toContainText("test encrypted 1"); + // no e2e icon + await expect(lastTileE2eIcon).not.toBeVisible(); + + // Workaround for https://github.com/element-hq/element-web/issues/27267. It can take up to 10 seconds for + // the key to be backed up. + await page.waitForTimeout(10000); + + /* log out, and back in */ + await logOutOfElement(page); + // Reload to work around a Rust crypto bug where it can hold onto the indexeddb even after logout + // https://github.com/element-hq/element-web/issues/25779 + await page.addInitScript(() => { + // When we reload, the initScript created by the `user`/`pageWithCredentials` fixtures + // will re-inject the original credentials into localStorage, which we don't want. + // To work around, we add a second initScript which will clear localStorage again. + window.localStorage.clear(); + }); + await page.reload(); + await logIntoElement(page, homeserver, aliceCredentials, securityKey); + + /* go back to the test room and find Bob's message again */ + await app.viewRoomById(testRoomId); + await expect(lastTile).toContainText("test encrypted 1"); + // The gray shield would be a mx_EventTile_e2eIcon_normal. The red shield would be a mx_EventTile_e2eIcon_warning. + // No shield would have no div mx_EventTile_e2eIcon at all. + await expect(lastTileE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_normal/); + await lastTileE2eIcon.hover(); + // The key is coming from backup, so it is not anymore possible to establish if the claimed device + // creator of this key is authentic. The tooltip should be "The authenticity of this encrypted message can't be guaranteed on this device." + // It is not "Encrypted by an unknown or deleted device." even if the claimed device is actually deleted. + await expect(page.getByRole("tooltip")).toContainText( + "The authenticity of this encrypted message can't be guaranteed on this device.", + ); + }); + + test("should show the correct shield on edited e2e events", async ({ page, app, bot: bob, homeserver }) => { + // bob has a second, not cross-signed, device + const bobSecondDevice = new Bot(page, homeserver, { + bootstrapSecretStorage: false, + bootstrapCrossSigning: false, + }); + bobSecondDevice.setCredentials( + await homeserver.loginUser(bob.credentials.userId, bob.credentials.password), + ); + await bobSecondDevice.prepareClient(); + + // verify Bob + await verify(page, bob); + + // bob sends a valid event + const testEvent = await bob.sendMessage(testRoomId, "Hoo!"); + + // the message should appear, decrypted, with no warning + await expect( + page.locator(".mx_EventTile", { hasText: "Hoo!" }).locator(".mx_EventTile_e2eIcon_warning"), + ).not.toBeVisible(); + + // bob sends an edit to the first message with his unverified device + await bobSecondDevice.sendMessage(testRoomId, { + "m.new_content": { + msgtype: "m.text", + body: "Haa!", + }, + "m.relates_to": { + rel_type: "m.replace", + event_id: testEvent.event_id, + }, + }); + + // the edit should have a warning + await expect( + page.locator(".mx_EventTile", { hasText: "Haa!" }).locator(".mx_EventTile_e2eIcon_warning"), + ).toBeVisible(); + + // a second edit from the verified device should be ok + await bob.sendMessage(testRoomId, { + "m.new_content": { + msgtype: "m.text", + body: "Hee!", + }, + "m.relates_to": { + rel_type: "m.replace", + event_id: testEvent.event_id, + }, + }); + + await expect( + page.locator(".mx_EventTile", { hasText: "Hee!" }).locator(".mx_EventTile_e2eIcon_warning"), + ).not.toBeVisible(); + }); + }); +}); diff --git a/playwright/e2e/crypto/user-verification.spec.ts b/playwright/e2e/crypto/user-verification.spec.ts new file mode 100644 index 0000000000..eac0fb639e --- /dev/null +++ b/playwright/e2e/crypto/user-verification.spec.ts @@ -0,0 +1,145 @@ +/* +Copyright 2023 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { type Preset, type Visibility } from "matrix-js-sdk/src/matrix"; + +import { test, expect } from "../../element-web-test"; +import { doTwoWaySasVerification, awaitVerifier } from "./utils"; +import { Client } from "../../pages/client"; + +test.describe("User verification", () => { + // note that there are other tests that check user verification works in `crypto.spec.ts`. + + test.use({ + displayName: "Alice", + botCreateOpts: { displayName: "Bob", autoAcceptInvites: true, userIdPrefix: "bob_" }, + room: async ({ page, app, bot: bob, user: aliceCredentials }, use) => { + await app.client.bootstrapCrossSigning(aliceCredentials); + + // the other user creates a DM + const dmRoomId = await createDMRoom(bob, aliceCredentials.userId); + + // accept the DM + await app.viewRoomByName("Bob"); + await page.getByRole("button", { name: "Start chatting" }).click(); + await use({ roomId: dmRoomId }); + }, + }); + + test("can receive a verification request when there is no existing DM", async ({ + page, + bot: bob, + user: aliceCredentials, + toasts, + room: { roomId: dmRoomId }, + }) => { + // once Alice has joined, Bob starts the verification + const bobVerificationRequest = await bob.evaluateHandle( + async (client, { dmRoomId, aliceCredentials }) => { + const room = client.getRoom(dmRoomId); + while (room.getMember(aliceCredentials.userId)?.membership !== "join") { + await new Promise((resolve) => { + room.once(window.matrixcs.RoomStateEvent.Members, resolve); + }); + } + + return client.getCrypto().requestVerificationDM(aliceCredentials.userId, dmRoomId); + }, + { dmRoomId, aliceCredentials }, + ); + + // there should also be a toast + const toast = await toasts.getToast("Verification requested"); + // it should contain the details of the requesting user + await expect(toast.getByText(`Bob (${bob.credentials.userId})`)).toBeVisible(); + // Accept + await toast.getByRole("button", { name: "Verify User" }).click(); + + // request verification by emoji + await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click(); + + /* on the bot side, wait for the verifier to exist ... */ + const botVerifier = await awaitVerifier(bobVerificationRequest); + // ... confirm ... + botVerifier.evaluate((verifier) => verifier.verify()); + // ... and then check the emoji match + await doTwoWaySasVerification(page, botVerifier); + + await page.getByRole("button", { name: "They match" }).click(); + await expect(page.getByText("You've successfully verified Bob!")).toBeVisible(); + await page.getByRole("button", { name: "Got it" }).click(); + }); + + test("can abort emoji verification when emoji mismatch", async ({ + page, + bot: bob, + user: aliceCredentials, + toasts, + room: { roomId: dmRoomId }, + }) => { + // once Alice has joined, Bob starts the verification + const bobVerificationRequest = await bob.evaluateHandle( + async (client, { dmRoomId, aliceCredentials }) => { + const room = client.getRoom(dmRoomId); + while (room.getMember(aliceCredentials.userId)?.membership !== "join") { + await new Promise((resolve) => { + room.once(window.matrixcs.RoomStateEvent.Members, resolve); + }); + } + + return client.getCrypto().requestVerificationDM(aliceCredentials.userId, dmRoomId); + }, + { dmRoomId, aliceCredentials }, + ); + + // Accept verification via toast + const toast = await toasts.getToast("Verification requested"); + await toast.getByRole("button", { name: "Verify User" }).click(); + + // request verification by emoji + await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click(); + + /* on the bot side, wait for the verifier to exist ... */ + const botVerifier = await awaitVerifier(bobVerificationRequest); + // ... confirm ... + botVerifier.evaluate((verifier) => verifier.verify()).catch(() => {}); + // ... and abort the verification + await page.getByRole("button", { name: "They don't match" }).click(); + + const dialog = page.locator(".mx_Dialog"); + await expect(dialog.getByText("Your messages are not secure")).toBeVisible(); + await dialog.getByRole("button", { name: "OK" }).click(); + await expect(dialog).not.toBeVisible(); + }); +}); + +async function createDMRoom(client: Client, userId: string): Promise { + return client.createRoom({ + preset: "trusted_private_chat" as Preset, + visibility: "private" as Visibility, + invite: [userId], + is_direct: true, + initial_state: [ + { + type: "m.room.encryption", + state_key: "", + content: { + algorithm: "m.megolm.v1.aes-sha2", + }, + }, + ], + }); +} diff --git a/playwright/e2e/crypto/utils.ts b/playwright/e2e/crypto/utils.ts index b5109490a9..c4042d43e8 100644 --- a/playwright/e2e/crypto/utils.ts +++ b/playwright/e2e/crypto/utils.ts @@ -27,6 +27,7 @@ import type { import { Credentials, HomeserverInstance } from "../../plugins/homeserver"; import { Client } from "../../pages/client"; import { ElementAppPage } from "../../pages/ElementAppPage"; +import { Bot } from "../../pages/bot"; /** * wait for the given client to receive an incoming verification request, and automatically accept it @@ -327,3 +328,68 @@ export async function createRoom(page: Page, roomName: string, isEncrypted: bool await expect(page.getByText("Encryption enabled")).toBeVisible(); } } + +/** + * Open the room info panel and return the panel element + * @param page - the page to use + */ +export const openRoomInfo = async (page: Page) => { + await page.getByRole("button", { name: "Room info" }).click(); + return page.locator(".mx_RightPanel"); +}; + +/** + * Configure the given MatrixClient to auto-accept any invites + * @param client - the client to configure + */ +export async function autoJoin(client: Client) { + await client.evaluate((cli) => { + cli.on(window.matrixcs.RoomMemberEvent.Membership, (event, member) => { + if (member.membership === "invite" && member.userId === cli.getUserId()) { + cli.joinRoom(member.roomId); + } + }); + }); +} + +/** + * Verify a user by emoji + * @param page - the page to use + * @param bob - the user to verify + */ +export const verify = async (page: Page, bob: Bot) => { + const bobsVerificationRequestPromise = waitForVerificationRequest(bob); + + const roomInfo = await openRoomInfo(page); + await page.locator(".mx_RightPanelTabs").getByText("People").click(); + await roomInfo.getByText("Bob").click(); + await roomInfo.getByRole("button", { name: "Verify" }).click(); + await roomInfo.getByRole("button", { name: "Start Verification" }).click(); + + // this requires creating a DM, so can take a while. Give it a longer timeout. + await roomInfo.getByRole("button", { name: "Verify by emoji" }).click({ timeout: 30000 }); + + const request = await bobsVerificationRequestPromise; + // the bot user races with the Element user to hit the "verify by emoji" button + const verifier = await request.evaluateHandle((request) => request.startVerification("m.sas.v1")); + await doTwoWaySasVerification(page, verifier); + await roomInfo.getByRole("button", { name: "They match" }).click(); + await expect(roomInfo.getByText("You've successfully verified Bob!")).toBeVisible(); + await roomInfo.getByRole("button", { name: "Got it" }).click(); +}; + +/** + * Wait for a verifier to exist for a VerificationRequest + * + * @param botVerificationRequest + */ +export async function awaitVerifier( + botVerificationRequest: JSHandle, +): Promise> { + return botVerificationRequest.evaluateHandle(async (verificationRequest) => { + while (!verificationRequest.verifier) { + await new Promise((r) => verificationRequest.once("change" as any, r)); + } + return verificationRequest.verifier; + }); +} diff --git a/playwright/e2e/read-receipts/editing-messages-in-threads.spec.ts b/playwright/e2e/read-receipts/editing-messages-in-threads.spec.ts new file mode 100644 index 0000000000..62394cccb5 --- /dev/null +++ b/playwright/e2e/read-receipts/editing-messages-in-threads.spec.ts @@ -0,0 +1,191 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("editing messages", () => { + test.describe("in threads", () => { + test("An edit of a threaded message makes the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given we have read the thread + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.assertReadThread("Resp1"); + await util.goTo(room1); + + // When a message inside it is edited + await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); + + // Then the room and thread are read + await util.assertStillRead(room2); + await util.goTo(room2); + await util.assertReadThread("Msg1"); + }); + + test("Reading an edit of a threaded message makes the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an edited thread message appears after we read it + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.assertReadThread("Resp1"); + await util.goTo(room1); + await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); + await util.assertStillRead(room2); + + // When I read it + await util.goTo(room2); + await util.openThread("Msg1"); + + // Then the room and thread are still read + await util.assertStillRead(room2); + await util.assertReadThread("Msg1"); + }); + + test("Marking a room as read after an edit in a thread makes it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an edit in a thread is making the room unread + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Msg1", + msg.threadedOff("Msg1", "Resp1"), + msg.editOf("Resp1", "Edit1"), + ]); + await util.assertUnread(room2, 1); + + // When I mark the room as read + await util.markAsRead(room2); + + // Then it is read + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + }); + + test("Editing a thread message after marking as read leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a room is marked as read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.assertUnread(room2, 1); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When a message is edited + await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); + + // Then the room remains read + await util.assertStillRead(room2); + await util.assertReadThread("Msg1"); + }); + + test("A room with an edited threaded message is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an edit in a thread is leaving a room read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.markAsRead(room2); + await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); + await util.assertStillRead(room2); + + // When I restart + await util.saveAndReload(); + + // Then is it still read + await util.assertRead(room2); + }); + + test("A room where all threaded edits are read is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.assertUnread(room2, 1); + await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); + await util.assertUnread(room2, 1); + + await util.goTo(room2); + + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + await util.goTo(room1); // Make sure we are looking at room1 after reload + await util.assertStillRead(room2); + + await util.saveAndReload(); + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + }); + + test("A room where all threaded edits are marked as read is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Msg1", + msg.threadedOff("Msg1", "Resp1"), + msg.editOf("Resp1", "Edit1"), + ]); + await util.assertUnread(room2, 1); + await util.markAsRead(room2); + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + + // When I restart + await util.saveAndReload(); + + // It is still read + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/editing-messages-main-timeline.spec.ts b/playwright/e2e/read-receipts/editing-messages-main-timeline.spec.ts new file mode 100644 index 0000000000..e03a011a4d --- /dev/null +++ b/playwright/e2e/read-receipts/editing-messages-main-timeline.spec.ts @@ -0,0 +1,180 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("editing messages", () => { + test.describe("in the main timeline", () => { + test("Editing a message leaves a room read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { + // Given I am not looking at the room + await util.goTo(room1); + + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + // When an edit appears in the room + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); + + // Then it remains read + await util.assertStillRead(room2); + }); + test("Reading an edit leaves the room read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { + // Given an edit is making the room unread + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); + await util.assertStillRead(room2); + + // When I read it + await util.goTo(room2); + + // Then the room stays read + await util.assertStillRead(room2); + await util.goTo(room1); + await util.assertStillRead(room2); + }); + test("Editing a message after marking as read leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given the room is marked as read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When a message is edited + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); + + // Then the room remains read + await util.assertStillRead(room2); + }); + test("Editing a reply after reading it makes the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given the room is all read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.replyTo("Msg1", "Reply1")]); + await util.assertUnread(room2, 2); + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + // When a message is edited + await util.receiveMessages(room2, [msg.editOf("Reply1", "Reply1 Edit1")]); + + // Then it remains read + await util.assertStillRead(room2); + }); + test("Editing a reply after marking as read makes the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a reply is marked as read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.replyTo("Msg1", "Reply1")]); + await util.assertUnread(room2, 2); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When the reply is edited + await util.receiveMessages(room2, [msg.editOf("Reply1", "Reply1 Edit1")]); + + // Then the room remains read + await util.assertStillRead(room2); + }); + test("A room with an edit is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a message is marked as read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When an edit appears in the room + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); + + // Then it remains read + await util.assertStillRead(room2); + + // And remains so after a reload + await util.saveAndReload(); + await util.assertStillRead(room2); + }); + test("An edited message becomes read if it happens while I am looking", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a message is marked as read + await util.goTo(room2); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertRead(room2); + + // When I see an edit appear in the room I am looking at + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); + + // Then it becomes read + await util.assertStillRead(room2); + }); + test("A room where all edits are read is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a message was edited and read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.editOf("Msg1", "Msg1 Edit1")]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.assertRead(room2); + + // When I reload + await util.saveAndReload(); + + // Then the room is still read + await util.assertRead(room2); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/editing-messages-thread-roots.spec.ts b/playwright/e2e/read-receipts/editing-messages-thread-roots.spec.ts new file mode 100644 index 0000000000..279845f5d2 --- /dev/null +++ b/playwright/e2e/read-receipts/editing-messages-thread-roots.spec.ts @@ -0,0 +1,179 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("editing messages", () => { + test.describe("thread roots", () => { + test("An edit of a thread root leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I have read a thread + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Msg1"); + await util.backToThreadsList(); + await util.assertRead(room2); + await util.goTo(room1); + + // When the thread root is edited + await util.receiveMessages(room2, [msg.editOf("Msg1", "Edit1")]); + + // Then the room is read + await util.assertStillRead(room2); + + // And the thread is read + await util.goTo(room2); + await util.assertStillRead(room2); + await util.assertReadThread("Edit1"); + }); + + test("Reading an edit of a thread root leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a fully-read thread exists + await util.goTo(room2); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.goTo(room1); + await util.assertRead(room2); + + // When the thread root is edited + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); + + // And I read that edit + await util.goTo(room2); + + // Then the room becomes read and stays read + await util.assertStillRead(room2); + await util.goTo(room1); + await util.assertStillRead(room2); + }); + + test("Editing a thread root after reading leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a fully-read thread exists + await util.goTo(room2); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.goTo(room1); + + // When the thread root is edited + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); + + // Then the room stays read + await util.assertStillRead(room2); + }); + + test("Marking a room as read after an edit of a thread root keeps it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a fully-read thread exists + await util.goTo(room2); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.goTo(room1); + await util.assertRead(room2); + + // When the thread root is edited (and I receive another message + // to allow Mark as read) + await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1"), "Msg2"]); + + // And when I mark the room as read + await util.markAsRead(room2); + + // Then the room becomes read and stays read + await util.assertStillRead(room2); + await util.goTo(room1); + await util.assertStillRead(room2); + }); + + test("Editing a thread root that is a reply after marking as read leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread based on a reply exists and is read because it is marked as read + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Msg", + msg.replyTo("Msg", "Reply"), + msg.threadedOff("Reply", "InThread"), + ]); + await util.assertUnread(room2, 2); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When I edit the thread root + await util.receiveMessages(room2, [msg.editOf("Reply", "Edited Reply")]); + + // Then the room is read + await util.assertStillRead(room2); + + // And the thread is read + await util.goTo(room2); + await util.assertReadThread("Edited Reply"); + }); + + test("Marking a room as read after an edit of a thread root that is a reply leaves it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread based on a reply exists and the reply has been edited + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Msg", + msg.replyTo("Msg", "Reply"), + msg.threadedOff("Reply", "InThread"), + ]); + await util.receiveMessages(room2, [msg.editOf("Reply", "Edited Reply")]); + await util.assertUnread(room2, 2); + + // When I mark the room as read + await util.markAsRead(room2); + + // Then the room and thread are read + await util.assertStillRead(room2); + await util.goTo(room2); + await util.assertReadThread("Edited Reply"); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/editing-messages.spec.ts b/playwright/e2e/read-receipts/editing-messages.spec.ts deleted file mode 100644 index 5005ad62bf..0000000000 --- a/playwright/e2e/read-receipts/editing-messages.spec.ts +++ /dev/null @@ -1,504 +0,0 @@ -/* -Copyright 2023 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. -*/ - -/* See readme.md for tips on writing these tests. */ - -import { test } from "."; - -test.describe("Read receipts", () => { - test.describe("editing messages", () => { - test.describe("in the main timeline", () => { - test("Editing a message leaves a room read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { - // Given I am not looking at the room - await util.goTo(room1); - - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - // When an edit appears in the room - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); - - // Then it remains read - await util.assertStillRead(room2); - }); - test("Reading an edit leaves the room read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { - // Given an edit is making the room unread - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); - await util.assertStillRead(room2); - - // When I read it - await util.goTo(room2); - - // Then the room stays read - await util.assertStillRead(room2); - await util.goTo(room1); - await util.assertStillRead(room2); - }); - test("Editing a message after marking as read leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given the room is marked as read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When a message is edited - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); - - // Then the room remains read - await util.assertStillRead(room2); - }); - test("Editing a reply after reading it makes the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given the room is all read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.replyTo("Msg1", "Reply1")]); - await util.assertUnread(room2, 2); - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - // When a message is edited - await util.receiveMessages(room2, [msg.editOf("Reply1", "Reply1 Edit1")]); - - // Then it remains read - await util.assertStillRead(room2); - }); - test("Editing a reply after marking as read makes the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a reply is marked as read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.replyTo("Msg1", "Reply1")]); - await util.assertUnread(room2, 2); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When the reply is edited - await util.receiveMessages(room2, [msg.editOf("Reply1", "Reply1 Edit1")]); - - // Then the room remains read - await util.assertStillRead(room2); - }); - test("A room with an edit is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a message is marked as read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When an edit appears in the room - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); - - // Then it remains read - await util.assertStillRead(room2); - - // And remains so after a reload - await util.saveAndReload(); - await util.assertStillRead(room2); - }); - test("An edited message becomes read if it happens while I am looking", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a message is marked as read - await util.goTo(room2); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertRead(room2); - - // When I see an edit appear in the room I am looking at - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); - - // Then it becomes read - await util.assertStillRead(room2); - }); - test("A room where all edits are read is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a message was edited and read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.editOf("Msg1", "Msg1 Edit1")]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.assertRead(room2); - - // When I reload - await util.saveAndReload(); - - // Then the room is still read - await util.assertRead(room2); - }); - }); - - test.describe("in threads", () => { - test("An edit of a threaded message makes the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given we have read the thread - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.assertReadThread("Resp1"); - await util.goTo(room1); - - // When a message inside it is edited - await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); - - // Then the room and thread are read - await util.assertStillRead(room2); - await util.goTo(room2); - await util.assertReadThread("Msg1"); - }); - - test("Reading an edit of a threaded message makes the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an edited thread message appears after we read it - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.assertReadThread("Resp1"); - await util.goTo(room1); - await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); - await util.assertStillRead(room2); - - // When I read it - await util.goTo(room2); - await util.openThread("Msg1"); - - // Then the room and thread are still read - await util.assertStillRead(room2); - await util.assertReadThread("Msg1"); - }); - - test("Marking a room as read after an edit in a thread makes it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an edit in a thread is making the room unread - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Msg1", - msg.threadedOff("Msg1", "Resp1"), - msg.editOf("Resp1", "Edit1"), - ]); - await util.assertUnread(room2, 1); - - // When I mark the room as read - await util.markAsRead(room2); - - // Then it is read - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - }); - - test("Editing a thread message after marking as read leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a room is marked as read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.assertUnread(room2, 1); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When a message is edited - await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); - - // Then the room remains read - await util.assertStillRead(room2); - await util.assertReadThread("Msg1"); - }); - - test("A room with an edited threaded message is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an edit in a thread is leaving a room read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.markAsRead(room2); - await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); - await util.assertStillRead(room2); - - // When I restart - await util.saveAndReload(); - - // Then is it still read - await util.assertRead(room2); - }); - - test("A room where all threaded edits are read is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.assertUnread(room2, 1); - await util.receiveMessages(room2, [msg.editOf("Resp1", "Edit1")]); - await util.assertUnread(room2, 1); - - await util.goTo(room2); - - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - await util.goTo(room1); // Make sure we are looking at room1 after reload - await util.assertStillRead(room2); - - await util.saveAndReload(); - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - }); - - test("A room where all threaded edits are marked as read is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Msg1", - msg.threadedOff("Msg1", "Resp1"), - msg.editOf("Resp1", "Edit1"), - ]); - await util.assertUnread(room2, 1); - await util.markAsRead(room2); - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - - // When I restart - await util.saveAndReload(); - - // It is still read - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - }); - }); - - test.describe("thread roots", () => { - test("An edit of a thread root leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I have read a thread - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Msg1"); - await util.backToThreadsList(); - await util.assertRead(room2); - await util.goTo(room1); - - // When the thread root is edited - await util.receiveMessages(room2, [msg.editOf("Msg1", "Edit1")]); - - // Then the room is read - await util.assertStillRead(room2); - - // And the thread is read - await util.goTo(room2); - await util.assertStillRead(room2); - await util.assertReadThread("Edit1"); - }); - - test("Reading an edit of a thread root leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a fully-read thread exists - await util.goTo(room2); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.goTo(room1); - await util.assertRead(room2); - - // When the thread root is edited - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); - - // And I read that edit - await util.goTo(room2); - - // Then the room becomes read and stays read - await util.assertStillRead(room2); - await util.goTo(room1); - await util.assertStillRead(room2); - }); - - test("Editing a thread root after reading leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a fully-read thread exists - await util.goTo(room2); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.goTo(room1); - - // When the thread root is edited - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1")]); - - // Then the room stays read - await util.assertStillRead(room2); - }); - - test("Marking a room as read after an edit of a thread root keeps it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a fully-read thread exists - await util.goTo(room2); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.goTo(room1); - await util.assertRead(room2); - - // When the thread root is edited (and I receive another message - // to allow Mark as read) - await util.receiveMessages(room2, [msg.editOf("Msg1", "Msg1 Edit1"), "Msg2"]); - - // And when I mark the room as read - await util.markAsRead(room2); - - // Then the room becomes read and stays read - await util.assertStillRead(room2); - await util.goTo(room1); - await util.assertStillRead(room2); - }); - - test("Editing a thread root that is a reply after marking as read leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread based on a reply exists and is read because it is marked as read - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Msg", - msg.replyTo("Msg", "Reply"), - msg.threadedOff("Reply", "InThread"), - ]); - await util.assertUnread(room2, 2); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When I edit the thread root - await util.receiveMessages(room2, [msg.editOf("Reply", "Edited Reply")]); - - // Then the room is read - await util.assertStillRead(room2); - - // And the thread is read - await util.goTo(room2); - await util.assertReadThread("Edited Reply"); - }); - - test("Marking a room as read after an edit of a thread root that is a reply leaves it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread based on a reply exists and the reply has been edited - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Msg", - msg.replyTo("Msg", "Reply"), - msg.threadedOff("Reply", "InThread"), - ]); - await util.receiveMessages(room2, [msg.editOf("Reply", "Edited Reply")]); - await util.assertUnread(room2, 2); - - // When I mark the room as read - await util.markAsRead(room2); - - // Then the room and thread are read - await util.assertStillRead(room2); - await util.goTo(room2); - await util.assertReadThread("Edited Reply"); - }); - }); - }); -}); diff --git a/playwright/e2e/read-receipts/high-level.spec.ts b/playwright/e2e/read-receipts/high-level.spec.ts index 30a3788e3e..a3c2c0de3d 100644 --- a/playwright/e2e/read-receipts/high-level.spec.ts +++ b/playwright/e2e/read-receipts/high-level.spec.ts @@ -19,77 +19,6 @@ limitations under the License. import { customEvent, many, test } from "."; test.describe("Read receipts", () => { - test.describe("Message ordering", () => { - test.describe("in the main timeline", () => { - test.fixme( - "A receipt for the last event in sync order (even with wrong ts) marks a room as read", - () => {}, - ); - test.fixme( - "A receipt for a non-last event in sync order (even when ts makes it last) leaves room unread", - () => {}, - ); - }); - - test.describe("in threads", () => { - // These don't pass yet - we need MSC4033 - we don't even know the Sync order yet - test.fixme( - "A receipt for the last event in sync order (even with wrong ts) marks a thread as read", - () => {}, - ); - test.fixme( - "A receipt for a non-last event in sync order (even when ts makes it last) leaves thread unread", - () => {}, - ); - - // These pass now and should not later - we should use order from MSC4033 instead of ts - // These are broken out - test.fixme( - "A receipt for last threaded event in ts order (even when it was received non-last) marks a thread as read", - () => {}, - ); - test.fixme( - "A receipt for non-last threaded event in ts order (even when it was received last) leaves thread unread", - () => {}, - ); - test.fixme( - "A receipt for last threaded edit in ts order (even when it was received non-last) marks a thread as read", - () => {}, - ); - test.fixme( - "A receipt for non-last threaded edit in ts order (even when it was received last) leaves thread unread", - () => {}, - ); - test.fixme( - "A receipt for last threaded reaction in ts order (even when it was received non-last) marks a thread as read", - () => {}, - ); - test.fixme( - "A receipt for non-last threaded reaction in ts order (even when it was received last) leaves thread unread", - () => {}, - ); - }); - - test.describe("thread roots", () => { - test.fixme( - "A receipt for last reaction to thread root in sync order (even when ts makes it last) marks room as read", - () => {}, - ); - test.fixme( - "A receipt for non-last reaction to thread root in sync order (even when ts makes it last) leaves room unread", - () => {}, - ); - test.fixme( - "A receipt for last edit to thread root in sync order (even when ts makes it last) marks room as read", - () => {}, - ); - test.fixme( - "A receipt for non-last edit to thread root in sync order (even when ts makes it last) leaves room unread", - () => {}, - ); - }); - }); - test.describe("Ignored events", () => { test("If all events after receipt are unimportant, the room is read", async ({ roomAlpha: room1, @@ -414,79 +343,4 @@ test.describe("Read receipts", () => { await util.assertReadThread("Root3"); }); }); - - test.describe("Room list order", () => { - test("Rooms with unread messages appear at the top of room list if 'unread first' is selected", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - page, - }) => { - await util.goTo(room2); - - // Display the unread first room - await util.toggleRoomUnreadOrder(); - await util.receiveMessages(room1, ["Msg1"]); - await page.reload(); - - // Room 1 has an unread message and should be displayed first - await util.assertRoomListOrder([room1, room2]); - }); - - test("Rooms with unread threads appear at the top of room list if 'unread first' is selected", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - await util.goTo(room2); - await util.receiveMessages(room1, ["Msg1"]); - await util.markAsRead(room1); - await util.assertRead(room1); - - // Display the unread first room - await util.toggleRoomUnreadOrder(); - await util.receiveMessages(room1, [msg.threadedOff("Msg1", "Resp1")]); - await util.saveAndReload(); - - // Room 1 has an unread message and should be displayed first - await util.assertRoomListOrder([room1, room2]); - }); - }); - - test.describe("Notifications", () => { - test.describe("in the main timeline", () => { - test.fixme("A new message that mentions me shows a notification", () => {}); - test.fixme( - "Reading a notifying message reduces the notification count in the room list, space and tab", - () => {}, - ); - test.fixme( - "Reading the last notifying message removes the notification marker from room list, space and tab", - () => {}, - ); - test.fixme("Editing a message to mentions me shows a notification", () => {}); - test.fixme("Reading the last notifying edited message removes the notification marker", () => {}); - test.fixme("Redacting a notifying message removes the notification marker", () => {}); - }); - - test.describe("in threads", () => { - test.fixme("A new threaded message that mentions me shows a notification", () => {}); - test.fixme("Reading a notifying threaded message removes the notification count", () => {}); - test.fixme( - "Notification count remains steady when reading threads that contain seen notifications", - () => {}, - ); - test.fixme( - "Notification count remains steady when paging up thread view even when threads contain seen notifications", - () => {}, - ); - test.fixme( - "Notification count remains steady when paging up thread view after mark as unread even if older threads contain notifications", - () => {}, - ); - test.fixme("Redacting a notifying threaded message removes the notification marker", () => {}); - }); - }); }); diff --git a/playwright/e2e/read-receipts/message-ordering.spec.ts b/playwright/e2e/read-receipts/message-ordering.spec.ts new file mode 100644 index 0000000000..73c640d35a --- /dev/null +++ b/playwright/e2e/read-receipts/message-ordering.spec.ts @@ -0,0 +1,92 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("Message ordering", () => { + test.describe("in the main timeline", () => { + test.fixme( + "A receipt for the last event in sync order (even with wrong ts) marks a room as read", + () => {}, + ); + test.fixme( + "A receipt for a non-last event in sync order (even when ts makes it last) leaves room unread", + () => {}, + ); + }); + + test.describe("in threads", () => { + // These don't pass yet - we need MSC4033 - we don't even know the Sync order yet + test.fixme( + "A receipt for the last event in sync order (even with wrong ts) marks a thread as read", + () => {}, + ); + test.fixme( + "A receipt for a non-last event in sync order (even when ts makes it last) leaves thread unread", + () => {}, + ); + + // These pass now and should not later - we should use order from MSC4033 instead of ts + // These are broken out + test.fixme( + "A receipt for last threaded event in ts order (even when it was received non-last) marks a thread as read", + () => {}, + ); + test.fixme( + "A receipt for non-last threaded event in ts order (even when it was received last) leaves thread unread", + () => {}, + ); + test.fixme( + "A receipt for last threaded edit in ts order (even when it was received non-last) marks a thread as read", + () => {}, + ); + test.fixme( + "A receipt for non-last threaded edit in ts order (even when it was received last) leaves thread unread", + () => {}, + ); + test.fixme( + "A receipt for last threaded reaction in ts order (even when it was received non-last) marks a thread as read", + () => {}, + ); + test.fixme( + "A receipt for non-last threaded reaction in ts order (even when it was received last) leaves thread unread", + () => {}, + ); + }); + + test.describe("thread roots", () => { + test.fixme( + "A receipt for last reaction to thread root in sync order (even when ts makes it last) marks room as read", + () => {}, + ); + test.fixme( + "A receipt for non-last reaction to thread root in sync order (even when ts makes it last) leaves room unread", + () => {}, + ); + test.fixme( + "A receipt for last edit to thread root in sync order (even when ts makes it last) marks room as read", + () => {}, + ); + test.fixme( + "A receipt for non-last edit to thread root in sync order (even when ts makes it last) leaves room unread", + () => {}, + ); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/new-messages.spec.ts b/playwright/e2e/read-receipts/new-messages-in-threads.spec.ts similarity index 55% rename from playwright/e2e/read-receipts/new-messages.spec.ts rename to playwright/e2e/read-receipts/new-messages-in-threads.spec.ts index 97308a4bb2..37b43bae1d 100644 --- a/playwright/e2e/read-receipts/new-messages.spec.ts +++ b/playwright/e2e/read-receipts/new-messages-in-threads.spec.ts @@ -20,151 +20,6 @@ import { many, test } from "."; test.describe("Read receipts", () => { test.describe("new messages", () => { - test.describe("in the main timeline", () => { - test("Receiving a message makes a room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I am in a different room - await util.goTo(room1); - await util.assertRead(room2); - - // When I receive some messages - await util.receiveMessages(room2, ["Msg1"]); - - // Then the room is marked as unread - await util.assertUnread(room2, 1); - }); - test("Reading latest message makes the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I have some unread messages - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - - // When I read the main timeline - await util.goTo(room2); - - // Then the room becomes read - await util.assertRead(room2); - }); - test("Reading an older message leaves the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given there are lots of messages in a room - await util.goTo(room1); - await util.receiveMessages(room2, many("Msg", 30)); - await util.assertUnread(room2, 30); - - // When I jump to one of the older messages - await msg.jumpTo(room2.name, "Msg0001"); - - // Then the room is still unread, but some messages were read - await util.assertUnreadLessThan(room2, 30); - }); - test("Marking a room as read makes it read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { - // Given I have some unread messages - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - - // When I mark the room as read - await util.markAsRead(room2); - - // Then it is read - await util.assertRead(room2); - }); - test("Receiving a new message after marking as read makes it unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I have marked my messages as read - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When I receive a new message - await util.receiveMessages(room2, ["Msg2"]); - - // Then the room is unread - await util.assertUnread(room2, 1); - }); - test("A room with a new message is still unread after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I have an unread message - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - - // When I restart - await util.saveAndReload(); - - // Then I still have an unread message - await util.assertUnread(room2, 1); - }); - test("A room where all messages are read is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I have read all messages - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.assertRead(room2); - - // When I restart - await util.saveAndReload(); - - // Then all messages are still read - await util.assertRead(room2); - }); - test("A room that was marked as read is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I have marked all messages as read - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1"]); - await util.assertUnread(room2, 1); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When I restart - await util.saveAndReload(); - - // Then all messages are still read - await util.assertRead(room2); - }); - }); - test.describe("in threads", () => { test("Receiving a message makes a room unread", async ({ roomAlpha: room1, @@ -450,100 +305,5 @@ test.describe("Read receipts", () => { await util.assertReadThread("Msg1"); }); }); - - test.describe("thread roots", () => { - test("Reading a thread root does not mark the thread as read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread exists - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); - await util.assertUnread(room2, 1); // (Sanity) - - // When I read the main timeline - await util.goTo(room2); - - // Then room doesn't appear unread but the thread does - await util.assertRead(room2); - await util.assertUnreadThread("Msg1"); - }); - - test("Reading a thread root within the thread view marks it as read in the main timeline", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given lots of messages are on the main timeline, and one has a thread off it - await util.goTo(room1); - await util.receiveMessages(room2, [ - ...many("beforeThread", 30), - "ThreadRoot", - msg.threadedOff("ThreadRoot", "InThread"), - ...many("afterThread", 30), - ]); - await util.assertUnread(room2, 61); // Sanity - - // When I jump to an old message and read the thread - await msg.jumpTo(room2.name, "beforeThread0000"); - // When the thread is opened, the timeline is scrolled until the thread root reached the center - await util.openThread("ThreadRoot"); - - // Then the thread root is marked as read in the main timeline, - // 30 remaining messages are unread - 7 messages are displayed under the thread root - await util.assertUnread(room2, 30 - 7); - }); - - test("Creating a new thread based on a reply makes the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a message and reply exist and are read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", msg.replyTo("Msg1", "Reply1")]); - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - await util.assertRead(room2); - - // When I receive a thread message created on the reply - await util.receiveMessages(room2, [msg.threadedOff("Reply1", "Resp1")]); - - // Then the thread is unread - await util.goTo(room2); - await util.assertUnreadThread("Reply1"); - }); - - test("Reading a thread whose root is a reply makes the thread read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an unread thread off a reply exists - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Msg1", - msg.replyTo("Msg1", "Reply1"), - msg.threadedOff("Reply1", "Resp1"), - ]); - await util.assertUnread(room2, 2); - await util.goTo(room2); - await util.assertRead(room2); - await util.assertUnreadThread("Reply1"); - - // When I read the thread - await util.openThread("Reply1"); - - // Then the room and thread are read - await util.assertRead(room2); - await util.assertReadThread("Reply1"); - }); - }); }); }); diff --git a/playwright/e2e/read-receipts/new-messages-main-timeline.spec.ts b/playwright/e2e/read-receipts/new-messages-main-timeline.spec.ts new file mode 100644 index 0000000000..eb528f2816 --- /dev/null +++ b/playwright/e2e/read-receipts/new-messages-main-timeline.spec.ts @@ -0,0 +1,168 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { many, test } from "."; + +test.describe("Read receipts", () => { + test.describe("new messages", () => { + test.describe("in the main timeline", () => { + test("Receiving a message makes a room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I am in a different room + await util.goTo(room1); + await util.assertRead(room2); + + // When I receive some messages + await util.receiveMessages(room2, ["Msg1"]); + + // Then the room is marked as unread + await util.assertUnread(room2, 1); + }); + test("Reading latest message makes the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I have some unread messages + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + + // When I read the main timeline + await util.goTo(room2); + + // Then the room becomes read + await util.assertRead(room2); + }); + test("Reading an older message leaves the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given there are lots of messages in a room + await util.goTo(room1); + await util.receiveMessages(room2, many("Msg", 30)); + await util.assertUnread(room2, 30); + + // When I jump to one of the older messages + await msg.jumpTo(room2.name, "Msg0001"); + + // Then the room is still unread, but some messages were read + await util.assertUnreadLessThan(room2, 30); + }); + test("Marking a room as read makes it read", async ({ roomAlpha: room1, roomBeta: room2, util, msg }) => { + // Given I have some unread messages + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + + // When I mark the room as read + await util.markAsRead(room2); + + // Then it is read + await util.assertRead(room2); + }); + test("Receiving a new message after marking as read makes it unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I have marked my messages as read + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When I receive a new message + await util.receiveMessages(room2, ["Msg2"]); + + // Then the room is unread + await util.assertUnread(room2, 1); + }); + test("A room with a new message is still unread after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I have an unread message + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + + // When I restart + await util.saveAndReload(); + + // Then I still have an unread message + await util.assertUnread(room2, 1); + }); + test("A room where all messages are read is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I have read all messages + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.assertRead(room2); + + // When I restart + await util.saveAndReload(); + + // Then all messages are still read + await util.assertRead(room2); + }); + test("A room that was marked as read is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I have marked all messages as read + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1"]); + await util.assertUnread(room2, 1); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When I restart + await util.saveAndReload(); + + // Then all messages are still read + await util.assertRead(room2); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/new-messages-thread-roots.spec.ts b/playwright/e2e/read-receipts/new-messages-thread-roots.spec.ts new file mode 100644 index 0000000000..526bac4bff --- /dev/null +++ b/playwright/e2e/read-receipts/new-messages-thread-roots.spec.ts @@ -0,0 +1,118 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { many, test } from "."; + +test.describe("Read receipts", () => { + test.describe("new messages", () => { + test.describe("thread roots", () => { + test("Reading a thread root does not mark the thread as read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread exists + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Resp1")]); + await util.assertUnread(room2, 1); // (Sanity) + + // When I read the main timeline + await util.goTo(room2); + + // Then room doesn't appear unread but the thread does + await util.assertRead(room2); + await util.assertUnreadThread("Msg1"); + }); + + test("Reading a thread root within the thread view marks it as read in the main timeline", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given lots of messages are on the main timeline, and one has a thread off it + await util.goTo(room1); + await util.receiveMessages(room2, [ + ...many("beforeThread", 30), + "ThreadRoot", + msg.threadedOff("ThreadRoot", "InThread"), + ...many("afterThread", 30), + ]); + await util.assertUnread(room2, 61); // Sanity + + // When I jump to an old message and read the thread + await msg.jumpTo(room2.name, "beforeThread0000"); + // When the thread is opened, the timeline is scrolled until the thread root reached the center + await util.openThread("ThreadRoot"); + + // Then the thread root is marked as read in the main timeline, + // 30 remaining messages are unread - 7 messages are displayed under the thread root + await util.assertUnread(room2, 30 - 7); + }); + + test("Creating a new thread based on a reply makes the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a message and reply exist and are read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", msg.replyTo("Msg1", "Reply1")]); + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + await util.assertRead(room2); + + // When I receive a thread message created on the reply + await util.receiveMessages(room2, [msg.threadedOff("Reply1", "Resp1")]); + + // Then the thread is unread + await util.goTo(room2); + await util.assertUnreadThread("Reply1"); + }); + + test("Reading a thread whose root is a reply makes the thread read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an unread thread off a reply exists + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Msg1", + msg.replyTo("Msg1", "Reply1"), + msg.threadedOff("Reply1", "Resp1"), + ]); + await util.assertUnread(room2, 2); + await util.goTo(room2); + await util.assertRead(room2); + await util.assertUnreadThread("Reply1"); + + // When I read the thread + await util.openThread("Reply1"); + + // Then the room and thread are read + await util.assertRead(room2); + await util.assertReadThread("Reply1"); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/notifications.spec.ts b/playwright/e2e/read-receipts/notifications.spec.ts new file mode 100644 index 0000000000..5d87de1bb6 --- /dev/null +++ b/playwright/e2e/read-receipts/notifications.spec.ts @@ -0,0 +1,56 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("Notifications", () => { + test.describe("in the main timeline", () => { + test.fixme("A new message that mentions me shows a notification", () => {}); + test.fixme( + "Reading a notifying message reduces the notification count in the room list, space and tab", + () => {}, + ); + test.fixme( + "Reading the last notifying message removes the notification marker from room list, space and tab", + () => {}, + ); + test.fixme("Editing a message to mentions me shows a notification", () => {}); + test.fixme("Reading the last notifying edited message removes the notification marker", () => {}); + test.fixme("Redacting a notifying message removes the notification marker", () => {}); + }); + + test.describe("in threads", () => { + test.fixme("A new threaded message that mentions me shows a notification", () => {}); + test.fixme("Reading a notifying threaded message removes the notification count", () => {}); + test.fixme( + "Notification count remains steady when reading threads that contain seen notifications", + () => {}, + ); + test.fixme( + "Notification count remains steady when paging up thread view even when threads contain seen notifications", + () => {}, + ); + test.fixme( + "Notification count remains steady when paging up thread view after mark as unread even if older threads contain notifications", + () => {}, + ); + test.fixme("Redacting a notifying threaded message removes the notification marker", () => {}); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/reactions.spec.ts b/playwright/e2e/read-receipts/reactions-in-threads.spec.ts similarity index 56% rename from playwright/e2e/read-receipts/reactions.spec.ts rename to playwright/e2e/read-receipts/reactions-in-threads.spec.ts index 69208e5fc9..dcd97ac431 100644 --- a/playwright/e2e/read-receipts/reactions.spec.ts +++ b/playwright/e2e/read-receipts/reactions-in-threads.spec.ts @@ -20,82 +20,6 @@ import { test, expect } from "."; test.describe("Read receipts", () => { test.describe("reactions", () => { - test.describe("in the main timeline", () => { - test("Receiving a reaction to a message does not make a room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - - // When I read the main timeline - await util.goTo(room2); - await util.assertRead(room2); - - await util.goTo(room1); - await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); - await util.assertRead(room2); - }); - test("Reacting to a message after marking as read does not make the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - - await util.markAsRead(room2); - await util.assertRead(room2); - - await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); - await util.assertRead(room2); - }); - test("A room with an unread reaction is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - - await util.markAsRead(room2); - await util.assertRead(room2); - - await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); - await util.assertRead(room2); - - await util.saveAndReload(); - await util.assertRead(room2); - }); - test("A room where all reactions are read is still read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1", "Msg2", msg.reactionTo("Msg2", "🪿")]); - await util.assertUnread(room2, 2); - - await util.markAsRead(room2); - await util.assertRead(room2); - - await util.saveAndReload(); - await util.assertRead(room2); - }); - }); - test.describe("in threads", () => { test("A reaction to a threaded message does not make the room unread", async ({ roomAlpha: room1, @@ -281,97 +205,5 @@ test.describe("Read receipts", () => { await expect(await page.locator(".mx_ThreadPanel").getByLabel("Mae reacted with 😀")).not.toBeVisible(); }); }); - - test.describe("thread roots", () => { - test("A reaction to a thread root does not make the room unread", async ({ - page, - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a read thread root exists - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Reply1")]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - - // When someone reacts to it - await util.goTo(room1); - await util.receiveMessages(room2, [msg.reactionTo("Msg1", "🪿")]); - await page.waitForTimeout(200); - - // Then the room is still read - await util.assertRead(room2); - // as is the thread - await util.assertReadThread("Msg1"); - }); - - test("Reading a reaction to a thread root leaves the room read", async ({ - page, - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a read thread root exists - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Reply1")]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Msg1"); - await util.assertRead(room2); - - // And the reaction to it does not make us unread - await util.goTo(room1); - await util.receiveMessages(room2, [msg.reactionTo("Msg1", "🪿")]); - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - - // When we read the reaction and go away again - await util.goTo(room2); - await util.openThread("Msg1"); - await util.assertRead(room2); - await util.goTo(room1); - await page.waitForTimeout(200); - - // Then the room is still read - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - }); - - test("Reacting to a thread root after marking as read makes the room unread but not the thread", async ({ - page, - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread root exists - await util.goTo(room1); - await util.assertRead(room2); - await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Reply1")]); - await util.assertUnread(room2, 1); - - // And we have marked the room as read - await util.markAsRead(room2); - await util.assertRead(room2); - await util.assertReadThread("Msg1"); - - // When someone reacts to it - await util.receiveMessages(room2, [msg.reactionTo("Msg1", "🪿")]); - await page.waitForTimeout(200); - - // Then the room is still read - await util.assertRead(room2); - // as is the thread - await util.assertReadThread("Msg1"); - }); - }); }); }); diff --git a/playwright/e2e/read-receipts/reactions-main-timeline.spec.ts b/playwright/e2e/read-receipts/reactions-main-timeline.spec.ts new file mode 100644 index 0000000000..54f0c89afe --- /dev/null +++ b/playwright/e2e/read-receipts/reactions-main-timeline.spec.ts @@ -0,0 +1,99 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("reactions", () => { + test.describe("in the main timeline", () => { + test("Receiving a reaction to a message does not make a room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + + // When I read the main timeline + await util.goTo(room2); + await util.assertRead(room2); + + await util.goTo(room1); + await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); + await util.assertRead(room2); + }); + test("Reacting to a message after marking as read does not make the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + + await util.markAsRead(room2); + await util.assertRead(room2); + + await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); + await util.assertRead(room2); + }); + test("A room with an unread reaction is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + + await util.markAsRead(room2); + await util.assertRead(room2); + + await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); + await util.assertRead(room2); + + await util.saveAndReload(); + await util.assertRead(room2); + }); + test("A room where all reactions are read is still read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1", "Msg2", msg.reactionTo("Msg2", "🪿")]); + await util.assertUnread(room2, 2); + + await util.markAsRead(room2); + await util.assertRead(room2); + + await util.saveAndReload(); + await util.assertRead(room2); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/reactions-thread-roots.spec.ts b/playwright/e2e/read-receipts/reactions-thread-roots.spec.ts new file mode 100644 index 0000000000..9c1be63e5b --- /dev/null +++ b/playwright/e2e/read-receipts/reactions-thread-roots.spec.ts @@ -0,0 +1,115 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("reactions", () => { + test.describe("thread roots", () => { + test("A reaction to a thread root does not make the room unread", async ({ + page, + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a read thread root exists + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Reply1")]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + + // When someone reacts to it + await util.goTo(room1); + await util.receiveMessages(room2, [msg.reactionTo("Msg1", "🪿")]); + await page.waitForTimeout(200); + + // Then the room is still read + await util.assertRead(room2); + // as is the thread + await util.assertReadThread("Msg1"); + }); + + test("Reading a reaction to a thread root leaves the room read", async ({ + page, + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a read thread root exists + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Reply1")]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Msg1"); + await util.assertRead(room2); + + // And the reaction to it does not make us unread + await util.goTo(room1); + await util.receiveMessages(room2, [msg.reactionTo("Msg1", "🪿")]); + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + + // When we read the reaction and go away again + await util.goTo(room2); + await util.openThread("Msg1"); + await util.assertRead(room2); + await util.goTo(room1); + await page.waitForTimeout(200); + + // Then the room is still read + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + }); + + test("Reacting to a thread root after marking as read makes the room unread but not the thread", async ({ + page, + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread root exists + await util.goTo(room1); + await util.assertRead(room2); + await util.receiveMessages(room2, ["Msg1", msg.threadedOff("Msg1", "Reply1")]); + await util.assertUnread(room2, 1); + + // And we have marked the room as read + await util.markAsRead(room2); + await util.assertRead(room2); + await util.assertReadThread("Msg1"); + + // When someone reacts to it + await util.receiveMessages(room2, [msg.reactionTo("Msg1", "🪿")]); + await page.waitForTimeout(200); + + // Then the room is still read + await util.assertRead(room2); + // as is the thread + await util.assertReadThread("Msg1"); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/redactions.spec.ts b/playwright/e2e/read-receipts/redactions-in-threads.spec.ts similarity index 52% rename from playwright/e2e/read-receipts/redactions.spec.ts rename to playwright/e2e/read-receipts/redactions-in-threads.spec.ts index f7affbed21..323748e7e0 100644 --- a/playwright/e2e/read-receipts/redactions.spec.ts +++ b/playwright/e2e/read-receipts/redactions-in-threads.spec.ts @@ -20,314 +20,6 @@ import { test } from "."; test.describe("Read receipts", () => { test.describe("redactions", () => { - test.describe("in the main timeline", () => { - test("Redacting the message pointed to by my receipt leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given I have read the messages in a room - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - // When the latest message is redacted - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - - // Then the room remains read - await util.assertStillRead(room2); - }); - - test("Reading an unread room after a redaction of the latest message makes it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an unread room - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - - // And the latest message has been redacted - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - - // When I read the room - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - // Then it becomes read - await util.assertStillRead(room2); - }); - test("Reading an unread room after a redaction of an older message makes it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an unread room with an earlier redaction - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); - - // When I read the room - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - // Then it becomes read - await util.assertStillRead(room2); - }); - test("Marking an unread room as read after a redaction makes it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an unread room where latest message is redacted - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.assertUnread(room2, 1); - - // When I mark it as read - await util.markAsRead(room2); - - // Then it becomes read - await util.assertRead(room2); - }); - test("Sending and redacting a message after marking the room as read makes it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a room that is marked as read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When a message is sent and then redacted - await util.receiveMessages(room2, ["Msg3"]); - await util.assertUnread(room2, 1); - await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); - - // Then the room is read - await util.assertRead(room2); - }); - test("Redacting a message after marking the room as read leaves it read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a room that is marked as read - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2", "Msg3"]); - await util.assertUnread(room2, 3); - await util.markAsRead(room2); - await util.assertRead(room2); - - // When we redact some messages - await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); - await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); - - // Then it is still read - await util.assertStillRead(room2); - }); - test("Redacting one of the unread messages reduces the unread count", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an unread room - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2", "Msg3"]); - await util.assertUnread(room2, 3); - - // When I redact a non-latest message - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - - // Then the unread count goes down - await util.assertUnread(room2, 2); - - // And when I redact the latest message - await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); - - // Then the unread count goes down again - await util.assertUnread(room2, 1); - }); - test("Redacting one of the unread messages reduces the unread count after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given unread count was reduced by redacting messages - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2", "Msg3"]); - await util.assertUnread(room2, 3); - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); - await util.assertUnread(room2, 1); - - // When I restart - await util.saveAndReload(); - - // Then the unread count is still reduced - await util.assertUnread(room2, 1); - }); - test("Redacting all unread messages makes the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an unread room - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - - // When I redact all the unread messages - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); - - // Then the room is back to being read - await util.assertRead(room2); - }); - test("Redacting all unread messages makes the room read after restart", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given all unread messages were redacted - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); - await util.assertRead(room2); - - // When I restart - await util.saveAndReload(); - - // Then the room is still read - await util.assertRead(room2); - }); - test("Reacting to a redacted message leaves the room read", async ({ - page, - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a redacted message exists - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.assertUnread(room2, 1); - - // And the room is read - await util.goTo(room2); - await util.assertRead(room2); - await page.waitForTimeout(200); - await util.goTo(room1); - - // When I react to the redacted message - await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); - - // Then the room is still read - await util.assertStillRead(room2); - }); - test("Editing a redacted message leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a redacted message exists - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.assertUnread(room2, 1); - - // And the room is read - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - // When I attempt to edit the redacted message - await util.receiveMessages(room2, [msg.editOf("Msg2", "Msg2 is BACK")]); - - // Then the room is still read - await util.assertStillRead(room2); - }); - test("A reply to a redacted message makes the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a message was redacted - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.assertUnread(room2, 1); - - // And the room is read - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - - // When I receive a reply to the redacted message - await util.receiveMessages(room2, [msg.replyTo("Msg2", "Reply to Msg2")]); - - // Then the room is unread - await util.assertUnread(room2, 1); - }); - test("Reading a reply to a redacted message marks the room as read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given someone replied to a redacted message - await util.goTo(room1); - await util.receiveMessages(room2, ["Msg1", "Msg2"]); - await util.assertUnread(room2, 2); - await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.assertRead(room2); - await util.goTo(room1); - await util.receiveMessages(room2, [msg.replyTo("Msg2", "Reply to Msg2")]); - await util.assertUnread(room2, 1); - - // When I read the reply - await util.goTo(room2); - await util.assertRead(room2); - - // Then the room is unread - await util.goTo(room1); - await util.assertStillRead(room2); - }); - }); - test.describe("in threads", () => { test("Redacting the threaded message pointed to by my receipt leaves the room read", async ({ roomAlpha: room1, @@ -866,214 +558,5 @@ test.describe("Read receipts", () => { await util.assertReadThread("Root"); }); }); - - test.describe("thread roots", () => { - test("Redacting a thread root after it was read leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - test.slow(); - - // Given a thread exists and is read - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Root", - msg.threadedOff("Root", "Msg2"), - msg.threadedOff("Root", "Msg3"), - ]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Root"); - await util.assertRead(room2); - await util.assertReadThread("Root"); - - // When someone redacts the thread root - await util.receiveMessages(room2, [msg.redactionOf("Root")]); - - // Then the room is still read - await util.assertStillRead(room2); - }); - - /* - * Disabled for the same reason as "A thread with a read redaction is still read after restart" - * above - */ - test.skip("Redacting a thread root still allows us to read the thread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given an unread thread exists - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Root", - msg.threadedOff("Root", "Msg2"), - msg.threadedOff("Root", "Msg3"), - ]); - await util.assertUnread(room2, 1); - - // When someone redacts the thread root - await util.receiveMessages(room2, [msg.redactionOf("Root")]); - - // Then the room is still unread - await util.assertUnread(room2, 1); - - // And I can open the thread and read it - await util.goTo(room2); - await util.assertRead(room2); - // The redacted message gets collapsed into, "foo was invited, joined and removed a message" - await util.openCollapsedMessage(1); - await util.openThread("Message deleted"); - await util.assertRead(room2); - await util.assertReadThread("Root"); - }); - - test("Sending a threaded message onto a redacted thread root leaves the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread exists, is read and its root is redacted - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Root", - msg.threadedOff("Root", "Msg2"), - msg.threadedOff("Root", "Msg3"), - ]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Root"); - await util.assertRead(room2); - await util.assertReadThread("Root"); - await util.receiveMessages(room2, [msg.redactionOf("Root")]); - - // When we receive a new message on it - await util.receiveMessages(room2, [msg.threadedOff("Root", "Msg4")]); - - // Then the room is read but the thread is unread - await util.assertRead(room2); - await util.goTo(room2); - await util.assertUnreadThread("Message deleted"); - }); - - test("Reacting to a redacted thread root leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread exists, is read and the root was redacted - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Root", - msg.threadedOff("Root", "Msg2"), - msg.threadedOff("Root", "Msg3"), - ]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Root"); - await util.assertRead(room2); - await util.assertReadThread("Root"); - await util.receiveMessages(room2, [msg.redactionOf("Root")]); - - // When I react to the old root - await util.receiveMessages(room2, [msg.reactionTo("Root", "y")]); - - // Then the room is still read - await util.assertRead(room2); - await util.assertReadThread("Root"); - }); - - test("Editing a redacted thread root leaves the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread exists, is read and the root was redacted - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Root", - msg.threadedOff("Root", "Msg2"), - msg.threadedOff("Root", "Msg3"), - ]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Root"); - await util.assertRead(room2); - await util.assertReadThread("Root"); - await util.receiveMessages(room2, [msg.redactionOf("Root")]); - - // When I edit the old root - await util.receiveMessages(room2, [msg.editOf("Root", "New Root")]); - - // Then the room is still read - await util.assertRead(room2); - // as is the thread - await util.assertReadThread("Root"); - }); - - test("Replying to a redacted thread root makes the room unread", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread exists, is read and the root was redacted - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Root", - msg.threadedOff("Root", "Msg2"), - msg.threadedOff("Root", "Msg3"), - ]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Root"); - await util.assertRead(room2); - await util.assertReadThread("Root"); - await util.receiveMessages(room2, [msg.redactionOf("Root")]); - - // When I reply to the old root - await util.receiveMessages(room2, [msg.replyTo("Root", "Reply!")]); - - // Then the room is unread - await util.assertUnread(room2, 1); - }); - - test("Reading a reply to a redacted thread root makes the room read", async ({ - roomAlpha: room1, - roomBeta: room2, - util, - msg, - }) => { - // Given a thread exists, is read and the root was redacted, and - // someone replied to it - await util.goTo(room1); - await util.receiveMessages(room2, [ - "Root", - msg.threadedOff("Root", "Msg2"), - msg.threadedOff("Root", "Msg3"), - ]); - await util.assertUnread(room2, 1); - await util.goTo(room2); - await util.openThread("Root"); - await util.assertRead(room2); - await util.assertReadThread("Root"); - await util.receiveMessages(room2, [msg.redactionOf("Root")]); - await util.assertStillRead(room2); - await util.receiveMessages(room2, [msg.replyTo("Root", "Reply!")]); - await util.assertUnread(room2, 1); - - // When I read the room - await util.goTo(room2); - - // Then it becomes read - await util.assertRead(room2); - }); - }); }); }); diff --git a/playwright/e2e/read-receipts/redactions-main-timeline.spec.ts b/playwright/e2e/read-receipts/redactions-main-timeline.spec.ts new file mode 100644 index 0000000000..cb7393a63f --- /dev/null +++ b/playwright/e2e/read-receipts/redactions-main-timeline.spec.ts @@ -0,0 +1,331 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("redactions", () => { + test.describe("in the main timeline", () => { + test("Redacting the message pointed to by my receipt leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given I have read the messages in a room + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + // When the latest message is redacted + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + + // Then the room remains read + await util.assertStillRead(room2); + }); + + test("Reading an unread room after a redaction of the latest message makes it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an unread room + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + + // And the latest message has been redacted + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + + // When I read the room + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + // Then it becomes read + await util.assertStillRead(room2); + }); + test("Reading an unread room after a redaction of an older message makes it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an unread room with an earlier redaction + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); + + // When I read the room + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + // Then it becomes read + await util.assertStillRead(room2); + }); + test("Marking an unread room as read after a redaction makes it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an unread room where latest message is redacted + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.assertUnread(room2, 1); + + // When I mark it as read + await util.markAsRead(room2); + + // Then it becomes read + await util.assertRead(room2); + }); + test("Sending and redacting a message after marking the room as read makes it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a room that is marked as read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When a message is sent and then redacted + await util.receiveMessages(room2, ["Msg3"]); + await util.assertUnread(room2, 1); + await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); + + // Then the room is read + await util.assertRead(room2); + }); + test("Redacting a message after marking the room as read leaves it read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a room that is marked as read + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2", "Msg3"]); + await util.assertUnread(room2, 3); + await util.markAsRead(room2); + await util.assertRead(room2); + + // When we redact some messages + await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); + await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); + + // Then it is still read + await util.assertStillRead(room2); + }); + test("Redacting one of the unread messages reduces the unread count", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an unread room + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2", "Msg3"]); + await util.assertUnread(room2, 3); + + // When I redact a non-latest message + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + + // Then the unread count goes down + await util.assertUnread(room2, 2); + + // And when I redact the latest message + await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); + + // Then the unread count goes down again + await util.assertUnread(room2, 1); + }); + test("Redacting one of the unread messages reduces the unread count after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given unread count was reduced by redacting messages + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2", "Msg3"]); + await util.assertUnread(room2, 3); + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg3")]); + await util.assertUnread(room2, 1); + + // When I restart + await util.saveAndReload(); + + // Then the unread count is still reduced + await util.assertUnread(room2, 1); + }); + test("Redacting all unread messages makes the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an unread room + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + + // When I redact all the unread messages + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); + + // Then the room is back to being read + await util.assertRead(room2); + }); + test("Redacting all unread messages makes the room read after restart", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given all unread messages were redacted + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.receiveMessages(room2, [msg.redactionOf("Msg1")]); + await util.assertRead(room2); + + // When I restart + await util.saveAndReload(); + + // Then the room is still read + await util.assertRead(room2); + }); + test("Reacting to a redacted message leaves the room read", async ({ + page, + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a redacted message exists + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.assertUnread(room2, 1); + + // And the room is read + await util.goTo(room2); + await util.assertRead(room2); + await page.waitForTimeout(200); + await util.goTo(room1); + + // When I react to the redacted message + await util.receiveMessages(room2, [msg.reactionTo("Msg2", "🪿")]); + + // Then the room is still read + await util.assertStillRead(room2); + }); + test("Editing a redacted message leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a redacted message exists + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.assertUnread(room2, 1); + + // And the room is read + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + // When I attempt to edit the redacted message + await util.receiveMessages(room2, [msg.editOf("Msg2", "Msg2 is BACK")]); + + // Then the room is still read + await util.assertStillRead(room2); + }); + test("A reply to a redacted message makes the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a message was redacted + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.assertUnread(room2, 1); + + // And the room is read + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + + // When I receive a reply to the redacted message + await util.receiveMessages(room2, [msg.replyTo("Msg2", "Reply to Msg2")]); + + // Then the room is unread + await util.assertUnread(room2, 1); + }); + test("Reading a reply to a redacted message marks the room as read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given someone replied to a redacted message + await util.goTo(room1); + await util.receiveMessages(room2, ["Msg1", "Msg2"]); + await util.assertUnread(room2, 2); + await util.receiveMessages(room2, [msg.redactionOf("Msg2")]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.assertRead(room2); + await util.goTo(room1); + await util.receiveMessages(room2, [msg.replyTo("Msg2", "Reply to Msg2")]); + await util.assertUnread(room2, 1); + + // When I read the reply + await util.goTo(room2); + await util.assertRead(room2); + + // Then the room is unread + await util.goTo(room1); + await util.assertStillRead(room2); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/redactions-thread-roots.spec.ts b/playwright/e2e/read-receipts/redactions-thread-roots.spec.ts new file mode 100644 index 0000000000..0ded3957fb --- /dev/null +++ b/playwright/e2e/read-receipts/redactions-thread-roots.spec.ts @@ -0,0 +1,232 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("redactions", () => { + test.describe("thread roots", () => { + test("Redacting a thread root after it was read leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + test.slow(); + + // Given a thread exists and is read + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Root", + msg.threadedOff("Root", "Msg2"), + msg.threadedOff("Root", "Msg3"), + ]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Root"); + await util.assertRead(room2); + await util.assertReadThread("Root"); + + // When someone redacts the thread root + await util.receiveMessages(room2, [msg.redactionOf("Root")]); + + // Then the room is still read + await util.assertStillRead(room2); + }); + + /* + * Disabled for the same reason as "A thread with a read redaction is still read after restart" + * above + */ + test.skip("Redacting a thread root still allows us to read the thread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given an unread thread exists + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Root", + msg.threadedOff("Root", "Msg2"), + msg.threadedOff("Root", "Msg3"), + ]); + await util.assertUnread(room2, 1); + + // When someone redacts the thread root + await util.receiveMessages(room2, [msg.redactionOf("Root")]); + + // Then the room is still unread + await util.assertUnread(room2, 1); + + // And I can open the thread and read it + await util.goTo(room2); + await util.assertRead(room2); + // The redacted message gets collapsed into, "foo was invited, joined and removed a message" + await util.openCollapsedMessage(1); + await util.openThread("Message deleted"); + await util.assertRead(room2); + await util.assertReadThread("Root"); + }); + + test("Sending a threaded message onto a redacted thread root leaves the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread exists, is read and its root is redacted + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Root", + msg.threadedOff("Root", "Msg2"), + msg.threadedOff("Root", "Msg3"), + ]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Root"); + await util.assertRead(room2); + await util.assertReadThread("Root"); + await util.receiveMessages(room2, [msg.redactionOf("Root")]); + + // When we receive a new message on it + await util.receiveMessages(room2, [msg.threadedOff("Root", "Msg4")]); + + // Then the room is read but the thread is unread + await util.assertRead(room2); + await util.goTo(room2); + await util.assertUnreadThread("Message deleted"); + }); + + test("Reacting to a redacted thread root leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread exists, is read and the root was redacted + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Root", + msg.threadedOff("Root", "Msg2"), + msg.threadedOff("Root", "Msg3"), + ]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Root"); + await util.assertRead(room2); + await util.assertReadThread("Root"); + await util.receiveMessages(room2, [msg.redactionOf("Root")]); + + // When I react to the old root + await util.receiveMessages(room2, [msg.reactionTo("Root", "y")]); + + // Then the room is still read + await util.assertRead(room2); + await util.assertReadThread("Root"); + }); + + test("Editing a redacted thread root leaves the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread exists, is read and the root was redacted + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Root", + msg.threadedOff("Root", "Msg2"), + msg.threadedOff("Root", "Msg3"), + ]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Root"); + await util.assertRead(room2); + await util.assertReadThread("Root"); + await util.receiveMessages(room2, [msg.redactionOf("Root")]); + + // When I edit the old root + await util.receiveMessages(room2, [msg.editOf("Root", "New Root")]); + + // Then the room is still read + await util.assertRead(room2); + // as is the thread + await util.assertReadThread("Root"); + }); + + test("Replying to a redacted thread root makes the room unread", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread exists, is read and the root was redacted + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Root", + msg.threadedOff("Root", "Msg2"), + msg.threadedOff("Root", "Msg3"), + ]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Root"); + await util.assertRead(room2); + await util.assertReadThread("Root"); + await util.receiveMessages(room2, [msg.redactionOf("Root")]); + + // When I reply to the old root + await util.receiveMessages(room2, [msg.replyTo("Root", "Reply!")]); + + // Then the room is unread + await util.assertUnread(room2, 1); + }); + + test("Reading a reply to a redacted thread root makes the room read", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + // Given a thread exists, is read and the root was redacted, and + // someone replied to it + await util.goTo(room1); + await util.receiveMessages(room2, [ + "Root", + msg.threadedOff("Root", "Msg2"), + msg.threadedOff("Root", "Msg3"), + ]); + await util.assertUnread(room2, 1); + await util.goTo(room2); + await util.openThread("Root"); + await util.assertRead(room2); + await util.assertReadThread("Root"); + await util.receiveMessages(room2, [msg.redactionOf("Root")]); + await util.assertStillRead(room2); + await util.receiveMessages(room2, [msg.replyTo("Root", "Reply!")]); + await util.assertUnread(room2, 1); + + // When I read the room + await util.goTo(room2); + + // Then it becomes read + await util.assertRead(room2); + }); + }); + }); +}); diff --git a/playwright/e2e/read-receipts/room-list-order.spec.ts b/playwright/e2e/read-receipts/room-list-order.spec.ts new file mode 100644 index 0000000000..2b43022918 --- /dev/null +++ b/playwright/e2e/read-receipts/room-list-order.spec.ts @@ -0,0 +1,61 @@ +/* +Copyright 2023 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. +*/ + +/* See readme.md for tips on writing these tests. */ + +import { test } from "."; + +test.describe("Read receipts", () => { + test.describe("Room list order", () => { + test("Rooms with unread messages appear at the top of room list if 'unread first' is selected", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + page, + }) => { + await util.goTo(room2); + + // Display the unread first room + await util.toggleRoomUnreadOrder(); + await util.receiveMessages(room1, ["Msg1"]); + await page.reload(); + + // Room 1 has an unread message and should be displayed first + await util.assertRoomListOrder([room1, room2]); + }); + + test("Rooms with unread threads appear at the top of room list if 'unread first' is selected", async ({ + roomAlpha: room1, + roomBeta: room2, + util, + msg, + }) => { + await util.goTo(room2); + await util.receiveMessages(room1, ["Msg1"]); + await util.markAsRead(room1); + await util.assertRead(room1); + + // Display the unread first room + await util.toggleRoomUnreadOrder(); + await util.receiveMessages(room1, [msg.threadedOff("Msg1", "Resp1")]); + await util.saveAndReload(); + + // Room 1 has an unread message and should be displayed first + await util.assertRoomListOrder([room1, room2]); + }); + }); +}); diff --git a/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts index 79c78b71f7..aa00681f61 100644 --- a/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts @@ -60,113 +60,4 @@ test.describe("Appearance user settings tab", () => { // Assert that the font-family value was removed await expect(page.locator("body")).toHaveCSS("font-family", '""'); }); - - test.describe("Message Layout Panel", () => { - test.beforeEach(async ({ app, user, util }) => { - await util.createAndDisplayRoom(); - await util.assertModernLayout(); - await util.openAppearanceTab(); - }); - - test("should change the message layout from modern to bubble", async ({ page, app, user, util }) => { - await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-modern.png"); - - await util.getBubbleLayout().click(); - - // Assert that modern are irc layout are not selected - await expect(util.getBubbleLayout()).toBeChecked(); - await expect(util.getModernLayout()).not.toBeChecked(); - await expect(util.getIRCLayout()).not.toBeChecked(); - - // Assert that the room layout is set to bubble layout - await util.assertBubbleLayout(); - await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-bubble.png"); - }); - - test("should enable compact layout when the modern layout is selected", async ({ page, app, user, util }) => { - await expect(util.getCompactLayoutCheckbox()).not.toBeChecked(); - - await util.getCompactLayoutCheckbox().click(); - await util.assertCompactLayout(); - }); - - test("should disable compact layout when the modern layout is not selected", async ({ - page, - app, - user, - util, - }) => { - await expect(util.getCompactLayoutCheckbox()).not.toBeDisabled(); - - // Select the bubble layout, which should disable the compact layout checkbox - await util.getBubbleLayout().click(); - await expect(util.getCompactLayoutCheckbox()).toBeDisabled(); - }); - }); - - test.describe("Theme Choice Panel", () => { - test.beforeEach(async ({ app, user, util }) => { - // Disable the default theme for consistency in case ThemeWatcher automatically chooses it - await util.disableSystemTheme(); - await util.openAppearanceTab(); - }); - - test("should be rendered with the light theme selected", async ({ page, app, util }) => { - // Assert that 'Match system theme' is not checked - await expect(util.getMatchSystemThemeCheckbox()).not.toBeChecked(); - - // Assert that the light theme is selected - 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(); - - await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-light.png"); - }); - - test("should disable the themes when the system theme is clicked", async ({ page, app, util }) => { - await util.getMatchSystemThemeCheckbox().click(); - - // Assert that the themes are disabled - await expect(util.getLightTheme()).toBeDisabled(); - await expect(util.getDarkTheme()).toBeDisabled(); - await expect(util.getHighContrastTheme()).toBeDisabled(); - - await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-match-system-enabled.png"); - }); - - test("should change the theme to dark", async ({ page, app, util }) => { - // Assert that the light theme is selected - await expect(util.getLightTheme()).toBeChecked(); - - await util.getDarkTheme().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(); - - 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/message-layout-panel.ts b/playwright/e2e/settings/appearance-user-settings-tab/message-layout-panel.ts new file mode 100644 index 0000000000..1a22696da1 --- /dev/null +++ b/playwright/e2e/settings/appearance-user-settings-tab/message-layout-panel.ts @@ -0,0 +1,66 @@ +/* +Copyright 2023 Suguru Hirahara + +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 { expect, test } from "."; + +test.describe("Appearance user settings tab", () => { + test.use({ + displayName: "Hanako", + }); + + test.describe("Message Layout Panel", () => { + test.beforeEach(async ({ app, user, util }) => { + await util.createAndDisplayRoom(); + await util.assertModernLayout(); + await util.openAppearanceTab(); + }); + + test("should change the message layout from modern to bubble", async ({ page, app, user, util }) => { + await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-modern.png"); + + await util.getBubbleLayout().click(); + + // Assert that modern are irc layout are not selected + await expect(util.getBubbleLayout()).toBeChecked(); + await expect(util.getModernLayout()).not.toBeChecked(); + await expect(util.getIRCLayout()).not.toBeChecked(); + + // Assert that the room layout is set to bubble layout + await util.assertBubbleLayout(); + await util.assertScreenshot(util.getMessageLayoutPanel(), "message-layout-panel-bubble.png"); + }); + + test("should enable compact layout when the modern layout is selected", async ({ page, app, user, util }) => { + await expect(util.getCompactLayoutCheckbox()).not.toBeChecked(); + + await util.getCompactLayoutCheckbox().click(); + await util.assertCompactLayout(); + }); + + test("should disable compact layout when the modern layout is not selected", async ({ + page, + app, + user, + util, + }) => { + await expect(util.getCompactLayoutCheckbox()).not.toBeDisabled(); + + // Select the bubble layout, which should disable the compact layout checkbox + await util.getBubbleLayout().click(); + await expect(util.getCompactLayoutCheckbox()).toBeDisabled(); + }); + }); +}); diff --git a/playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts b/playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts new file mode 100644 index 0000000000..2b1e8cc14d --- /dev/null +++ b/playwright/e2e/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts @@ -0,0 +1,89 @@ +/* +Copyright 2023 Suguru Hirahara + +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 { expect, test } from "."; + +test.describe("Appearance user settings tab", () => { + test.use({ + displayName: "Hanako", + }); + + test.describe("Theme Choice Panel", () => { + test.beforeEach(async ({ app, user, util }) => { + // Disable the default theme for consistency in case ThemeWatcher automatically chooses it + await util.disableSystemTheme(); + await util.openAppearanceTab(); + }); + + test("should be rendered with the light theme selected", async ({ page, app, util }) => { + // Assert that 'Match system theme' is not checked + await expect(util.getMatchSystemThemeCheckbox()).not.toBeChecked(); + + // Assert that the light theme is selected + 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(); + + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-light.png"); + }); + + test("should disable the themes when the system theme is clicked", async ({ page, app, util }) => { + await util.getMatchSystemThemeCheckbox().click(); + + // Assert that the themes are disabled + await expect(util.getLightTheme()).toBeDisabled(); + await expect(util.getDarkTheme()).toBeDisabled(); + await expect(util.getHighContrastTheme()).toBeDisabled(); + + await expect(util.getThemePanel()).toMatchScreenshot("theme-panel-match-system-enabled.png"); + }); + + test("should change the theme to dark", async ({ page, app, util }) => { + // Assert that the light theme is selected + await expect(util.getLightTheme()).toBeChecked(); + + await util.getDarkTheme().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(); + + 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/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/theme-choice-panel.spec.ts/theme-panel-custom-theme-added-linux.png similarity index 100% rename from playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-custom-theme-added-linux.png rename to playwright/snapshots/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts/theme-panel-custom-theme-added-linux.png diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-custom-theme-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts/theme-panel-custom-theme-linux.png similarity index 100% rename from playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-custom-theme-linux.png rename to playwright/snapshots/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts/theme-panel-custom-theme-linux.png 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/theme-choice-panel.spec.ts/theme-panel-dark-linux.png similarity index 100% rename from playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-dark-linux.png rename to playwright/snapshots/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts/theme-panel-dark-linux.png 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/theme-choice-panel.spec.ts/theme-panel-light-linux.png similarity index 100% rename from playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-light-linux.png rename to playwright/snapshots/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts/theme-panel-light-linux.png 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/theme-choice-panel.spec.ts/theme-panel-match-system-enabled-linux.png similarity index 100% rename from playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/theme-panel-match-system-enabled-linux.png rename to playwright/snapshots/settings/appearance-user-settings-tab/theme-choice-panel.spec.ts/theme-panel-match-system-enabled-linux.png From 19f9f9856451a8e4cce6d313d19ca8aed4b5d6b4 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Wed, 10 Jul 2024 10:22:59 +0100 Subject: [PATCH 14/59] Element-R: Report events with withheld keys separately to Posthog. (#12755) * Remove refs to deprecated method `MatrixEvent.isEncryptedDisabledForUnverifiedDevices` is now deprecated * Report new posthog code for withheld message keys --- package.json | 2 +- src/DecryptionFailureTracker.ts | 3 + .../views/messages/DecryptionFailureBody.tsx | 4 +- test/DecryptionFailureTracker-test.ts | 57 ++++++------------- .../messages/DecryptionFailureBody-test.tsx | 17 +++--- yarn.lock | 8 +-- 6 files changed, 35 insertions(+), 56 deletions(-) diff --git a/package.json b/package.json index 89a9946811..4250a9d1ca 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ }, "dependencies": { "@babel/runtime": "^7.12.5", - "@matrix-org/analytics-events": "^0.23.0", + "@matrix-org/analytics-events": "^0.24.0", "@matrix-org/emojibase-bindings": "^1.1.2", "@matrix-org/matrix-wysiwyg": "2.37.4", "@matrix-org/react-sdk-module-api": "^2.4.0", diff --git a/src/DecryptionFailureTracker.ts b/src/DecryptionFailureTracker.ts index d16ddedbde..99ad2e8caa 100644 --- a/src/DecryptionFailureTracker.ts +++ b/src/DecryptionFailureTracker.ts @@ -78,7 +78,10 @@ export class DecryptionFailureTracker { // Map JS-SDK error codes to tracker codes for aggregation switch (errorCode) { case DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID: + case DecryptionFailureCode.MEGOLM_KEY_WITHHELD: return "OlmKeysNotSentError"; + case DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE: + return "RoomKeysWithheldForUnverifiedDevice"; case DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX: return "OlmIndexError"; case DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP: diff --git a/src/components/views/messages/DecryptionFailureBody.tsx b/src/components/views/messages/DecryptionFailureBody.tsx index 718fa492e2..7789e2d1da 100644 --- a/src/components/views/messages/DecryptionFailureBody.tsx +++ b/src/components/views/messages/DecryptionFailureBody.tsx @@ -23,8 +23,10 @@ import { IBodyProps } from "./IBodyProps"; import { LocalDeviceVerificationStateContext } from "../../../contexts/LocalDeviceVerificationStateContext"; function getErrorMessage(mxEvent: MatrixEvent, isVerified: boolean | undefined): string { - if (mxEvent.isEncryptedDisabledForUnverifiedDevices) return _t("timeline|decryption_failure|blocked"); switch (mxEvent.decryptionFailureReason) { + case DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE: + return _t("timeline|decryption_failure|blocked"); + case DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP: return _t("timeline|decryption_failure|historical_event_no_key_backup"); diff --git a/test/DecryptionFailureTracker-test.ts b/test/DecryptionFailureTracker-test.ts index ca8c4b3660..d465d9b2aa 100644 --- a/test/DecryptionFailureTracker-test.ts +++ b/test/DecryptionFailureTracker-test.ts @@ -490,47 +490,22 @@ describe("DecryptionFailureTracker", function () { const now = Date.now(); - const event1 = await createFailedDecryptionEvent({ - code: DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID, - }); - tracker.addVisibleEvent(event1); - eventDecrypted(tracker, event1, now); + async function createAndTrackEventWithError(code: DecryptionFailureCode) { + const event = await createFailedDecryptionEvent({ code }); + tracker.addVisibleEvent(event); + eventDecrypted(tracker, event, now); + return event; + } - const event2 = await createFailedDecryptionEvent({ - code: DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX, - }); - tracker.addVisibleEvent(event2); - eventDecrypted(tracker, event2, now); - - const event3 = await createFailedDecryptionEvent({ - code: DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP, - }); - tracker.addVisibleEvent(event3); - eventDecrypted(tracker, event3, now); - - const event4 = await createFailedDecryptionEvent({ - code: DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED, - }); - tracker.addVisibleEvent(event4); - eventDecrypted(tracker, event4, now); - - const event5 = await createFailedDecryptionEvent({ - code: DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP, - }); - tracker.addVisibleEvent(event5); - eventDecrypted(tracker, event5, now); - - const event6 = await createFailedDecryptionEvent({ - code: DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED, - }); - tracker.addVisibleEvent(event6); - eventDecrypted(tracker, event6, now); - - const event7 = await createFailedDecryptionEvent({ - code: DecryptionFailureCode.UNKNOWN_ERROR, - }); - tracker.addVisibleEvent(event7); - eventDecrypted(tracker, event7, now); + await createAndTrackEventWithError(DecryptionFailureCode.MEGOLM_UNKNOWN_INBOUND_SESSION_ID); + await createAndTrackEventWithError(DecryptionFailureCode.OLM_UNKNOWN_MESSAGE_INDEX); + await createAndTrackEventWithError(DecryptionFailureCode.HISTORICAL_MESSAGE_NO_KEY_BACKUP); + await createAndTrackEventWithError(DecryptionFailureCode.HISTORICAL_MESSAGE_BACKUP_UNCONFIGURED); + await createAndTrackEventWithError(DecryptionFailureCode.HISTORICAL_MESSAGE_WORKING_BACKUP); + await createAndTrackEventWithError(DecryptionFailureCode.HISTORICAL_MESSAGE_USER_NOT_JOINED); + await createAndTrackEventWithError(DecryptionFailureCode.MEGOLM_KEY_WITHHELD); + await createAndTrackEventWithError(DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE); + await createAndTrackEventWithError(DecryptionFailureCode.UNKNOWN_ERROR); // Pretend "now" is Infinity tracker.checkFailures(Infinity); @@ -542,6 +517,8 @@ describe("DecryptionFailureTracker", function () { "HistoricalMessage", "HistoricalMessage", "ExpectedDueToMembership", + "OlmKeysNotSentError", + "RoomKeysWithheldForUnverifiedDevice", "UnknownError", ]); }); diff --git a/test/components/views/messages/DecryptionFailureBody-test.tsx b/test/components/views/messages/DecryptionFailureBody-test.tsx index 6b0177a916..b9b90b9922 100644 --- a/test/components/views/messages/DecryptionFailureBody-test.tsx +++ b/test/components/views/messages/DecryptionFailureBody-test.tsx @@ -50,18 +50,15 @@ describe("DecryptionFailureBody", () => { expect(container).toMatchSnapshot(); }); - it(`Should display "The sender has blocked you from receiving this message"`, () => { + it(`Should display "The sender has blocked you from receiving this message"`, async () => { // When - const event = mkEvent({ - type: "m.room.message", - room: "myfakeroom", - user: "myfakeuser", - content: { - msgtype: "m.bad.encrypted", - }, - event: true, + const event = await mkDecryptionFailureMatrixEvent({ + code: DecryptionFailureCode.MEGOLM_KEY_WITHHELD_FOR_UNVERIFIED_DEVICE, + msg: "withheld", + roomId: "myfakeroom", + sender: "myfakeuser", }); - jest.spyOn(event, "isEncryptedDisabledForUnverifiedDevices", "get").mockReturnValue(true); + const { container } = customRender(event); // Then diff --git a/yarn.lock b/yarn.lock index 8e702d5d2a..3c3dcf25ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1773,10 +1773,10 @@ resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== -"@matrix-org/analytics-events@^0.23.0": - version "0.23.1" - resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.23.1.tgz#206224f63e64b8cd892f704964204bce433bd189" - integrity sha512-+DuK5F313bZfO0jCsP7X3u0FQ09IM9Ujc9Zf//XoxzGThG9pvSYsEyNXQO7kUeQHwXlOobtVg1QcP172kN+h/g== +"@matrix-org/analytics-events@^0.24.0": + version "0.24.0" + resolved "https://registry.yarnpkg.com/@matrix-org/analytics-events/-/analytics-events-0.24.0.tgz#21a64537ac975b18e1eb13d9fd0bdc7d448a6039" + integrity sha512-3FDdtqZ+5cMqVffWjFNOIQ7RDFN6XS11kqdtN2ps8uvq5ce8gT0yXQvK37WeKWKZZ5QAKeoMzGhud+lsVcb1xg== "@matrix-org/emojibase-bindings@^1.1.2": version "1.1.3" From 44b98896a79ede48f5ad7ff22619a39d5f6ff03c Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 10 Jul 2024 20:10:19 +0100 Subject: [PATCH 15/59] Move integrations switch (#12733) * Move integrations switch This is the last thing to move out of 'general' now. * unused import * Move tests out to the SetIntegrationManager component * Only a decade out * Move playwright test to the new tab * Update snapshot * Update other snapshot --- .../general-user-settings-tab.spec.ts | 12 -- .../security-user-settings-tab.spec.ts | 20 ++++ .../views/settings/SetIntegrationManager.tsx | 7 +- .../tabs/user/GeneralUserSettingsTab.tsx | 8 -- .../tabs/user/SecurityUserSettingsTab.tsx | 2 + .../settings/SetIntegrationManager-test.tsx | 104 ++++++++++++++++++ .../SetIntegrationManager-test.tsx.snap | 56 ++++++++++ .../tabs/user/GeneralUserSettingsTab-test.tsx | 60 ---------- .../GeneralUserSettingsTab-test.tsx.snap | 63 +---------- .../SecurityUserSettingsTab-test.tsx.snap | 52 +++++++++ 10 files changed, 243 insertions(+), 141 deletions(-) create mode 100644 test/components/views/settings/SetIntegrationManager-test.tsx create mode 100644 test/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap diff --git a/playwright/e2e/settings/general-user-settings-tab.spec.ts b/playwright/e2e/settings/general-user-settings-tab.spec.ts index 050cd76d00..0ba85e890b 100644 --- a/playwright/e2e/settings/general-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/general-user-settings-tab.spec.ts @@ -18,7 +18,6 @@ import { test, expect } from "../../element-web-test"; const USER_NAME = "Bob"; const USER_NAME_NEW = "Alice"; -const IntegrationManager = "scalar.vector.im"; test.describe("General user settings tab", () => { test.use({ @@ -73,17 +72,6 @@ test.describe("General user settings tab", () => { // Assert that the add button is rendered await expect(phoneNumbers.getByRole("button", { name: "Add" })).toBeVisible(); - const setIntegrationManager = uut.locator(".mx_SetIntegrationManager"); - await setIntegrationManager.scrollIntoViewIfNeeded(); - await expect( - setIntegrationManager.locator(".mx_SetIntegrationManager_heading_manager", { hasText: IntegrationManager }), - ).toBeVisible(); - // Make sure integration manager's toggle switch is enabled - await expect(setIntegrationManager.locator(".mx_ToggleSwitch_enabled")).toBeVisible(); - await expect(setIntegrationManager.locator(".mx_SetIntegrationManager_heading_manager")).toHaveText( - "Manage integrations(scalar.vector.im)", - ); - // Assert the account deactivation button is displayed const accountManagementSection = uut.getByTestId("account-management-section"); await accountManagementSection.scrollIntoViewIfNeeded(); diff --git a/playwright/e2e/settings/security-user-settings-tab.spec.ts b/playwright/e2e/settings/security-user-settings-tab.spec.ts index 5cd2a92c16..381b291e97 100644 --- a/playwright/e2e/settings/security-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/security-user-settings-tab.spec.ts @@ -1,5 +1,6 @@ /* Copyright 2023 Suguru Hirahara +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. @@ -16,6 +17,8 @@ limitations under the License. import { test, expect } from "../../element-web-test"; +const IntegrationManager = "scalar.vector.im"; + test.describe("Security user settings tab", () => { test.describe("with posthog enabled", () => { test.use({ @@ -56,5 +59,22 @@ test.describe("Security user settings tab", () => { // Assert that an input area for identity server exists await expect(setIdServer.getByRole("textbox", { name: "Enter a new identity server" })).toBeVisible(); }); + + test("should enable show integrations as enabled", async ({ app, page }) => { + const tab = await app.settings.openUserSettings("Security"); + + const setIntegrationManager = tab.locator(".mx_SetIntegrationManager"); + await setIntegrationManager.scrollIntoViewIfNeeded(); + await expect( + setIntegrationManager.locator(".mx_SetIntegrationManager_heading_manager", { + hasText: IntegrationManager, + }), + ).toBeVisible(); + // Make sure integration manager's toggle switch is enabled + await expect(setIntegrationManager.locator(".mx_ToggleSwitch_enabled")).toBeVisible(); + await expect(setIntegrationManager.locator(".mx_SetIntegrationManager_heading_manager")).toHaveText( + "Manage integrations(scalar.vector.im)", + ); + }); }); }); diff --git a/src/components/views/settings/SetIntegrationManager.tsx b/src/components/views/settings/SetIntegrationManager.tsx index 374508d9c6..fe55efd90f 100644 --- a/src/components/views/settings/SetIntegrationManager.tsx +++ b/src/components/views/settings/SetIntegrationManager.tsx @@ -25,6 +25,7 @@ import { SettingLevel } from "../../../settings/SettingLevel"; import ToggleSwitch from "../elements/ToggleSwitch"; import Heading from "../typography/Heading"; import { SettingsSubsectionText } from "./shared/SettingsSubsection"; +import { UIFeature } from "../../../settings/UIFeature"; interface IProps {} @@ -71,6 +72,8 @@ export default class SetIntegrationManager extends React.Component
- {_t("integration_manager|manage_title")} - {managerName} + {_t("integration_manager|manage_title")} + {managerName}
; - } - public render(): React.ReactNode { let accountManagementSection: JSX.Element | undefined; const isAccountManagedExternally = !!this.state.externalAccountManagementUrl; @@ -218,7 +211,6 @@ export default class GeneralUserSettingsTab extends React.Component {this.renderAccountSection()} - {this.renderIntegrationManagerSection()} {accountManagementSection} ); diff --git a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx index c636721201..3b0dfb2dfc 100644 --- a/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/SecurityUserSettingsTab.tsx @@ -44,6 +44,7 @@ import { SettingsSection } from "../../shared/SettingsSection"; import SettingsSubsection, { SettingsSubsectionText } from "../../shared/SettingsSubsection"; import { useOwnDevices } from "../../devices/useOwnDevices"; import DiscoverySettings from "../../discovery/DiscoverySettings"; +import SetIntegrationManager from "../../SetIntegrationManager"; interface IIgnoredUserProps { userId: string; @@ -376,6 +377,7 @@ export default class SecurityUserSettingsTab extends React.Component {warning} + {secureBackup} {eventIndex} diff --git a/test/components/views/settings/SetIntegrationManager-test.tsx b/test/components/views/settings/SetIntegrationManager-test.tsx new file mode 100644 index 0000000000..5b92e03940 --- /dev/null +++ b/test/components/views/settings/SetIntegrationManager-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 { fireEvent, render, screen, within } from "@testing-library/react"; +import { logger } from "matrix-js-sdk/src/logger"; + +import MatrixClientContext from "../../../../src/contexts/MatrixClientContext"; +import { SDKContext, SdkContextClass } from "../../../../src/contexts/SDKContext"; +import SettingsStore from "../../../../src/settings/SettingsStore"; +import { UIFeature } from "../../../../src/settings/UIFeature"; +import { + getMockClientWithEventEmitter, + mockClientMethodsServer, + mockClientMethodsUser, + flushPromises, +} from "../../../test-utils"; +import SetIntegrationManager from "../../../../src/components/views/settings/SetIntegrationManager"; +import { SettingLevel } from "../../../../src/settings/SettingLevel"; + +describe("SetIntegrationManager", () => { + const userId = "@alice:server.org"; + + const mockClient = getMockClientWithEventEmitter({ + ...mockClientMethodsUser(userId), + ...mockClientMethodsServer(), + getCapabilities: jest.fn(), + getThreePids: jest.fn(), + getIdentityServerUrl: jest.fn(), + deleteThreePid: jest.fn(), + }); + + let stores: SdkContextClass; + + const getComponent = () => ( + + + + + + ); + + it("should not render manage integrations section when widgets feature is disabled", () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => settingName !== UIFeature.Widgets); + render(getComponent()); + + expect(screen.queryByTestId("mx_SetIntegrationManager")).not.toBeInTheDocument(); + expect(SettingsStore.getValue).toHaveBeenCalledWith(UIFeature.Widgets); + }); + it("should render manage integrations sections", () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => settingName === UIFeature.Widgets); + + render(getComponent()); + + expect(screen.getByTestId("mx_SetIntegrationManager")).toMatchSnapshot(); + }); + it("should update integrations provisioning on toggle", () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => settingName === UIFeature.Widgets); + jest.spyOn(SettingsStore, "setValue").mockResolvedValue(undefined); + + render(getComponent()); + + const integrationSection = screen.getByTestId("mx_SetIntegrationManager"); + fireEvent.click(within(integrationSection).getByRole("switch")); + + expect(SettingsStore.setValue).toHaveBeenCalledWith( + "integrationProvisioning", + null, + SettingLevel.ACCOUNT, + true, + ); + expect(within(integrationSection).getByRole("switch")).toBeChecked(); + }); + it("handles error when updating setting fails", async () => { + jest.spyOn(SettingsStore, "getValue").mockImplementation((settingName) => settingName === UIFeature.Widgets); + jest.spyOn(logger, "error").mockImplementation(() => {}); + + jest.spyOn(SettingsStore, "setValue").mockRejectedValue("oups"); + + render(getComponent()); + + const integrationSection = screen.getByTestId("mx_SetIntegrationManager"); + fireEvent.click(within(integrationSection).getByRole("switch")); + + await flushPromises(); + + expect(logger.error).toHaveBeenCalledWith("Error changing integration manager provisioning"); + expect(logger.error).toHaveBeenCalledWith("oups"); + expect(within(integrationSection).getByRole("switch")).not.toBeChecked(); + }); +}); diff --git a/test/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap b/test/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap new file mode 100644 index 0000000000..cde822f6ab --- /dev/null +++ b/test/components/views/settings/__snapshots__/SetIntegrationManager-test.tsx.snap @@ -0,0 +1,56 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`SetIntegrationManager should render manage integrations sections 1`] = ` +
From 348000100a19cba4a3fb094c3c48fc0afe501343 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Sat, 13 Jul 2024 11:27:59 +0100 Subject: [PATCH 24/59] Cleanup tasks in SecurityManager/SetupEncryptionStore (#12764) * Remove call to no-op `checkOwnCrossSigningTrust` this is a no-op on rust crypto * inline `SecurityManager.isCachingAllowed` Since https://github.com/matrix-org/matrix-react-sdk/pull/4789, this has just been an obscure way to write a test of a local variable. * Remove unused `CreateSecretStorageOpts.getKeyBackupPassphrase` parameter This is unused on rust crypto (cf https://github.com/matrix-org/matrix-js-sdk/pull/4313) --- src/SecurityManager.ts | 39 +++---------------- .../security/CreateSecretStorageDialog.tsx | 17 +------- src/stores/SetupEncryptionStore.ts | 2 - test/test-utils/test-utils.ts | 1 - 4 files changed, 6 insertions(+), 53 deletions(-) diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index 873aec08e2..c5958a6f48 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -25,7 +25,6 @@ import { MatrixClientPeg } from "./MatrixClientPeg"; import { _t } from "./languageHandler"; import { isSecureBackupRequired } from "./utils/WellKnownUtils"; import AccessSecretStorageDialog, { KeyParams } from "./components/views/dialogs/security/AccessSecretStorageDialog"; -import RestoreKeyBackupDialog from "./components/views/dialogs/security/RestoreKeyBackupDialog"; import SettingsStore from "./settings/SettingsStore"; import { ModuleRunner } from "./modules/ModuleRunner"; import QuestionDialog from "./components/views/dialogs/QuestionDialog"; @@ -45,10 +44,6 @@ let dehydrationCache: { keyInfo?: SecretStorage.SecretStorageKeyDescription; } = {}; -function isCachingAllowed(): boolean { - return secretStorageBeingAccessed; -} - /** * This can be used by other components to check if secret storage access is in * progress, so that we can e.g. avoid intermittently showing toasts during @@ -118,7 +113,7 @@ async function getSecretStorageKey({ } // Check the in-memory cache - if (isCachingAllowed() && secretStorageKeys[keyId]) { + if (secretStorageBeingAccessed && secretStorageKeys[keyId]) { return [keyId, secretStorageKeys[keyId]]; } @@ -226,7 +221,7 @@ function cacheSecretStorageKey( keyInfo: SecretStorage.SecretStorageKeyDescription, key: Uint8Array, ): void { - if (isCachingAllowed()) { + if (secretStorageBeingAccessed) { secretStorageKeys[keyId] = key; secretStorageKeyInfo[keyId] = keyInfo; } @@ -278,26 +273,6 @@ export const crossSigningCallbacks: ICryptoCallbacks = { getDehydrationKey, }; -export async function promptForBackupPassphrase(): Promise { - let key!: Uint8Array; - - const { finished } = Modal.createDialog( - RestoreKeyBackupDialog, - { - showSummary: false, - keyCallback: (k: Uint8Array) => (key = k), - }, - undefined, - /* priority = */ false, - /* static = */ true, - ); - - const success = await finished; - if (!success) throw new Error("Key backup prompt cancelled"); - - return key; -} - /** * Carry out an operation that may require multiple accesses to secret storage, caching the key. * @@ -313,10 +288,8 @@ export async function withSecretStorageKeyCache(func: () => Promise): Prom } finally { // Clear secret storage key cache now that work is complete secretStorageBeingAccessed = false; - if (!isCachingAllowed()) { - secretStorageKeys = {}; - secretStorageKeyInfo = {}; - } + secretStorageKeys = {}; + secretStorageKeyInfo = {}; } } @@ -395,9 +368,7 @@ async function doAccessSecretStorage(func: () => Promise, forceReset: bool } }, }); - await crypto.bootstrapSecretStorage({ - getKeyBackupPassphrase: promptForBackupPassphrase, - }); + await crypto.bootstrapSecretStorage({}); const keyId = Object.keys(secretStorageKeys)[0]; if (keyId && SettingsStore.getValue("feature_dehydration")) { diff --git a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx index 0316c43994..97469177d9 100644 --- a/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx +++ b/src/async-components/views/dialogs/security/CreateSecretStorageDialog.tsx @@ -26,7 +26,6 @@ import { BackupTrustInfo, GeneratedSecretStorageKey, KeyBackupInfo } from "matri import { MatrixClientPeg } from "../../../../MatrixClientPeg"; import { _t, _td } from "../../../../languageHandler"; import Modal from "../../../../Modal"; -import { promptForBackupPassphrase } from "../../../../SecurityManager"; import { copyNode } from "../../../../utils/strings"; import { SSOAuthEntry } from "../../../../components/views/auth/InteractiveAuthEntryComponents"; import PassphraseField from "../../../../components/views/auth/PassphraseField"; @@ -123,7 +122,6 @@ export default class CreateSecretStorageDialog extends React.PureComponent(); private passphraseField = createRef(); @@ -384,15 +382,6 @@ export default class CreateSecretStorageDialog extends React.PureComponent this.recoveryKey!, keyBackupInfo: this.state.backupInfo!, setupNewKeyBackup: !this.state.backupInfo, - getKeyBackupPassphrase: async (): Promise => { - // We may already have the backup key if we earlier went - // through the restore backup path, so pass it along - // rather than prompting again. - if (this.backupKey) { - return this.backupKey; - } - return promptForBackupPassphrase(); - }, }); } await initialiseDehydration(true); @@ -424,11 +413,7 @@ export default class CreateSecretStorageDialog extends React.PureComponent => { - // It's possible we'll need the backup key later on for bootstrapping, - // so let's stash it here, rather than prompting for it twice. - const keyCallback = (k: Uint8Array): void => { - this.backupKey = k; - }; + const keyCallback = (k: Uint8Array): void => {}; const { finished } = Modal.createDialog( RestoreKeyBackupDialog, diff --git a/src/stores/SetupEncryptionStore.ts b/src/stores/SetupEncryptionStore.ts index 640ef2c7a4..dce523875e 100644 --- a/src/stores/SetupEncryptionStore.ts +++ b/src/stores/SetupEncryptionStore.ts @@ -152,8 +152,6 @@ export class SetupEncryptionStore extends EventEmitter { // in the background. await new Promise((resolve: (value?: unknown) => void, reject: (reason?: any) => void) => { accessSecretStorage(async (): Promise => { - await cli.checkOwnCrossSigningTrust(); - // The remaining tasks (device dehydration and restoring // key backup) may take some time due to processing many // to-device messages in the case of device dehydration, or diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 9b28a3077a..5370f72b18 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -116,7 +116,6 @@ export function createTestClient(): MatrixClient { bootstrapCrossSigning: jest.fn(), hasSecretStorageKey: jest.fn(), getKeyBackupVersion: jest.fn(), - checkOwnCrossSigningTrust: jest.fn(), secretStorage: { get: jest.fn(), From 52c32f37c3bd0f0423e7c885a42c2c029a682c7a Mon Sep 17 00:00:00 2001 From: Richard van der Hoff <1389908+richvdh@users.noreply.github.com> Date: Sat, 13 Jul 2024 13:36:45 +0100 Subject: [PATCH 25/59] Add logging to encryption setup (#12765) * Add logging to `getSecretStorageKey` * Replace call to deprecated MatrixClient.hasSecretStorageKey * Add/improve logging in `accessSecretStorage` * Add/improve logging in SetupEncryptionStore.usePassPhrase --- src/SecurityManager.ts | 46 ++++++++++++++++++++++-------- src/stores/SetupEncryptionStore.ts | 36 ++++++++++++----------- test/SecurityManager-test.ts | 4 +-- 3 files changed, 56 insertions(+), 30 deletions(-) diff --git a/src/SecurityManager.ts b/src/SecurityManager.ts index c5958a6f48..c1c4e7a72b 100644 --- a/src/SecurityManager.ts +++ b/src/SecurityManager.ts @@ -111,14 +111,17 @@ async function getSecretStorageKey({ } [keyId, keyInfo] = keyInfoEntries[0]; } + logger.debug(`getSecretStorageKey: request for 4S keys [${Object.keys(keyInfos)}]: looking for key ${keyId}`); // Check the in-memory cache if (secretStorageBeingAccessed && secretStorageKeys[keyId]) { + logger.debug(`getSecretStorageKey: returning key ${keyId} from cache`); return [keyId, secretStorageKeys[keyId]]; } if (dehydrationCache.key) { if (await MatrixClientPeg.safeGet().checkSecretStorageKey(dehydrationCache.key, keyInfo)) { + logger.debug("getSecretStorageKey: returning key from dehydration cache"); cacheSecretStorageKey(keyId, keyInfo, dehydrationCache.key); return [keyId, dehydrationCache.key]; } @@ -126,11 +129,12 @@ async function getSecretStorageKey({ const keyFromCustomisations = ModuleRunner.instance.extensions.cryptoSetup.getSecretStorageKey(); if (keyFromCustomisations) { - logger.log("CryptoSetupExtension: Using key from extension (secret storage)"); + logger.log("getSecretStorageKey: Using secret storage key from CryptoSetupExtension"); cacheSecretStorageKey(keyId, keyInfo, keyFromCustomisations); return [keyId, keyFromCustomisations]; } + logger.debug("getSecretStorageKey: prompting user for key"); const inputToKey = makeInputToKey(keyInfo); const { finished } = Modal.createDialog( AccessSecretStorageDialog, @@ -158,6 +162,7 @@ async function getSecretStorageKey({ if (!keyParams) { throw new AccessCancelledError(); } + logger.debug("getSecretStorageKey: got key from user"); const key = await inputToKey(keyParams); // Save to cache to avoid future prompts in the current session @@ -282,11 +287,13 @@ export const crossSigningCallbacks: ICryptoCallbacks = { * @param func - The operation to be wrapped. */ export async function withSecretStorageKeyCache(func: () => Promise): Promise { + logger.debug("SecurityManager: enabling 4S key cache"); secretStorageBeingAccessed = true; try { return await func(); } finally { // Clear secret storage key cache now that work is complete + logger.debug("SecurityManager: disabling 4S key cache"); secretStorageBeingAccessed = false; secretStorageKeys = {}; secretStorageKeyInfo = {}; @@ -322,7 +329,21 @@ export async function accessSecretStorage(func = async (): Promise => {}, async function doAccessSecretStorage(func: () => Promise, forceReset: boolean): Promise { try { const cli = MatrixClientPeg.safeGet(); - if (!(await cli.hasSecretStorageKey()) || forceReset) { + const crypto = cli.getCrypto(); + if (!crypto) { + throw new Error("End-to-end encryption is disabled - unable to access secret storage."); + } + + let createNew = false; + if (forceReset) { + logger.debug("accessSecretStorage: resetting 4S"); + createNew = true; + } else if (!(await cli.secretStorage.hasKey())) { + logger.debug("accessSecretStorage: no 4S key configured, creating a new one"); + createNew = true; + } + + if (createNew) { // This dialog calls bootstrap itself after guiding the user through // passphrase creation. const { finished } = Modal.createDialogAsync( @@ -350,13 +371,10 @@ async function doAccessSecretStorage(func: () => Promise, forceReset: bool throw new Error("Secret storage creation canceled"); } } else { - const crypto = cli.getCrypto(); - if (!crypto) { - throw new Error("End-to-end encryption is disabled - unable to access secret storage."); - } - + logger.debug("accessSecretStorage: bootstrapCrossSigning"); await crypto.bootstrapCrossSigning({ authUploadDeviceSigningKeys: async (makeRequest): Promise => { + logger.debug("accessSecretStorage: performing UIA to upload cross-signing keys"); const { finished } = Modal.createDialog(InteractiveAuthDialog, { title: _t("encryption|bootstrap_title"), matrixClient: cli, @@ -366,8 +384,10 @@ async function doAccessSecretStorage(func: () => Promise, forceReset: bool if (!confirmed) { throw new Error("Cross-signing key upload auth canceled"); } + logger.debug("accessSecretStorage: Cross-signing key upload successful"); }, }); + logger.debug("accessSecretStorage: bootstrapSecretStorage"); await crypto.bootstrapSecretStorage({}); const keyId = Object.keys(secretStorageKeys)[0]; @@ -376,21 +396,23 @@ async function doAccessSecretStorage(func: () => Promise, forceReset: bool if (secretStorageKeyInfo[keyId] && secretStorageKeyInfo[keyId].passphrase) { dehydrationKeyInfo = { passphrase: secretStorageKeyInfo[keyId].passphrase }; } - logger.log("Setting dehydration key"); + logger.log("accessSecretStorage: Setting dehydration key"); await cli.setDehydrationKey(secretStorageKeys[keyId], dehydrationKeyInfo, "Backup device"); } else if (!keyId) { - logger.warn("Not setting dehydration key: no SSSS key found"); + logger.warn("accessSecretStorage: Not setting dehydration key: no SSSS key found"); } else { - logger.log("Not setting dehydration key: feature disabled"); + logger.log("accessSecretStorage: Not setting dehydration key: feature disabled"); } } + logger.debug("accessSecretStorage: 4S now ready"); // `return await` needed here to ensure `finally` block runs after the // inner operation completes. - return await func(); + await func(); + logger.debug("accessSecretStorage: operation complete"); } catch (e) { ModuleRunner.instance.extensions.cryptoSetup.catchAccessSecretStorageError(e as Error); - logger.error(e); + logger.error("accessSecretStorage: error during operation", e); // Re-throw so that higher level logic can abort as needed throw e; } diff --git a/src/stores/SetupEncryptionStore.ts b/src/stores/SetupEncryptionStore.ts index dce523875e..62a3412d81 100644 --- a/src/stores/SetupEncryptionStore.ts +++ b/src/stores/SetupEncryptionStore.ts @@ -135,6 +135,7 @@ export class SetupEncryptionStore extends EventEmitter { } public async usePassPhrase(): Promise { + logger.debug("SetupEncryptionStore.usePassphrase"); this.phase = Phase.Busy; this.emit("update"); try { @@ -142,21 +143,21 @@ export class SetupEncryptionStore extends EventEmitter { const backupInfo = await cli.getKeyBackupVersion(); this.backupInfo = backupInfo; this.emit("update"); - // The control flow is fairly twisted here... - // For the purposes of completing security, we only wait on getting - // as far as the trust check and then show a green shield. - // We also begin the key backup restore as well, which we're - // awaiting inside `accessSecretStorage` only so that it keeps your - // passphase cached for that work. This dialog itself will only wait - // on the first trust check, and the key backup restore will happen - // in the background. + await new Promise((resolve: (value?: unknown) => void, reject: (reason?: any) => void) => { accessSecretStorage(async (): Promise => { - // The remaining tasks (device dehydration and restoring - // key backup) may take some time due to processing many - // to-device messages in the case of device dehydration, or - // having many keys to restore in the case of key backups, - // so we allow the dialog to advance before this. + // `accessSecretStorage` will call `boostrapCrossSigning` and `bootstrapSecretStorage`, so that + // should be enough to ensure that our device is correctly cross-signed. + // + // The remaining tasks (device dehydration and restoring key backup) may take some time due to + // processing many to-device messages in the case of device dehydration, or having many keys to + // restore in the case of key backups, so we allow the dialog to advance before this. + // + // However, we need to keep the 4S key cached, so we stay inside `accessSecretStorage`. + logger.debug( + "SetupEncryptionStore.usePassphrase: cross-signing and secret storage set up; checking " + + "dehydration and backup in the background", + ); resolve(); await initialiseDehydration(); @@ -168,14 +169,17 @@ export class SetupEncryptionStore extends EventEmitter { }); if (await cli.getCrypto()?.getCrossSigningKeyId()) { + logger.debug("SetupEncryptionStore.usePassphrase: done"); this.phase = Phase.Done; this.emit("update"); } } catch (e) { - if (!(e instanceof AccessCancelledError)) { - logger.log(e); + if (e instanceof AccessCancelledError) { + logger.debug("SetupEncryptionStore.usePassphrase: user cancelled access to secret storage"); + } else { + logger.log("SetupEncryptionStore.usePassphrase: error", e); } - // this will throw if the user hits cancel, so ignore + this.phase = Phase.Intro; this.emit("update"); } diff --git a/test/SecurityManager-test.ts b/test/SecurityManager-test.ts index 15d1eb1dec..13d5f2f63f 100644 --- a/test/SecurityManager-test.ts +++ b/test/SecurityManager-test.ts @@ -31,7 +31,7 @@ describe("SecurityManager", () => { bootstrapSecretStorage: () => {}, } as unknown as CryptoApi; const client = stubClient(); - mocked(client.hasSecretStorageKey).mockResolvedValue(true); + client.secretStorage.hasKey = jest.fn().mockResolvedValue(true); mocked(client.getCrypto).mockReturnValue(crypto); // When I run accessSecretStorage @@ -48,7 +48,7 @@ describe("SecurityManager", () => { it("throws if crypto is unavailable", async () => { // Given a client with no crypto const client = stubClient(); - mocked(client.hasSecretStorageKey).mockResolvedValue(true); + client.secretStorage.hasKey = jest.fn().mockResolvedValue(true); mocked(client.getCrypto).mockReturnValue(undefined); // When I run accessSecretStorage From 44454618d80dafe8bb4d9722e8c80c8bb8ec8fc8 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 15 Jul 2024 07:16:24 +0100 Subject: [PATCH 26/59] [create-pull-request] automated change (#12776) Co-authored-by: github-merge-queue --- src/i18n/strings/cs.json | 2 -- src/i18n/strings/de_DE.json | 2 -- src/i18n/strings/el.json | 2 -- src/i18n/strings/eo.json | 2 -- src/i18n/strings/es.json | 2 -- src/i18n/strings/et.json | 2 -- src/i18n/strings/fa.json | 2 -- src/i18n/strings/fi.json | 2 -- src/i18n/strings/fr.json | 2 -- src/i18n/strings/gl.json | 2 -- src/i18n/strings/he.json | 2 -- src/i18n/strings/hu.json | 2 -- src/i18n/strings/id.json | 2 -- src/i18n/strings/is.json | 2 -- src/i18n/strings/it.json | 2 -- src/i18n/strings/ja.json | 2 -- src/i18n/strings/lo.json | 2 -- src/i18n/strings/lt.json | 2 -- src/i18n/strings/nl.json | 2 -- src/i18n/strings/pl.json | 15 +++++++-------- src/i18n/strings/pt_BR.json | 2 -- src/i18n/strings/ru.json | 2 -- src/i18n/strings/sk.json | 2 -- src/i18n/strings/sq.json | 2 -- src/i18n/strings/sv.json | 2 -- src/i18n/strings/uk.json | 2 -- src/i18n/strings/vi.json | 2 -- src/i18n/strings/zh_Hans.json | 2 -- src/i18n/strings/zh_Hant.json | 2 -- 29 files changed, 7 insertions(+), 64 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 7b885d2ac9..7da68c59d3 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -2642,7 +2642,6 @@ "delete_backup_confirm_description": "Opravdu? Pokud klíče nejsou správně zálohované můžete přijít o šifrované zprávy.", "e2ee_default_disabled_warning": "Správce vašeho serveru vypnul ve výchozím nastavení koncové šifrování v soukromých místnostech a přímých zprávách.", "enable_message_search": "Povolit vyhledávání v šifrovaných místnostech", - "encryption_individual_verification_mode": "Individuálně ověřit každou uživatelovu relaci a označit jí za důvěryhodnou, bez důvěry v křížový podpis.", "encryption_section": "Šifrování", "error_loading_key_backup_status": "Nepovedlo se načíst stav zálohy", "export_megolm_keys": "Exportovat šifrovací klíče místností", @@ -2661,7 +2660,6 @@ "key_backup_inactive": "Tato relace nezálohuje vaše klíče, ale už máte zálohu ze které je můžete obnovit.", "key_backup_inactive_warning": "Vaše klíče nejsou z této relace zálohovány.", "key_backup_latest_version": "Nejnovější verze zálohy na serveru:", - "manually_verify_all_sessions": "Ručně ověřit všechny relace", "message_search_disable_warning": "Když je to zakázané, zprávy v šifrovaných místnostech se nebudou objevovat ve výsledcích vyhledávání.", "message_search_disabled": "Bezpečně uchovávat zprávy na tomto zařízení aby se v nich dalo vyhledávat.", "message_search_enabled": { diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 5982ae172f..26ebeb05d6 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -2621,7 +2621,6 @@ "delete_backup_confirm_description": "Bist du sicher? Du wirst alle deine verschlüsselten Nachrichten verlieren, wenn deine Schlüssel nicht gut gesichert sind.", "e2ee_default_disabled_warning": "Deine Server-Administration hat die Ende-zu-Ende-Verschlüsselung für private Räume und Direktnachrichten standardmäßig deaktiviert.", "enable_message_search": "Nachrichtensuche in verschlüsselten Räumen aktivieren", - "encryption_individual_verification_mode": "Alle Sitzungen einzeln verifizieren, anstatt auch Sitzungen zu vertrauen, die durch Quersignierungen verifiziert sind.", "encryption_section": "Verschlüsselung", "error_loading_key_backup_status": "Konnte Status der Schlüsselsicherung nicht laden", "export_megolm_keys": "E2E-Raumschlüssel exportieren", @@ -2640,7 +2639,6 @@ "key_backup_inactive": "Diese Sitzung sichert deine Schlüssel nicht, aber du hast eine vorhandene Sicherung, die du wiederherstellen und in Zukunft hinzufügen kannst.", "key_backup_inactive_warning": "Deine Schlüssel werden von dieser Sitzung nicht gesichert.", "key_backup_latest_version": "Letzte Backup-Version auf diesen Server:", - "manually_verify_all_sessions": "Indirekte Sitzungen manuell verifizieren", "message_search_disable_warning": "Wenn deaktiviert, werden Nachrichten von verschlüsselten Räumen nicht in den Ergebnissen auftauchen.", "message_search_disabled": "Speichere verschlüsselte Nachrichten lokal, sodass sie deinen Suchergebnissen erscheinen können.", "message_search_enabled": { diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 78af9d60ea..2cc7aeafee 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -2108,7 +2108,6 @@ "delete_backup_confirm_description": "Είσαι σίγουρος? Θα χάσετε τα κρυπτογραφημένα μηνύματά σας εάν δε δημιουργηθούν σωστά αντίγραφα ασφαλείας των κλειδιών σας.", "e2ee_default_disabled_warning": "Ο διαχειριστής του διακομιστή σας έχει απενεργοποιήσει την κρυπτογράφηση από άκρο σε άκρο από προεπιλογή σε ιδιωτικά δωμάτια & άμεσα μηνύματα.", "enable_message_search": "Ενεργοποίηση αναζήτησης μηνυμάτων σε κρυπτογραφημένα δωμάτια", - "encryption_individual_verification_mode": "Επαληθεύστε μεμονωμένα κάθε συνεδρία που χρησιμοποιείται από έναν χρήστη για να την επισημάνετε ως αξιόπιστη, χωρίς να εμπιστεύεστε συσκευές με διασταυρούμενη υπογραφή.", "encryption_section": "Κρυπτογράφηση", "error_loading_key_backup_status": "Δεν είναι δυνατή η φόρτωση της κατάστασης του αντιγράφου ασφαλείας κλειδιού", "export_megolm_keys": "Εξαγωγή κλειδιών κρυπτογράφησης για το δωμάτιο", @@ -2122,7 +2121,6 @@ "key_backup_connect_prompt": "Συνδέστε αυτήν την συνεδρία με το αντίγραφο ασφαλείας κλειδιού πριν αποσυνδεθείτε για να αποφύγετε την απώλεια κλειδιών που μπορεί να υπάρχουν μόνο σε αυτήν την συνεδρία.", "key_backup_inactive": "Αυτή η συνεδρία δεν δημιουργεί αντίγραφα ασφαλείας των κλειδιών σας, αλλά έχετε ένα υπάρχον αντίγραφο ασφαλείας από το οποίο μπορείτε να επαναφέρετε και να προσθέσετε στη συνέχεια.", "key_backup_inactive_warning": "Δεν δημιουργούνται αντίγραφα ασφαλείας των κλειδιών σας από αυτήν την συνεδρία.", - "manually_verify_all_sessions": "Επαληθεύστε χειροκίνητα όλες τις απομακρυσμένες συνεδρίες", "message_search_disable_warning": "Εάν απενεργοποιηθεί, τα μηνύματα από κρυπτογραφημένα δωμάτια δε θα εμφανίζονται στα αποτελέσματα αναζήτησης.", "message_search_disabled": "Αποθηκεύστε με ασφάλεια κρυπτογραφημένα μηνύματα τοπικά για να εμφανίζονται στα αποτελέσματα αναζήτησης.", "message_search_enabled": { diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index 45da8d4d92..acf1dcebb0 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -1892,7 +1892,6 @@ "delete_backup_confirm_description": "Ĉu vi certas? Vi perdos ĉiujn viajn ĉifritajn mesaĝojn, se viaj ŝlosiloj ne estas savkopiitaj.", "e2ee_default_disabled_warning": "La administranto de via servilo malŝaltis implicitan tutvojan ĉifradon en privataj kaj individuaj ĉambroj.", "enable_message_search": "Ŝalti serĉon de mesaĝoj en ĉifritaj ĉambroj", - "encryption_individual_verification_mode": "Unuope kontroli ĉiun salutaĵon de uzanto por marki ĝin fidata, ne fidante delege subskribitajn aparatojn.", "encryption_section": "Ĉifrado", "error_loading_key_backup_status": "Ne povas enlegi staton de ŝlosila savkopio", "export_megolm_keys": "Elporti tutvoje ĉifrajn ŝlosilojn de la ĉambro", @@ -1906,7 +1905,6 @@ "key_backup_connect_prompt": "Konektu ĉi tiun salutaĵon al savkopiado de ŝlosiloj antaŭ ol vi adiaŭos, por ne perdi ŝlosilojn, kiuj povus troviĝi nur en ĉi tiu salutaĵo.", "key_backup_inactive": "Ĉi tiu salutaĵo ne savkopias viajn ŝlosilojn, sed vi jam havas savkopion, el kiu vi povas rehavi datumojn, kaj ilin kreskigi plue.", "key_backup_inactive_warning": "Viaj ŝlosiloj ne estas savkopiataj el ĉi tiu salutaĵo.", - "manually_verify_all_sessions": "Permane kontroli ĉiujn forajn salutaĵojn", "message_search_disable_warning": "Post malŝalto, mesaĝoj el ĉifritaj ĉambroj ne aperos en serĉorezultoj.", "message_search_disabled": "Sekure kaŝmemori ĉifritajn mesaĝojn loke, por aperigi ilin en serĉrezultoj.", "message_search_enabled": { diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 3e7c7c9cb6..c3ff20c5a6 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -2402,7 +2402,6 @@ "delete_backup_confirm_description": "¿Estás seguro? Perderás tus mensajes cifrados si las claves no se copian adecuadamente.", "e2ee_default_disabled_warning": "El administrador de tu servidor base ha desactivado el cifrado de extremo a extremo en salas privadas y mensajes directos.", "enable_message_search": "Activar la búsqueda de mensajes en salas cifradas", - "encryption_individual_verification_mode": "Verificar individualmente cada sesión utilizada por un usuario para marcarla como de confianza, no confiando en dispositivos de firma cruzada.", "encryption_section": "Cifrado", "error_loading_key_backup_status": "No se pudo cargar el estado de la copia de la clave", "export_megolm_keys": "Exportar claves de salas con cifrado de extremo a extremo", @@ -2416,7 +2415,6 @@ "key_backup_connect_prompt": "Conecte esta sesión a la copia de seguridad de las claves antes de firmar y así evitar perder las claves que sólo existen en esta sesión.", "key_backup_inactive": "Esta sesión no ha creado una copia de seguridad de tus llaves, pero tienes una copia de seguridad existente de la que puedes restaurar y añadir para proceder.", "key_backup_inactive_warning": "No se está haciendo una copia de seguridad de tus claves en esta sesión.", - "manually_verify_all_sessions": "Verificar manualmente todas las sesiones remotas", "message_search_disable_warning": "Si está desactivado, los mensajes de las salas cifradas no aparecerán en los resultados de búsqueda.", "message_search_disabled": "Almacenar localmente, de manera segura, a los mensajes cifrados localmente para que aparezcan en los resultados de búsqueda.", "message_search_enabled": { diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 5c2028d689..f2cc8b6922 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -2602,7 +2602,6 @@ "delete_backup_confirm_description": "Kas sa oled kindel? Kui sul muud varundust pole, siis kaotad ligipääsu oma krüptitud sõnumitele.", "e2ee_default_disabled_warning": "Sinu serveri haldur on lülitanud läbiva krüptimise omavahelistes jututubades ja otsesõnumites välja.", "enable_message_search": "Võta kasutusele sõnumite otsing krüptitud jututubades", - "encryption_individual_verification_mode": "Ära usalda risttunnustamist ning verifitseeri kasutaja iga sessioon eraldi.", "encryption_section": "Krüptimine", "error_loading_key_backup_status": "Võtmete varunduse oleku laadimine ei õnnestunud", "export_megolm_keys": "Ekspordi jututubade läbiva krüptimise võtmed", @@ -2618,7 +2617,6 @@ "key_backup_in_progress": "Varundan %(sessionsRemaining)s krüptovõtmeid…", "key_backup_inactive": "See sessioon ei varunda sinu krüptovõtmeid, aga sul on olemas varundus, millest saad taastada ning millele saad võtmeid lisada.", "key_backup_inactive_warning": "Sinu selle sessiooni krüptovõtmeid ei varundata.", - "manually_verify_all_sessions": "Verifitseeri käsitsi kõik välised sessioonid", "message_search_disable_warning": "Kui see seadistus pole kasutusel, siis krüptitud jututubade sõnumeid otsing ei vaata.", "message_search_disabled": "Turvaliselt puhverda krüptitud sõnumid kohalikku arvutisse ja võimalda kasutada neid otsingus.", "message_search_enabled": { diff --git a/src/i18n/strings/fa.json b/src/i18n/strings/fa.json index 0a7a41e281..0120a7e76d 100644 --- a/src/i18n/strings/fa.json +++ b/src/i18n/strings/fa.json @@ -1672,7 +1672,6 @@ "delete_backup_confirm_description": "آیا اطمینان دارید؟ در صورتی که از کلیدهای شما به درستی پشتیبان‌گیری نشده باشد، تمام پیام‌های رمزشده‌ی خود را از دست خواهید داد.", "e2ee_default_disabled_warning": "مدیر سرور شما قابلیت رمزنگاری سرتاسر برای اتاق‌ها و گفتگوهای خصوصی را به صورت پیش‌فرض غیرفعال کرده‌است.", "enable_message_search": "فعال‌سازی قابلیت جستجو در اتاق‌های رمزشده", - "encryption_individual_verification_mode": "به صورت جداگانه هر نشستی که با بقیه‌ی کاربران دارید را تائید کنید تا به عنوان نشست قابل اعتماد نشانه‌گذاری شود، با این کار می‌توانید به دستگاه‌های امضاء متقابل اعتماد نکنید.", "encryption_section": "رمزنگاری", "error_loading_key_backup_status": "امکان بارگیری و نمایش وضعیت کلید پشتیبان وجود ندارد", "export_megolm_keys": "استخراج (Export) کلیدهای رمزنگاری اتاق‌ها", @@ -1686,7 +1685,6 @@ "key_backup_connect_prompt": "پیش از خروج از حساب کاربری، این نشست را به کلید پشتیبان‌گیر متصل نمائید. با این کار مانع از گم‌شدن کلیدهای که فقط بر روی این نشست وجود دارند می‌شوید.", "key_backup_inactive": "این نشست از کلیدهای شما پشتیبان‌گیری نمی‌کند، با این حال شما یک نسخه‌ی پشتیبان موجود دارید که می‌توانید آن را بازیابی کنید.", "key_backup_inactive_warning": "کلید‌های شما از این نشست پشتیبان‌گیری نمی‌شود.", - "manually_verify_all_sessions": "به صورت دستی همه‌ی نشست‌ها را تائید نمائید", "message_search_disable_warning": "اگر غیر فعال شود، پیام‌های اتاق‌های رمزشده در نتایج جستجوها نمایش داده نمی‌شوند.", "message_search_disabled": "پیام‌های رمزشده را به صورتی محلی و امن ذخیره کرده تا در نتایج جستجو ظاهر شوند.", "message_search_enabled": { diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index 84ae773585..e1976e1bff 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -2278,7 +2278,6 @@ "delete_backup_confirm_description": "Oletko varma? Et voi lukea salattuja viestejäsi, mikäli avaimesi eivät ole kunnolla varmuuskopioituna.", "e2ee_default_disabled_warning": "Palvelimesi ylläpitäjä on poistanut päästä päähän -salauksen oletuksena käytöstä yksityisissä huoneissa ja yksityisviesteissä.", "enable_message_search": "Ota viestihaku salausta käyttävissä huoneissa käyttöön", - "encryption_individual_verification_mode": "Varmenna jokainen istunto erikseen, äläkä luota ristiinvarmennettuihin laitteisiin.", "encryption_section": "Salaus", "error_loading_key_backup_status": "Avainten varmuuskopionnin tilan lukeminen epäonnistui", "export_megolm_keys": "Tallenna osapuolten välisen salauksen huoneavaimet", @@ -2292,7 +2291,6 @@ "key_backup_connect_prompt": "Yhdistä tämä istunto avainten varmuuskopiointiin ennen uloskirjautumista, jotta et menetä avaimia, jotka ovat vain tässä istunnossa.", "key_backup_inactive": "Tämä istunto ei varmuuskopioi avaimiasi, mutta sillä on olemassaoleva varmuuskopio, jonka voit palauttaa ja lisätä jatkaaksesi.", "key_backup_inactive_warning": "Avaimiasi ei varmuuskopioida tästä istunnosta.", - "manually_verify_all_sessions": "Varmenna kaikki etäistunnot käsin", "message_search_disable_warning": "Jos ei ole käytössä, salattujen huoneiden viestejä ei näytetä hakutuloksissa.", "message_search_disabled": "Pidä salatut viestit turvallisessa välimuistissa, jotta ne näkyvät hakutuloksissa.", "message_search_enabled": { diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index ba4183e2df..9a35bd7f85 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -2672,7 +2672,6 @@ "delete_backup_confirm_description": "En êtes-vous sûr ? Vous perdrez vos messages chiffrés si vos clés ne sont pas sauvegardées correctement.", "e2ee_default_disabled_warning": "L’administrateur de votre serveur a désactivé le chiffrement de bout en bout par défaut dans les salons privés et les conversations privées.", "enable_message_search": "Activer la recherche de messages dans les salons chiffrés", - "encryption_individual_verification_mode": "Vérifiez individuellement chaque session utilisée par un utilisateur pour la marquer comme fiable, sans faire confiance aux appareils signés avec la signature croisée.", "encryption_section": "Chiffrement", "error_loading_key_backup_status": "Impossible de charger l’état de sauvegarde des clés", "export_megolm_keys": "Exporter les clés de chiffrement de salon", @@ -2691,7 +2690,6 @@ "key_backup_inactive": "Cette session ne sauvegarde pas vos clés, mais vous n’avez pas de sauvegarde existante que vous pouvez restaurer ou compléter à l’avenir.", "key_backup_inactive_warning": "Vos clés ne sont pas sauvegardées sur cette session.", "key_backup_latest_version": "Dernière version de la sauvegarde sur le serveur :", - "manually_verify_all_sessions": "Vérifier manuellement toutes les sessions à distance", "message_search_disable_warning": "Si l’option est désactivée, les messages des salons chiffrés n’apparaîtront pas dans les résultats de recherche.", "message_search_disabled": "Mettre en cache les messages chiffrés localement et de manière sécurisée pour qu’ils apparaissent dans les résultats de recherche.", "message_search_enabled": { diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 894b221096..1c799134b9 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -2228,7 +2228,6 @@ "delete_backup_confirm_description": "Estás seguro? Perderás as mensaxes cifradas se non tes unha copia de apoio das chaves de cifrado.", "e2ee_default_disabled_warning": "A administración do servidor desactivou por defecto o cifrado extremo-a-extremo en salas privadas e Mensaxes Directas.", "enable_message_search": "Activar a busca de mensaxes en salas cifradas", - "encryption_individual_verification_mode": "Verificar individualmente cada sesión utilizada pola usuaria para marcala como confiable, non confiando en dispositivos con sinatura cruzada.", "encryption_section": "Cifrado", "error_loading_key_backup_status": "Non se puido cargar o estado das chaves de apoio", "export_megolm_keys": "Exportar chaves E2E da sala", @@ -2242,7 +2241,6 @@ "key_backup_connect_prompt": "Conecta esta sesión ao gardado das chaves antes de desconectarte para evitar perder calquera chave que só puidese estar nesta sesión.", "key_backup_inactive": "Esta sesión non está facendo copia das chaves, pero tes unha copia de apoio existente que podes restablecer e engadir para seguir adiante.", "key_backup_inactive_warning": "As túas chaves non están a ser copiadas desde esta sesión.", - "manually_verify_all_sessions": "Verificar manualmente todas as sesións remotas", "message_search_disable_warning": "Se está desactivado, as mensaxes das salas cifradas non aparecerán nos resultados das buscas.", "message_search_disabled": "Gardar de xeito seguro mensaxes cifradas na caché local para que aparezan nos resultados de buscas.", "message_search_enabled": { diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index 360e0cd301..4cb91bc93e 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -1810,7 +1810,6 @@ "delete_backup_confirm_description": "האם אתה בטוח? תאבד את ההודעות המוצפנות שלך אם המפתחות שלך לא מגובים כראוי.", "e2ee_default_disabled_warning": "מנהל השרת שלך השבית הצפנה מקצה לקצה כברירת מחדל בחדרים פרטיים ובהודעות ישירות.", "enable_message_search": "אפשר חיפוש הודעות בחדרים מוצפנים", - "encryption_individual_verification_mode": "אמת בנפרד כל מושב שמשתמש בו כדי לסמן אותו כאמצעי מהימן, ולא אמון על מכשירים חתומים צולבים.", "encryption_section": "הצפנה", "error_loading_key_backup_status": "לא ניתן לטעון את מצב גיבוי המפתח", "export_megolm_keys": "ייצא מפתחות חדר E2E", @@ -1824,7 +1823,6 @@ "key_backup_connect_prompt": "חבר את ההפעלה הזו לגיבוי המפתח לפני היציאה, כדי למנוע אובדן מפתחות שיכולים להיות רק בפגישה זו.", "key_backup_inactive": "הפעלה זו אינה מגבה את המפתחות שלך , אך יש לך גיבוי קיים ממנו תוכל לשחזר ולהוסיף להמשך.", "key_backup_inactive_warning": "המפתחות שלך אינם מגובים מהתחברות זו .", - "manually_verify_all_sessions": "אמת באופן ידני את כל ההתחברויות", "message_search_disable_warning": "אם מושבת, הודעות מחדרים מוצפנים לא יופיעו בתוצאות החיפוש.", "message_search_disabled": "שמור באופן מאובטח הודעות מוצפנות באופן מקומי כדי שיופיעו בתוצאות החיפוש.", "message_search_enabled": { diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index b9fd14d926..8c0b1fcbd2 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -2563,7 +2563,6 @@ "delete_backup_confirm_description": "Biztos benne? Ha a kulcsai nincsenek megfelelően mentve, akkor elveszíti a titkosított üzeneteit.", "e2ee_default_disabled_warning": "A kiszolgáló rendszergazdája alapértelmezetten kikapcsolta a végpontok közötti titkosítást a privát szobákban és a közvetlen beszélgetésekben.", "enable_message_search": "Üzenetek keresésének bekapcsolása a titkosított szobákban", - "encryption_individual_verification_mode": "A felhasználó által használt munkamenetek ellenőrzése egyenként, nem bízva az eszközök közti aláírással rendelkező eszközökben.", "encryption_section": "Titkosítás", "error_loading_key_backup_status": "A mentett kulcsok állapotát nem lehet betölteni", "export_megolm_keys": "E2E szobakulcsok exportálása", @@ -2582,7 +2581,6 @@ "key_backup_inactive": "Ez az munkamenet nem menti el a kulcsait, de van létező mentése, amelyből helyre tudja állítani, és amelyhez hozzá tudja adni a továbbiakban.", "key_backup_inactive_warning": "A kulcsai nem kerülnek mentésre ebből a munkamenetből.", "key_backup_latest_version": "A legújabb biztonsági mentés verziója a kiszolgálón:", - "manually_verify_all_sessions": "Az összes távoli munkamenet kézi ellenőrzése", "message_search_disable_warning": "Ha nincs engedélyezve akkor a titkosított szobák üzenetei nem jelennek meg a keresések között.", "message_search_disabled": "A titkosított üzenetek biztonságos helyi gyorsítótárazása, hogy megjelenhessenek a keresési találatok között.", "message_search_enabled": { diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index 688241ba5f..746f175216 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -2596,7 +2596,6 @@ "delete_backup_confirm_description": "Apakah Anda yakin? Anda akan kehilangan pesan terenkripsi jika kunci Anda tidak dicadangkan dengan benar.", "e2ee_default_disabled_warning": "Admin server Anda telah menonaktifkan enkripsi ujung ke ujung secara bawaan di ruangan privat & Pesan Langsung.", "enable_message_search": "Aktifkan pencarian pesan di ruangan terenkripsi", - "encryption_individual_verification_mode": "Verifikasi setiap sesi yang digunakan oleh pengguna satu per satu untuk menandainya sebagai tepercaya, dan tidak memercayai perangkat yang ditandatangani silang.", "encryption_section": "Enkripsi", "error_loading_key_backup_status": "Tidak dapat memuat status pencadangan kunci", "export_megolm_keys": "Ekspor kunci ruangan enkripsi ujung ke ujung", @@ -2615,7 +2614,6 @@ "key_backup_inactive": "Sesi ini tidak mencadangkan kunci Anda, tetapi Anda memiliki cadangan yang ada yang dapat Anda pulihkan dan tambahkan untuk selanjutnya.", "key_backup_inactive_warning": "Kunci Anda tidak dicadangan dari sesi ini.", "key_backup_latest_version": "Versi cadangan terbaru di server:", - "manually_verify_all_sessions": "Verifikasi semua sesi jarak jauh secara manual", "message_search_disable_warning": "Jika dinonaktifkan, pesan dari ruangan terenkripsi tidak akan muncul di hasil pencarian.", "message_search_disabled": "Simpan pesan terenkripsi secara lokal dengan aman agar muncul di hasil pencarian.", "message_search_enabled": { diff --git a/src/i18n/strings/is.json b/src/i18n/strings/is.json index 16b5dd9abb..af7c28014e 100644 --- a/src/i18n/strings/is.json +++ b/src/i18n/strings/is.json @@ -2111,7 +2111,6 @@ "delete_backup_confirm_description": "Ertu viss? Þú munt tapa dulrituðu skilaboðunum þínum ef dulritunarlyklarnir þínir eru ekki rétt öryggisafritaðir.", "e2ee_default_disabled_warning": "Kerfisstjóri netþjónsins þíns hefur lokað á sjálfvirka dulritun í einkaspjallrásum og beinum skilaboðum.", "enable_message_search": "Virka skilaboðleit í dulrituðum spjallrásum", - "encryption_individual_verification_mode": "Sannreyndu hverja setu sem notandinn notar til að merkja hana sem treysta, án þess að treyta kross-undirrituðum tækjum.", "encryption_section": "Dulritun", "error_loading_key_backup_status": "Tókst ekki að hlaða inn stöðu öryggisafritunar dulritunarlykla", "export_megolm_keys": "Flytja út E2E dulritunarlykla spjallrásar", @@ -2124,7 +2123,6 @@ "key_backup_connect": "Tengja þessa setu við öryggisafrit af lykli", "key_backup_inactive": "Þessi seta er ekki að öryggisafrita dulritunarlyklana þína, en þú ert með fyrirliggjandi öryggisafrit sem þú getur endurheimt úr og notað til að halda áfram.", "key_backup_inactive_warning": "Dulritunarlyklarnir þínir eru ekki öryggisafritaðir úr þessari setu.", - "manually_verify_all_sessions": "Sannreyna handvirkt allar fjartengdar setur", "message_search_disable_warning": "Ef þetta er óvirkt, munu skilaboð frá dulrituðum spjallrásum ekki birtast í leitarniðurstöðum.", "message_search_disabled": "Setja dulrituð skilaboð leynilega í skyndiminni á tækinu svo þau birtist í leitarniðurstöðum.", "message_search_enabled": { diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index b2f99ba1b1..a5960e2d3a 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -2638,7 +2638,6 @@ "delete_backup_confirm_description": "Sei sicuro? Perderai i tuoi messaggi cifrati se non hai salvato adeguatamente le tue chiavi.", "e2ee_default_disabled_warning": "L'amministratore del server ha disattivato la crittografia end-to-end in modo predefinito nelle stanze private e nei messaggi diretti.", "enable_message_search": "Attiva la ricerca messaggi nelle stanze cifrate", - "encryption_individual_verification_mode": "Verifica individualmente ogni sessione usata da un utente per segnarla come fidata, senza fidarsi dei dispositivi a firma incrociata.", "encryption_section": "Crittografia", "error_loading_key_backup_status": "Impossibile caricare lo stato del backup delle chiavi", "export_megolm_keys": "Esporta chiavi E2E della stanza", @@ -2657,7 +2656,6 @@ "key_backup_inactive": "Questa sessione non sta facendo il backup delle tue chiavi, ma hai un backup esistente dal quale puoi ripristinare e che puoi usare da ora in poi.", "key_backup_inactive_warning": "Il backup chiavi non viene fatto per questa sessione.", "key_backup_latest_version": "Ultima versione del backup sul server:", - "manually_verify_all_sessions": "Verifica manualmente tutte le sessioni remote", "message_search_disable_warning": "Se disattivato, i messaggi delle stanze cifrate non appariranno nei risultati di ricerca.", "message_search_disabled": "Tieni in cache localmente i messaggi cifrati in modo sicuro affinché appaiano nei risultati di ricerca.", "message_search_enabled": { diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index 8f8a217cfd..788e305fbb 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -2396,7 +2396,6 @@ "delete_backup_confirm_description": "本当によろしいですか? もし鍵が正常にバックアップされていない場合、暗号化されたメッセージにアクセスできなくなります。", "e2ee_default_disabled_warning": "サーバー管理者は、非公開のルームとダイレクトメッセージで既定でエンドツーエンド暗号化を無効にしています。", "enable_message_search": "暗号化されたルームでメッセージの検索を有効にする", - "encryption_individual_verification_mode": "クロス署名された端末を信頼せず、ユーザーが使用する各セッションを個別に認証し、信頼済に設定。", "encryption_section": "暗号化", "error_loading_key_backup_status": "鍵のバックアップの状態を読み込めません", "export_megolm_keys": "ルームのエンドツーエンド暗号鍵をエクスポート", @@ -2412,7 +2411,6 @@ "key_backup_in_progress": "%(sessionsRemaining)s個の鍵をバックアップしています…", "key_backup_inactive": "このセッションでは鍵をバックアップしていませんが、復元に使用したり、今後鍵を追加したりできるバックアップがあります。", "key_backup_inactive_warning": "鍵はこのセッションからバックアップされていません。", - "manually_verify_all_sessions": "全てのリモートセッションを手動で認証", "message_search_disable_warning": "無効にすると、暗号化されたルームのメッセージは検索結果に表示されません。", "message_search_disabled": "検索結果の表示用に、暗号化されたメッセージをローカルに安全にキャッシュしています。", "message_search_enabled": { diff --git a/src/i18n/strings/lo.json b/src/i18n/strings/lo.json index 08ef6e739c..5cecf688f5 100644 --- a/src/i18n/strings/lo.json +++ b/src/i18n/strings/lo.json @@ -2136,7 +2136,6 @@ "delete_backup_confirm_description": "ທ່ານແນ່ໃຈບໍ່? ທ່ານຈະສູນເສຍຂໍ້ຄວາມທີ່ເຂົ້າລະຫັດໄວ້ຫາກກະແຈຂອງທ່ານບໍ່ຖືກສຳຮອງຂໍ້ມູນຢ່າງຖືກຕ້ອງ.", "e2ee_default_disabled_warning": "ຜູ້ຄຸມເຊີບເວີຂອງທ່ານໄດ້ປິດການນຳໃຊ້ການເຂົ້າລະຫັດແບບຕົ້ນທາງຮອດປາຍທາງໂດຍຄ່າເລີ່ມຕົ້ນໃນຫ້ອງສ່ວນຕົວ ແລະ ຂໍ້ຄວາມໂດຍກົງ.", "enable_message_search": "ເປີດໃຊ້ການຊອກຫາຂໍ້ຄວາມຢູ່ໃນຫ້ອງທີ່ຖືກເຂົ້າລະຫັດ", - "encryption_individual_verification_mode": "ຢືນຢັນແຕ່ລະລະບົບທີ່ໃຊ້ໂດຍຜູ້ໃຊ້ເພື່ອໝາຍວ່າເປັນທີ່ໜ້າເຊື່ອຖືໄດ້, ບໍ່ໄວ້ໃຈອຸປະກອນທີ່ cross-signed.", "encryption_section": "ການເຂົ້າລະຫັດ", "error_loading_key_backup_status": "ບໍ່ສາມາດໂຫຼດສະຖານະສຳຮອງລະຫັດໄດ້", "export_megolm_keys": "ສົ່ງກະແຈຫ້ອງ E2E ອອກ", @@ -2150,7 +2149,6 @@ "key_backup_connect_prompt": "ເຊື່ອມຕໍ່ລະບົບນີ້ກັບການສໍາຮອງກະແຈກ່ອນທີ່ຈະອອກຈາກລະບົບເພື່ອຫຼີກເວັ້ນການສູນເສຍກະແຈທີ່ອາດຢູ່ໃນລະບົບນີ້ເທົ່ານັ້ນ.", "key_backup_inactive": "ລະບົບນີ້ແມ່ນ ບໍ່ໄດ້ສໍາຮອງລະຫັດຂອງທ່ານ, ແຕ່ທ່ານມີການສໍາຮອງຂໍ້ມູນທີ່ມີຢູ່ແລ້ວທີ່ທ່ານສາມາດກູ້ຄືນຈາກ ແລະເພີ່ມຕໍ່ໄປ.", "key_backup_inactive_warning": "ກະແຈຂອງທ່ານ ບໍ່ຖືກສຳຮອງຂໍ້ມູນຈາກລະບົບນີ້.", - "manually_verify_all_sessions": "ຢັ້ງຢືນທຸກລະບົບທາງໄກດ້ວຍຕົນເອງ", "message_search_disable_warning": "ຖ້າປິດໃຊ້ງານ, ຂໍ້ຄວາມຈາກຫ້ອງທີ່ເຂົ້າລະຫັດຈະບໍ່ປາກົດຢູ່ໃນຜົນການຄົ້ນຫາ.", "message_search_disabled": "ເກັບຮັກສາຂໍ້ຄວາມທີ່ຖືກເຂົ້າລະຫັດໄວ້ຢ່າງປອດໄພຢູ່ໃນເຄື່ອງເພື່ອໃຫ້ປາກົດໃນຜົນການຄົ້ນຫາ.", "message_search_enabled": { diff --git a/src/i18n/strings/lt.json b/src/i18n/strings/lt.json index e7bc062aa5..cd092b5cbf 100644 --- a/src/i18n/strings/lt.json +++ b/src/i18n/strings/lt.json @@ -1703,7 +1703,6 @@ "delete_backup_confirm_description": "Ar tikrai? Jūs prarasite savo šifruotas žinutes, jei jūsų raktams nebus tinkamai sukurtos atsarginės kopijos.", "e2ee_default_disabled_warning": "Serverio administratorius išjungė visapusį šifravimą, kaip numatytą, privačiuose kambariuose ir Tiesioginėse Žinutėse.", "enable_message_search": "Įjungti žinučių paiešką užšifruotuose kambariuose", - "encryption_individual_verification_mode": "Individualiai patikrinkite kiekvieną vartotojo naudojamą seansą, kad pažymėtumėte jį kaip patikimą, nepasitikint kryžminiu pasirašymu patvirtintais įrenginiais.", "encryption_section": "Šifravimas", "error_loading_key_backup_status": "Nepavyko įkelti atsarginės raktų kopijos būklės", "export_megolm_keys": "Eksportuoti E2E (visapusio šifravimo) kambarių raktus", @@ -1717,7 +1716,6 @@ "key_backup_connect_prompt": "Prieš atsijungdami prijunkite šį seansą prie atsarginės raktų kopijos, kad neprarastumėte raktų, kurie gali būti tik šiame seanse.", "key_backup_inactive": "Šis seansas nekuria atsarginių raktų kopijų, bet jūs jau turite atsarginę kopiją iš kurios galite atkurti ir pridėti.", "key_backup_inactive_warning": "Jūsų raktams nėra daromos atsarginės kopijos iš šio seanso.", - "manually_verify_all_sessions": "Rankiniu būdu patvirtinti visus nuotolinius seansus", "message_search_disabled": "Šifruotas žinutes saugiai talpinkite lokaliai, kad jos būtų rodomos paieškos rezultatuose.", "message_search_enabled": { "one": "Saugiai talpinkite užšifruotas žinutes vietoje, kad jos būtų rodomos paieškos rezultatuose, naudojant %(size)s žinutėms iš %(rooms)s kambario saugoti.", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index 3a25d10c2d..e09544f451 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -2226,7 +2226,6 @@ "delete_backup_confirm_description": "Weet je het zeker? Je zal je versleutelde berichten verliezen als je sleutels niet correct geback-upt zijn.", "e2ee_default_disabled_warning": "De beheerder van je server heeft eind-tot-eind-versleuteling standaard uitgeschakeld in alle privékamers en directe gesprekken.", "enable_message_search": "Zoeken in versleutelde kamers inschakelen", - "encryption_individual_verification_mode": "Verifieer elke sessie die door een persoon wordt gebruikt afzonderlijk. Dit markeert hen als vertrouwd zonder te vertrouwen op kruislings ondertekende apparaten.", "encryption_section": "Versleuteling", "error_loading_key_backup_status": "Kan sleutelback-upstatus niet laden", "export_megolm_keys": "E2E-kamersleutels exporteren", @@ -2240,7 +2239,6 @@ "key_backup_connect_prompt": "Verbind deze sessie met de sleutelback-up voordat je jezelf afmeldt. Dit voorkomt dat je sleutels verliest die alleen op deze sessie voorkomen.", "key_backup_inactive": "Deze sessie maakt geen back-ups van je sleutels, maar je beschikt over een reeds bestaande back-up waaruit je kan herstellen en waaraan je nieuwe sleutels vanaf nu kunt toevoegen.", "key_backup_inactive_warning": "Jouw sleutels worden niet geback-upt van deze sessie.", - "manually_verify_all_sessions": "Handmatig alle externe sessies verifiëren", "message_search_disable_warning": "Dit moet aan staan om te kunnen zoeken in versleutelde kamers.", "message_search_disabled": "Sla versleutelde berichten veilig lokaal op om ze doorzoekbaar te maken.", "message_search_enabled": { diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index f2761b8c0f..82e2a50f7f 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -1612,7 +1612,7 @@ "all_messages_description": "Otrzymuj powiadomienie każdej wiadomości", "class_global": "Globalne", "class_other": "Inne", - "default": "Zwykły", + "default": "Domyślne", "email_pusher_app_display_name": "Powiadomienia e-mail", "enable_prompt_toast_description": "Włącz powiadomienia na pulpicie", "enable_prompt_toast_title": "Powiadomienia", @@ -1742,7 +1742,7 @@ "admin": "Administrator", "custom": "Własny (%(level)s)", "custom_level": "Własny poziom", - "default": "Zwykły", + "default": "Domyślne", "label": "Poziom uprawnień", "mod": "Moderator", "moderator": "Moderator", @@ -1948,7 +1948,7 @@ "hide_widgets_button": "Ukryj widżety", "n_people_asking_to_join": { "one": "Prosi o dołączenie", - "few": "%(count)s osób prosi o dołączenie", + "few": "%(count)s osoby proszą o dołączenie", "many": "%(count)s osób prosi o dołączenie" }, "room_is_public": "Ten pokój jest publiczny", @@ -2440,7 +2440,7 @@ "font_size": "Rozmiar czcionki", "font_size_default": "%(fontSize)s (domyślny)", "high_contrast": "Wysoki kontrast", - "image_size_default": "Zwykły", + "image_size_default": "Domyślne", "image_size_large": "Duży", "layout_bubbles": "Dymki wiadomości", "layout_irc": "IRC (eksperymentalny)", @@ -2732,7 +2732,6 @@ "dialog_title": "Ustawienia: Bezpieczeństwo i prywatność", "e2ee_default_disabled_warning": "Twój administrator serwera wyłączył domyślne szyfrowanie end-to-end w pokojach i wiadomościach prywatnych.", "enable_message_search": "Włącz wyszukiwanie wiadomości w szyfrowanych pokojach", - "encryption_individual_verification_mode": "Indywidualnie weryfikuj każdą sesję używaną przez użytkownika, aby oznaczyć ją jako zaufaną, nie ufając urządzeniom weryfikowanym krzyżowo.", "encryption_section": "Szyfrowanie", "error_loading_key_backup_status": "Nie można załadować stanu kopii zapasowej klucza", "export_megolm_keys": "Eksportuj klucze E2E pokojów", @@ -2751,7 +2750,6 @@ "key_backup_inactive": "Ta sesja nie wykonuje kopii zapasowej twoich kluczy, ale masz istniejącą kopię którą możesz przywrócić i uzupełniać w przyszłości.", "key_backup_inactive_warning": "Twoje klucze nie są zapisywanie na tej sesji.", "key_backup_latest_version": "Najnowsza wersja kopii zapasowej na serwerze:", - "manually_verify_all_sessions": "Ręcznie weryfikuj wszystkie zdalne sesje", "message_search_disable_warning": "Jeśli wyłączone, wiadomości z szyfrowanych pokojów nie pojawią się w wynikach wyszukiwania.", "message_search_disabled": "Bezpiecznie przechowuj lokalnie wiadomości szyfrowane, aby mogły się wyświetlać w wynikach wyszukiwania.", "message_search_enabled": { @@ -3258,7 +3256,7 @@ "creation_summary_dm": "%(creator)s utworzył tę wiadomość prywatną.", "creation_summary_room": "%(creator)s stworzył i skonfigurował pokój.", "decryption_failure": { - "blocked": "Nadawca zablokował Ci możliwość otrzymania tej wiadomości", + "blocked": "Nadawca zablokował Ci możliwość otrzymania tej wiadomości ponieważ twoje urządzenie nie zostało zweryfikowane", "historical_event_no_key_backup": "Historia wiadomości nie jest dostępna na tym urządzeniu", "historical_event_unverified_device": "Musisz zweryfikować to urządzenie, aby wyświetlić historię wiadomości", "historical_event_user_not_joined": "Nie masz dostępu do tej wiadomości", @@ -3518,7 +3516,8 @@ }, "read_receipt_title": { "one": "Odczytane przez %(count)s osobę", - "other": "Odczytane przez %(count)s osób" + "few": "Odczytane przez %(count)s osoby", + "many": "Odczytane przez %(count)s osób" }, "read_receipts_label": "Czytaj potwierdzenia", "redacted": { diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 989ac0297e..61c632dddf 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -1801,7 +1801,6 @@ "delete_backup_confirm_description": "Tem certeza? Você perderá suas mensagens criptografadas se não tiver feito o backup de suas chaves.", "e2ee_default_disabled_warning": "O administrador do servidor desativou a criptografia de ponta a ponta por padrão em salas privadas e em conversas.", "enable_message_search": "Ativar busca de mensagens em salas criptografadas", - "encryption_individual_verification_mode": "Verifique individualmente cada sessão usada por um usuário para marcá-la como confiável, em vez de confirmar em aparelhos autoverificados.", "encryption_section": "Criptografia", "error_loading_key_backup_status": "Não foi possível carregar o status do backup da chave", "export_megolm_keys": "Exportar chaves ponta-a-ponta da sala", @@ -1815,7 +1814,6 @@ "key_backup_connect_prompt": "Autorize esta sessão a fazer o backup de chaves antes de se desconectar, para evitar perder chaves que possam estar apenas nesta sessão.", "key_backup_inactive": "Esta sessão não está fazendo backup de suas chaves, mas você tem um backup existente que pode restaurar para continuar.", "key_backup_inactive_warning": "Suas chaves não estão sendo copiadas desta sessão.", - "manually_verify_all_sessions": "Verificar manualmente todas as sessões remotas", "message_search_disable_warning": "Se desativado, as mensagens de salas criptografadas não aparecerão em resultados de buscas.", "message_search_disabled": "Armazene mensagens criptografadas de forma segura localmente para que possam aparecer nos resultados das buscas.", "message_search_enabled": { diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index dbfde41d43..37beb7194a 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -2621,7 +2621,6 @@ "delete_backup_confirm_description": "Вы уверены? Зашифрованные сообщения будут безвозвратно утеряны при отсутствии соответствующего резервного копирования ваших ключей.", "e2ee_default_disabled_warning": "Администратор вашего сервера отключил сквозное шифрование по умолчанию в приватных комнатах и диалогах.", "enable_message_search": "Включить поиск сообщений в зашифрованных комнатах", - "encryption_individual_verification_mode": "Отдельно подтверждать каждый сеанс пользователя как доверенный, не доверяя кросс-подписанным устройствам.", "encryption_section": "Шифрование", "error_loading_key_backup_status": "Не удалось получить статус резервного копирования для ключей шифрования", "export_megolm_keys": "Экспорт ключей шифрования", @@ -2640,7 +2639,6 @@ "key_backup_inactive": "Это сеанс не сохраняет ваши ключи, но у вас есть резервная копия, из которой вы можете их восстановить.", "key_backup_inactive_warning": "Ваши ключи не резервируются с этом сеансе.", "key_backup_latest_version": "Последняя версия резервной копии на сервере:", - "manually_verify_all_sessions": "Подтверждать вручную все сеансы на других устройствах", "message_search_disable_warning": "Если этот параметр отключен, сообщения из зашифрованных комнат не будут отображаться в результатах поиска.", "message_search_disabled": "Безопасно кэшировать шифрованные сообщения локально, чтобы они появлялись в результатах поиска.", "message_search_enabled": { diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index faf57a637e..a8afeae2d6 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -2625,7 +2625,6 @@ "delete_backup_confirm_description": "Ste si istí? Ak nemáte správne zálohované šifrovacie kľúče, prídete o históriu šifrovaných konverzácií.", "e2ee_default_disabled_warning": "Správca vášho servera predvolene vypol end-to-end šifrovanie v súkromných miestnostiach a v priamych správach.", "enable_message_search": "Povoliť vyhľadávanie správ v šifrovaných miestnostiach", - "encryption_individual_verification_mode": "Individuálne overte každú používateľskú reláciu a označte ju za dôveryhodnú, bez dôvery krížovo podpísaných zariadení.", "encryption_section": "Šifrovanie", "error_loading_key_backup_status": "Nie je možné načítať stav zálohy kľúčov", "export_megolm_keys": "Exportovať end-to-end šifrovacie kľúče miestnosti", @@ -2644,7 +2643,6 @@ "key_backup_inactive": "Táto relácia nezálohuje vaše kľúče, ale máte jednu existujúcu zálohu, ktorú môžete obnoviť a pridať do budúcnosti.", "key_backup_inactive_warning": "Vaše kľúče nie sú zálohované z tejto relácie.", "key_backup_latest_version": "Najnovšia verzia zálohy na serveri:", - "manually_verify_all_sessions": "Manuálne overiť všetky relácie", "message_search_disable_warning": "Ak nie je povolené, správy zo zašifrovaných miestností sa nezobrazia vo výsledkoch vyhľadávania.", "message_search_disabled": "Bezpečne lokálne ukladať zašifrované správy do vyrovnávacej pamäte, aby sa zobrazovali vo výsledkoch vyhľadávania.", "message_search_enabled": { diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 736288371c..ab55e38ce4 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -2459,7 +2459,6 @@ "delete_backup_confirm_description": "Jeni i sigurt? Do të humbni mesazhet tuaj të fshehtëzuar, nëse kopjeruajtja për kyçet tuaj nuk bëhet si duhet.", "e2ee_default_disabled_warning": "Përgjegjësi i shërbyesit tuaj ka çaktivizuar fshehtëzimin skaj-më-skaj, si parazgjedhje, në dhoma private & Mesazhe të Drejtpërdrejtë.", "enable_message_search": "Aktivizo kërkim mesazhesh në dhoma të fshehtëzuara", - "encryption_individual_verification_mode": "Verifikoni individualisht çdo sesion të përdorur nga një përdorues, për t’i vënë shenjë si i besuar, duke mos besuar pajisje cross-signed.", "encryption_section": "Fshehtëzim", "error_loading_key_backup_status": "S’arrihet të ngarkohet gjendje kopjeruajtjeje kyçesh", "export_megolm_keys": "Eksporto kyçe dhome E2E", @@ -2475,7 +2474,6 @@ "key_backup_in_progress": "Po kopjeruhen kyçet për %(sessionsRemaining)s…", "key_backup_inactive": "Ky sesion nuk po bën kopjeruajtje të kyçeve tuaja, por keni një kopjeruajtje ekzistuese që mund ta përdorni për rimarrje dhe ta shtoni më tej.", "key_backup_inactive_warning": "Kyçet tuaj nuk po kopjeruhen nga ky sesion.", - "manually_verify_all_sessions": "Verifikoni dorazi krejt sesionet e largët", "message_search_disable_warning": "Në u çaktivizoftë, mesazhet prej dhomash të fshehtëzuara s’do të duken në përfundime kërkimi.", "message_search_disabled": "Ruaj lokalisht në mënyrë të sigurt në fshehtinë mesazhet që të shfaqen në përfundime kërkimi.", "message_search_enabled": { diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 834fa1c981..77fe12ee6e 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -2637,7 +2637,6 @@ "delete_backup_confirm_description": "Är du säker? Du kommer att förlora dina krypterade meddelanden om dina nycklar inte säkerhetskopieras ordentligt.", "e2ee_default_disabled_warning": "Din serveradministratör har inaktiverat totalsträckskryptering som förval för privata rum och direktmeddelanden.", "enable_message_search": "Aktivera meddelandesökning i krypterade rum", - "encryption_individual_verification_mode": "Verifiera individuellt varje session som används av en användare för att markera den som betrodd, och lita inte på korssignerade enheter.", "encryption_section": "Kryptering", "error_loading_key_backup_status": "Kunde inte ladda status för nyckelsäkerhetskopiering", "export_megolm_keys": "Exportera krypteringsrumsnycklar", @@ -2656,7 +2655,6 @@ "key_backup_inactive": "Den här servern säkerhetskopierar inte dina nycklar, men du har en existerande säkerhetskopia du kan återställa ifrån och lägga till till i framtiden.", "key_backup_inactive_warning": "Dina nycklar säkerhetskopieras inte från den här sessionen.", "key_backup_latest_version": "Senaste säkerhetskopieringsversionen på servern:", - "manually_verify_all_sessions": "Verifiera alla fjärrsessioner manuellt", "message_search_disable_warning": "Om den är inaktiverad visas inte meddelanden från krypterade rum i sökresultaten.", "message_search_disabled": "Cachar krypterade meddelanden säkert lokalt för att de ska visas i sökresultat.", "message_search_enabled": { diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 811e0234f8..1f3279ed9d 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -2562,7 +2562,6 @@ "delete_backup_confirm_description": "Ви впевнені? Ви втратите ваші зашифровані повідомлення якщо копія ключів не була створена коректно.", "e2ee_default_disabled_warning": "Адміністратором вашого сервера було вимкнено автоматичне наскрізне шифрування у приватних кімнатах і особистих повідомленнях.", "enable_message_search": "Увімкнути шукання повідомлень у зашифрованих кімнатах", - "encryption_individual_verification_mode": "Індивідуально звіряйте кожен сеанс, який використовується користувачем, щоб позначити його довіреним, не довіряючи пристроям перехресного підписування.", "encryption_section": "Шифрування", "error_loading_key_backup_status": "Не вдалося завантажити стан резервного копіювання ключа", "export_megolm_keys": "Експортувати ключі наскрізного шифрування кімнат", @@ -2581,7 +2580,6 @@ "key_backup_inactive": "Цей сеанс не створює резервну копію ваших ключів, але у вас є резервна копія, з якої ви можете їх відновити.", "key_backup_inactive_warning": "Резервна копія ваших ключів не створюється з цього сеансу.", "key_backup_latest_version": "Остання версія резервної копії на сервері:", - "manually_verify_all_sessions": "Звірити всі сеанси власноруч", "message_search_disable_warning": "Якщо вимкнути, пошук не показуватиме повідомлень зашифрованих кімнат.", "message_search_disabled": "Безпечно локально кешувати зашифровані повідомлення щоб вони з'являлись у результатах пошуку.", "message_search_enabled": { diff --git a/src/i18n/strings/vi.json b/src/i18n/strings/vi.json index 976976637e..a3e2488cdb 100644 --- a/src/i18n/strings/vi.json +++ b/src/i18n/strings/vi.json @@ -2336,7 +2336,6 @@ "delete_backup_confirm_description": "Bạn có chắc không? Bạn sẽ mất các tin nhắn được mã hóa nếu các khóa của bạn không được sao lưu đúng cách.", "e2ee_default_disabled_warning": "Người quản trị máy chủ của bạn đã vô hiệu hóa mã hóa đầu cuối theo mặc định trong phòng riêng và Tin nhắn trực tiếp.", "enable_message_search": "Bật tính năng tìm kiếm tin nhắn trong các phòng được mã hóa", - "encryption_individual_verification_mode": "Xác thực riêng từng phiên được người dùng sử dụng để đánh dấu phiên đó là đáng tin cậy, không tin cậy vào các thiết bị được xác thực chéo.", "encryption_section": "Mã hóa", "error_loading_key_backup_status": "Không thể tải trạng thái sao lưu khóa", "export_megolm_keys": "Xuất các mã khoá phòng E2E", @@ -2352,7 +2351,6 @@ "key_backup_in_progress": "Đang sao lưu %(sessionsRemaining)s khóa…", "key_backup_inactive": "Phiên này đang không sao lưu các khóa, nhưng bạn có một bản sao lưu hiện có, bạn có thể khôi phục và thêm vào để về sau.", "key_backup_inactive_warning": "Các khóa của bạn not being backed up from this session.", - "manually_verify_all_sessions": "Xác thực thủ công tất cả các phiên từ xa", "message_search_disable_warning": "Nếu bị tắt, tin nhắn từ các phòng được mã hóa sẽ không xuất hiện trong kết quả tìm kiếm.", "message_search_disabled": "Bộ nhớ cache an toàn các tin nhắn được mã hóa cục bộ để chúng xuất hiện trong kết quả tìm kiếm.", "message_search_enabled": { diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index c7d96fd36b..77dc330ef1 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -2353,7 +2353,6 @@ "delete_backup_confirm_description": "你确定吗?如果密钥没有正确地备份你将失去你的加密消息。", "e2ee_default_disabled_warning": "你的服务器管理员默认关闭了私人房间和私聊中的端到端加密。", "enable_message_search": "在加密房间中启用消息搜索", - "encryption_individual_verification_mode": "逐一验证用户的每一个会话以将其标记为已信任,而不信任交叉签名的设备。", "encryption_section": "加密", "error_loading_key_backup_status": "无法载入密钥备份状态", "export_megolm_keys": "导出房间的端到端加密密钥", @@ -2368,7 +2367,6 @@ "key_backup_connect_prompt": "在登出前连接此会话到密钥备份以避免丢失可能仅在此会话上的密钥。", "key_backup_inactive": "此会话未备份你的密钥,但如果你已有现存备份,你可以继续并从中恢复和向其添加。", "key_backup_inactive_warning": "你的密钥没有被此会话备份。", - "manually_verify_all_sessions": "手动验证所有远程会话", "message_search_disable_warning": "如果被禁用,加密房间内的消息不会显示在搜索结果中。", "message_search_disabled": "在本地安全地缓存加密消息以使其出现在搜索结果中。", "message_search_enabled": { diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index d8d4edc30a..f4ab63d787 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -2562,7 +2562,6 @@ "delete_backup_confirm_description": "您確定嗎?如果沒有正確備份金鑰的話,將會遺失所有加密訊息。", "e2ee_default_disabled_warning": "您的伺服器管理員已停用在私密聊天室與私人訊息中預設的端對端加密。", "enable_message_search": "在已加密的聊天室中啟用訊息搜尋", - "encryption_individual_verification_mode": "逐一手動驗證使用者的工作階段,將其標記為受信任階段,不透過裝置的交叉簽署機制來信任。", "encryption_section": "加密", "error_loading_key_backup_status": "無法載入金鑰備份狀態", "export_megolm_keys": "匯出聊天室的端對端加密金鑰", @@ -2578,7 +2577,6 @@ "key_backup_in_progress": "正在備份 %(sessionsRemaining)s 把金鑰…", "key_backup_inactive": "此工作階段並未備份您的金鑰,您可還原先前的備份後再繼續新增金鑰到備份內容中。", "key_backup_inactive_warning": "您並未備份此裝置的金鑰。", - "manually_verify_all_sessions": "手動驗證所有遠端工作階段", "message_search_disable_warning": "若停用,從加密聊天室傳來的訊息將不會出現在搜尋結果中。", "message_search_disabled": "將加密的訊息安全地在本機快取以出現在顯示結果中。", "message_search_enabled": { From 3221f7cadeb295d976bd3c0525eccb63862f30ad Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 15 Jul 2024 10:08:34 +0100 Subject: [PATCH 27/59] Align `widget_build_url_ignore_dm` with call behaviour switch between 1:1 and Widget (#12760) * Align `widget_build_url_ignore_dm` with call behaviour switch between 1:1 and Widget Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve coverage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/LegacyCallHandler.tsx | 16 +++--- src/hooks/room/useRoomCall.ts | 3 +- src/widgets/ManagedHybrid.ts | 42 +++++++--------- test/LegacyCallHandler-test.ts | 9 ++++ test/widgets/ManagedHybrid-test.ts | 79 +++++++++++++++++++++++++----- 5 files changed, 103 insertions(+), 46 deletions(-) diff --git a/src/LegacyCallHandler.tsx b/src/LegacyCallHandler.tsx index c8ee1d5c74..145784fe0c 100644 --- a/src/LegacyCallHandler.tsx +++ b/src/LegacyCallHandler.tsx @@ -861,6 +861,12 @@ export default class LegacyCallHandler extends EventEmitter { public async placeCall(roomId: string, type: CallType, transferee?: MatrixCall): Promise { const cli = MatrixClientPeg.safeGet(); + const room = cli.getRoom(roomId); + if (!room) { + logger.error(`Room ${roomId} does not exist.`); + return; + } + // Pause current broadcast, if any SdkContextClass.instance.voiceBroadcastPlaybacksStore.getCurrent()?.pause(); @@ -871,8 +877,8 @@ export default class LegacyCallHandler extends EventEmitter { } // We might be using managed hybrid widgets - if (isManagedHybridWidgetEnabled(roomId)) { - await addManagedHybridWidget(roomId); + if (isManagedHybridWidgetEnabled(room)) { + await addManagedHybridWidget(room); return; } @@ -902,12 +908,6 @@ export default class LegacyCallHandler extends EventEmitter { return; } - const room = cli.getRoom(roomId); - if (!room) { - logger.error(`Room ${roomId} does not exist.`); - return; - } - // We leave the check for whether there's already a call in this room until later, // otherwise it can race. diff --git a/src/hooks/room/useRoomCall.ts b/src/hooks/room/useRoomCall.ts index fd2ed9c750..8dc18040a1 100644 --- a/src/hooks/room/useRoomCall.ts +++ b/src/hooks/room/useRoomCall.ts @@ -271,8 +271,7 @@ export const useRoomCall = ( }, [isViewingCall, room.roomId]); // We hide the voice call button if it'd have the same effect as the video call button - let hideVoiceCallButton = - isManagedHybridWidgetEnabled(room.roomId) || !callOptions.includes(PlatformCallType.LegacyCall); + let hideVoiceCallButton = isManagedHybridWidgetEnabled(room) || !callOptions.includes(PlatformCallType.LegacyCall); let hideVideoCallButton = false; // We hide both buttons if they require widgets but widgets are disabled. if (memberCount > 2 && !SettingsStore.getValue(UIFeature.Widgets)) { diff --git a/src/widgets/ManagedHybrid.ts b/src/widgets/ManagedHybrid.ts index ff06c295e6..6617933d97 100644 --- a/src/widgets/ManagedHybrid.ts +++ b/src/widgets/ManagedHybrid.ts @@ -16,6 +16,7 @@ limitations under the License. import { IWidget } from "matrix-widget-api"; import { logger } from "matrix-js-sdk/src/logger"; +import { Room } from "matrix-js-sdk/src/matrix"; import { MatrixClientPeg } from "../MatrixClientPeg"; import { getCallBehaviourWellKnown } from "../utils/WellKnownUtils"; @@ -24,7 +25,7 @@ import { IStoredLayout, WidgetLayoutStore } from "../stores/widgets/WidgetLayout import WidgetEchoStore from "../stores/WidgetEchoStore"; import WidgetStore, { IApp } from "../stores/WidgetStore"; import SdkConfig from "../SdkConfig"; -import DMRoomMap from "../utils/DMRoomMap"; +import { getJoinedNonFunctionalMembers } from "../utils/room/getJoinedNonFunctionalMembers"; /* eslint-disable camelcase */ interface IManagedHybridWidgetData { @@ -34,8 +35,9 @@ interface IManagedHybridWidgetData { } /* eslint-enable camelcase */ -function getWidgetBuildUrl(roomId: string): string | undefined { - const isDm = !!DMRoomMap.shared().getUserIdForRoomId(roomId); +function getWidgetBuildUrl(room: Room): string | undefined { + const functionalMembers = getJoinedNonFunctionalMembers(room); + const isDm = functionalMembers.length === 2; if (SdkConfig.get().widget_build_url) { if (isDm && SdkConfig.get().widget_build_url_ignore_dm) { return undefined; @@ -51,35 +53,29 @@ function getWidgetBuildUrl(roomId: string): string | undefined { return wellKnown?.widget_build_url; } -export function isManagedHybridWidgetEnabled(roomId: string): boolean { - return !!getWidgetBuildUrl(roomId); +export function isManagedHybridWidgetEnabled(room: Room): boolean { + return !!getWidgetBuildUrl(room); } -export async function addManagedHybridWidget(roomId: string): Promise { - const cli = MatrixClientPeg.safeGet(); - const room = cli.getRoom(roomId); - if (!room) { - return; - } - +export async function addManagedHybridWidget(room: Room): Promise { // Check for permission - if (!WidgetUtils.canUserModifyWidgets(cli, roomId)) { - logger.error(`User not allowed to modify widgets in ${roomId}`); + if (!WidgetUtils.canUserModifyWidgets(room.client, room.roomId)) { + logger.error(`User not allowed to modify widgets in ${room.roomId}`); return; } // Get widget data /* eslint-disable-next-line camelcase */ - const widgetBuildUrl = getWidgetBuildUrl(roomId); + const widgetBuildUrl = getWidgetBuildUrl(room); if (!widgetBuildUrl) { return; } let widgetData: IManagedHybridWidgetData; try { - const response = await fetch(`${widgetBuildUrl}?roomId=${roomId}`); + const response = await fetch(`${widgetBuildUrl}?roomId=${room.roomId}`); widgetData = await response.json(); } catch (e) { - logger.error(`Managed hybrid widget builder failed for room ${roomId}`, e); + logger.error(`Managed hybrid widget builder failed for room ${room.roomId}`, e); return; } if (!widgetData) { @@ -88,21 +84,21 @@ export async function addManagedHybridWidget(roomId: string): Promise { const { widget_id: widgetId, widget: widgetContent, layout } = widgetData; // Ensure the widget is not already present in the room - let widgets = WidgetStore.instance.getApps(roomId); - const existing = widgets.some((w) => w.id === widgetId) || WidgetEchoStore.roomHasPendingWidgets(roomId, []); + let widgets = WidgetStore.instance.getApps(room.roomId); + const existing = widgets.some((w) => w.id === widgetId) || WidgetEchoStore.roomHasPendingWidgets(room.roomId, []); if (existing) { - logger.error(`Managed hybrid widget already present in room ${roomId}`); + logger.error(`Managed hybrid widget already present in room ${room.roomId}`); return; } // Add the widget try { - await WidgetUtils.setRoomWidgetContent(cli, roomId, widgetId, { + await WidgetUtils.setRoomWidgetContent(room.client, room.roomId, widgetId, { ...widgetContent, "io.element.managed_hybrid": true, }); } catch (e) { - logger.error(`Unable to add managed hybrid widget in room ${roomId}`, e); + logger.error(`Unable to add managed hybrid widget in room ${room.roomId}`, e); return; } @@ -110,7 +106,7 @@ export async function addManagedHybridWidget(roomId: string): Promise { if (!WidgetLayoutStore.instance.canCopyLayoutToRoom(room)) { return; } - widgets = WidgetStore.instance.getApps(roomId); + widgets = WidgetStore.instance.getApps(room.roomId); const installedWidget = widgets.find((w) => w.id === widgetId); if (!installedWidget) { return; diff --git a/test/LegacyCallHandler-test.ts b/test/LegacyCallHandler-test.ts index 005119cb7b..c310db55ab 100644 --- a/test/LegacyCallHandler-test.ts +++ b/test/LegacyCallHandler-test.ts @@ -52,6 +52,7 @@ import { mkVoiceBroadcastInfoStateEvent } from "./voice-broadcast/utils/test-uti import { SdkContextClass } from "../src/contexts/SDKContext"; import Modal from "../src/Modal"; import { createAudioContext } from "../src/audio/compat"; +import * as ManagedHybrid from "../src/widgets/ManagedHybrid"; jest.mock("../src/Modal"); @@ -315,6 +316,7 @@ describe("LegacyCallHandler", () => { document.body.removeChild(audioElement); SdkConfig.reset(); + jest.restoreAllMocks(); }); it("should look up the correct user and start a call in the room when a phone number is dialled", async () => { @@ -403,6 +405,13 @@ describe("LegacyCallHandler", () => { expect(callHandler.getCallForRoom(NATIVE_ROOM_CHARLIE)).toBe(fakeCall); }); + it("should place calls using managed hybrid widget if enabled", async () => { + const spy = jest.spyOn(ManagedHybrid, "addManagedHybridWidget"); + jest.spyOn(ManagedHybrid, "isManagedHybridWidgetEnabled").mockReturnValue(true); + await callHandler.placeCall(NATIVE_ROOM_ALICE, CallType.Voice); + expect(spy).toHaveBeenCalledWith(MatrixClientPeg.safeGet().getRoom(NATIVE_ROOM_ALICE)); + }); + describe("when listening to a voice broadcast", () => { let voiceBroadcastPlayback: VoiceBroadcastPlayback; diff --git a/test/widgets/ManagedHybrid-test.ts b/test/widgets/ManagedHybrid-test.ts index b91db09dc1..05093ed0d4 100644 --- a/test/widgets/ManagedHybrid-test.ts +++ b/test/widgets/ManagedHybrid-test.ts @@ -14,38 +14,91 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { isManagedHybridWidgetEnabled } from "../../src/widgets/ManagedHybrid"; -import DMRoomMap from "../../src/utils/DMRoomMap"; +import { Room } from "matrix-js-sdk/src/matrix"; +import { logger } from "matrix-js-sdk/src/logger"; +import fetchMock from "fetch-mock-jest"; + +import { addManagedHybridWidget, isManagedHybridWidgetEnabled } from "../../src/widgets/ManagedHybrid"; import { stubClient } from "../test-utils"; import SdkConfig from "../../src/SdkConfig"; +import WidgetUtils from "../../src/utils/WidgetUtils"; +import { WidgetLayoutStore } from "../../src/stores/widgets/WidgetLayoutStore"; + +jest.mock("../../src/utils/room/getJoinedNonFunctionalMembers", () => ({ + getJoinedNonFunctionalMembers: jest.fn().mockReturnValue([1, 2]), +})); describe("isManagedHybridWidgetEnabled", () => { - let dmRoomMap: DMRoomMap; + let room: Room; beforeEach(() => { - stubClient(); - dmRoomMap = { - getUserIdForRoomId: jest.fn().mockReturnValue("@user:server"), - } as unknown as DMRoomMap; - DMRoomMap.setShared(dmRoomMap); + const client = stubClient(); + room = new Room("!room:server", client, client.getSafeUserId()); }); it("should return false if widget_build_url is unset", () => { - expect(isManagedHybridWidgetEnabled("!room:server")).toBeFalsy(); + expect(isManagedHybridWidgetEnabled(room)).toBeFalsy(); }); - it("should return true for DMs when widget_build_url_ignore_dm is unset", () => { + it("should return true for 1-1 rooms when widget_build_url_ignore_dm is unset", () => { SdkConfig.put({ widget_build_url: "https://url", }); - expect(isManagedHybridWidgetEnabled("!room:server")).toBeTruthy(); + expect(isManagedHybridWidgetEnabled(room)).toBeTruthy(); }); - it("should return false for DMs when widget_build_url_ignore_dm is true", () => { + it("should return false for 1-1 rooms when widget_build_url_ignore_dm is true", () => { SdkConfig.put({ widget_build_url: "https://url", widget_build_url_ignore_dm: true, }); - expect(isManagedHybridWidgetEnabled("!room:server")).toBeFalsy(); + expect(isManagedHybridWidgetEnabled(room)).toBeFalsy(); + }); +}); + +describe("addManagedHybridWidget", () => { + let room: Room; + + beforeEach(() => { + const client = stubClient(); + room = new Room("!room:server", client, client.getSafeUserId()); + }); + + it("should noop if user lacks permission", async () => { + const logSpy = jest.spyOn(logger, "error").mockImplementation(); + jest.spyOn(WidgetUtils, "canUserModifyWidgets").mockReturnValue(false); + + fetchMock.mockClear(); + await addManagedHybridWidget(room); + expect(logSpy).toHaveBeenCalledWith("User not allowed to modify widgets in !room:server"); + expect(fetchMock).toHaveBeenCalledTimes(0); + }); + + it("should noop if no widget_build_url", async () => { + jest.spyOn(WidgetUtils, "canUserModifyWidgets").mockReturnValue(true); + + fetchMock.mockClear(); + await addManagedHybridWidget(room); + expect(fetchMock).toHaveBeenCalledTimes(0); + }); + + it("should add the widget successfully", async () => { + fetchMock.get("https://widget-build-url/?roomId=!room:server", { + widget_id: "WIDGET_ID", + widget: { key: "value" }, + }); + jest.spyOn(WidgetUtils, "canUserModifyWidgets").mockReturnValue(true); + jest.spyOn(WidgetLayoutStore.instance, "canCopyLayoutToRoom").mockReturnValue(true); + const setRoomWidgetContentSpy = jest.spyOn(WidgetUtils, "setRoomWidgetContent").mockResolvedValue(); + SdkConfig.put({ + widget_build_url: "https://widget-build-url", + }); + + await addManagedHybridWidget(room); + expect(fetchMock).toHaveBeenCalledWith("https://widget-build-url?roomId=!room:server"); + expect(setRoomWidgetContentSpy).toHaveBeenCalledWith(room.client, room.roomId, "WIDGET_ID", { + "key": "value", + "io.element.managed_hybrid": true, + }); }); }); From 2e0b5bb4624846ae223a04e3b7b2c89358e1795f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 15 Jul 2024 11:02:23 +0100 Subject: [PATCH 28/59] Fix edge case of landing on 3pid email link with registration disabled (#12771) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- src/components/structures/MatrixChat.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/components/structures/MatrixChat.tsx b/src/components/structures/MatrixChat.tsx index 70c4f9ce5f..f9d6db3f53 100644 --- a/src/components/structures/MatrixChat.tsx +++ b/src/components/structures/MatrixChat.tsx @@ -551,7 +551,10 @@ export default class MatrixChat extends React.PureComponent { .then((loadedSession) => { if (!loadedSession) { // fall back to showing the welcome screen... unless we have a 3pid invite pending - if (ThreepidInviteStore.instance.pickBestInvite()) { + if ( + ThreepidInviteStore.instance.pickBestInvite() && + SettingsStore.getValue(UIFeature.Registration) + ) { dis.dispatch({ action: "start_registration" }); } else { dis.dispatch({ action: "view_welcome_page" }); @@ -951,6 +954,11 @@ export default class MatrixChat extends React.PureComponent { } private async startRegistration(params: { [key: string]: string }): Promise { + if (!SettingsStore.getValue(UIFeature.Registration)) { + this.showScreen("welcome"); + return; + } + const newState: Partial = { view: Views.REGISTER, }; From 38e1da56260fcb5ba7a8fc33a4bc1fc0493b074a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 15 Jul 2024 11:02:29 +0100 Subject: [PATCH 29/59] Fix inability to change accent colour consistently in custom theming (#12772) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/themes/light-custom/css/_custom.pcss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/res/themes/light-custom/css/_custom.pcss b/res/themes/light-custom/css/_custom.pcss index 7fadb2cd0a..7912902645 100644 --- a/res/themes/light-custom/css/_custom.pcss +++ b/res/themes/light-custom/css/_custom.pcss @@ -18,7 +18,7 @@ $font-family: var(--font-family, $font-family); $monospace-font-family: var(--font-family-monospace, $monospace-font-family); /* Colors from Figma Compound https://www.figma.com/file/X4XTH9iS2KGJ2wFKDqkyed/Compound?node-id=559%3A741 */ -$accent: var(--accent, $accent); +$accent: var(--accent-color, $accent); $alert: var(--alert, $alert); $links: var(--links, $links); $primary-content: var(--primary-content, $primary-content); From b4ef5d3cc3ae414e5469b92d1cc9799f8a4c85b6 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 15 Jul 2024 11:33:41 +0100 Subject: [PATCH 30/59] Fix HTML export missing a bunch of Compound variables (#12774) --- package.json | 2 + .../e2e/chat-export/html-export.spec.ts | 132 ++++++++++++++++++ .../html-export.spec.ts/html-export-linux.png | Bin 0 -> 40662 bytes src/utils/exportUtils/HtmlExport.tsx | 132 +++++++++--------- src/utils/exportUtils/exportCSS.ts | 90 ++++++------ src/utils/exportUtils/exportCustomCSS.css | 5 + .../__snapshots__/HTMLExport-test.ts.snap | 122 ++++++++-------- yarn.lock | 5 + 8 files changed, 315 insertions(+), 173 deletions(-) create mode 100644 playwright/e2e/chat-export/html-export.spec.ts create mode 100644 playwright/snapshots/chat-export/html-export.spec.ts/html-export-linux.png diff --git a/package.json b/package.json index 4250a9d1ca..14635fdeee 100644 --- a/package.json +++ b/package.json @@ -91,6 +91,7 @@ "classnames": "^2.2.6", "commonmark": "^0.31.0", "counterpart": "^0.18.6", + "css-tree": "^2.3.1", "diff-dom": "^5.0.0", "diff-match-patch": "^1.0.5", "emojibase-regex": "15.3.2", @@ -167,6 +168,7 @@ "@types/commonmark": "^0.27.4", "@types/content-type": "^1.1.5", "@types/counterpart": "^0.18.1", + "@types/css-tree": "^2.3.8", "@types/diff-match-patch": "^1.0.32", "@types/escape-html": "^1.0.1", "@types/express": "^4.17.21", diff --git a/playwright/e2e/chat-export/html-export.spec.ts b/playwright/e2e/chat-export/html-export.spec.ts new file mode 100644 index 0000000000..947aa2c1bc --- /dev/null +++ b/playwright/e2e/chat-export/html-export.spec.ts @@ -0,0 +1,132 @@ +/* +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 os from "node:os"; +import path from "node:path"; +import * as fsp from "node:fs/promises"; +import * as fs from "node:fs"; +import JSZip from "jszip"; + +import { test, expect } from "../../element-web-test"; + +// Based on https://github.com/Stuk/jszip/issues/466#issuecomment-2097061912 +async function extractZipFileToPath(file: string, outputPath: string): Promise { + if (!fs.existsSync(outputPath)) { + fs.mkdirSync(outputPath, { recursive: true }); + } + + const data = await fsp.readFile(file); + const zip = await JSZip.loadAsync(data, { createFolders: true }); + + await new Promise((resolve, reject) => { + let entryCount = 0; + let errorOut = false; + + zip.forEach(() => { + entryCount++; + }); // there is no other way to count the number of entries within the zip file. + + zip.forEach((relativePath, zipEntry) => { + if (errorOut) { + return; + } + + const outputEntryPath = path.join(outputPath, relativePath); + if (zipEntry.dir) { + if (!fs.existsSync(outputEntryPath)) { + fs.mkdirSync(outputEntryPath, { recursive: true }); + } + + entryCount--; + + if (entryCount === 0) { + resolve(); + } + } else { + void zipEntry + .async("blob") + .then(async (content) => Buffer.from(await content.arrayBuffer())) + .then((buffer) => { + const stream = fs.createWriteStream(outputEntryPath); + stream.write(buffer, (error) => { + if (error) { + reject(error); + errorOut = true; + } + }); + stream.on("finish", () => { + entryCount--; + + if (entryCount === 0) { + resolve(); + } + }); + stream.end(); // extremely important on Windows. On Mac / Linux, not so much since those platforms allow multiple apps to read from the same file. Windows doesn't allow that. + }) + .catch((e) => { + errorOut = true; + reject(e); + }); + } + }); + }); + + return zip; +} + +test.describe("HTML Export", () => { + test.use({ + displayName: "Alice", + room: async ({ app, user }, use) => { + const roomId = await app.client.createRoom({ name: "Important Room" }); + await app.viewRoomByName("Important Room"); + await use({ roomId }); + }, + }); + + test("should export html successfully and match screenshot", async ({ page, app, room }) => { + // Send a bunch of messages to populate the room + for (let i = 1; i < 10; i++) { + await app.client.sendMessage(room.roomId, { body: `Testing ${i}`, msgtype: "m.text" }); + } + + // Wait for all the messages to be displayed + await expect( + page.locator(".mx_EventTile_last .mx_MTextBody .mx_EventTile_body").getByText("Testing 9"), + ).toBeVisible(); + + await page.getByRole("button", { name: "Room info" }).click(); + await page.getByRole("menuitem", { name: "Export Chat" }).click(); + + const downloadPromise = page.waitForEvent("download"); + await page.getByRole("button", { name: "Export", exact: true }).click(); + const download = await downloadPromise; + + const dirPath = path.join(os.tmpdir(), "html-export-test"); + const zipPath = `${dirPath}.zip`; + await download.saveAs(zipPath); + + const zip = await extractZipFileToPath(zipPath, dirPath); + await page.goto(`file://${dirPath}/${Object.keys(zip.files)[0]}/messages.html`); + await expect(page).toMatchScreenshot("html-export.png", { + mask: [ + page.getByText("This is the start of export", { exact: false }), + page.locator(".mx_DateSeparator_dateHeading"), + page.locator(".mx_MessageTimestamp"), + ], + }); + }); +}); diff --git a/playwright/snapshots/chat-export/html-export.spec.ts/html-export-linux.png b/playwright/snapshots/chat-export/html-export.spec.ts/html-export-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..99af1a757ba327b750e7859f9e8436102a2f8d7f GIT binary patch literal 40662 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 ${_t("export_chat|html_title")} - -
-
-
-
-
-
-
-
- ${roomAvatar} -
-
-
-
- ${safeRoomName} -
-
-
${safeTopic}
-
-
- ${previousMessagesLink} -
-
-
-
-
-
    +
    +
    +
    +
    +
    +
    +
    +
    + ${roomAvatar} +
    +
    +
    +
    - ${ - currentPage == 0 - ? `
    - ${roomAvatar} -

    ${safeRoomName}

    -

    ${safeCreatedText}

    ${safeExportedText}

    -
    -

    ${safeTopicText}

    -
    ` - : "" - } - ${content} -
+ ${safeRoomName} +
+
+
${safeTopic}
+
+
+ ${previousMessagesLink} +
+
+
+
+
+
    + ${ + currentPage == 0 + ? `
    + ${roomAvatar} +

    ${safeRoomName}

    +

    ${safeCreatedText}

    ${safeExportedText}

    +
    +

    ${safeTopicText}

    +
    ` + : "" + } + ${content} +
+
+
+
+
+
+
+
-
-
-
-
-
+ ${nextMessagesLink} +
-
- ${nextMessagesLink} -
-
`; diff --git a/src/utils/exportUtils/exportCSS.ts b/src/utils/exportUtils/exportCSS.ts index bd7ddac01b..15716ad544 100644 --- a/src/utils/exportUtils/exportCSS.ts +++ b/src/utils/exportUtils/exportCSS.ts @@ -14,74 +14,80 @@ See the License for the specific language governing permissions and limitations under the License. */ +import type { Rule, StyleSheet } from "css-tree"; + import customCSS from "!!raw-loader!./exportCustomCSS.css"; const cssSelectorTextClassesRegex = /\.[\w-]+/g; function mutateCssText(css: string): string { // replace used fonts so that we don't have to bundle Inter & Inconsalata + const sansFont = `-apple-system, BlinkMacSystemFont, avenir next, + avenir, segoe ui, helvetica neue, helvetica, Ubuntu, roboto, noto, arial, sans-serif`; return css - .replace( - /font-family: ?(Inter|'Inter'|"Inter")/g, - `font-family: -apple-system, BlinkMacSystemFont, avenir next, - avenir, segoe ui, helvetica neue, helvetica, Ubuntu, roboto, noto, arial, sans-serif`, - ) + .replace(/font-family: ?(Inter|'Inter'|"Inter")/g, `font-family: ${sansFont}`) + .replace(/--cpd-font-family-sans: ?(Inter|'Inter'|"Inter")/g, `--cpd-font-family-sans: ${sansFont}`) .replace( /font-family: ?Inconsolata/g, "font-family: Menlo, Consolas, Monaco, Liberation Mono, Lucida Console, monospace", ); } -function isLightTheme(sheet: CSSStyleSheet): boolean { - return (sheet.ownerNode)?.dataset.mxTheme?.toLowerCase() === "light"; -} +function includeRule(rule: Rule, usedClasses: Set): boolean { + if (rule.prelude.type === "Raw") { + // cull empty rules + if (rule.block.children.isEmpty) return false; -async function getRulesFromCssFile(path: string): Promise { - const doc = document.implementation.createHTMLDocument(""); - const styleElement = document.createElement("style"); - - const res = await fetch(path); - styleElement.textContent = await res.text(); - // the style will only be parsed once it is added to a document - doc.body.appendChild(styleElement); - - return styleElement.sheet!; + return rule.prelude.value.split(",").some((subselector) => { + const classes = subselector.trim().match(cssSelectorTextClassesRegex); + if (classes && !classes.every((c) => usedClasses.has(c.substring(1)))) { + return false; + } + return true; + }); + } + return true; } // naively culls unused css rules based on which classes are present in the html, // doesn't cull rules which won't apply due to the full selector not matching but gets rid of a LOT of cruft anyway. +// We cannot use document.styleSheets as it does not handle variables in shorthand properties sanely, +// see https://github.com/element-hq/element-web/issues/26761 const getExportCSS = async (usedClasses: Set): Promise => { - // only include bundle.css and the data-mx-theme=light styling - const stylesheets = Array.from(document.styleSheets).filter((s) => { - return s.href?.endsWith("bundle.css") || isLightTheme(s); + const csstree = await import("css-tree"); + + // only include bundle.css and light theme styling + const hrefs = ["bundle.css", "theme-light.css"].map((name) => { + return document.querySelector(`link[rel="stylesheet"][href$="${name}"]`)?.href; }); - // If the light theme isn't loaded we will have to fetch & parse it manually - if (!stylesheets.some(isLightTheme)) { - const href = document.querySelector('link[rel="stylesheet"][href$="theme-light.css"]')?.href; - if (href) stylesheets.push(await getRulesFromCssFile(href)); - } - let css = ""; - for (const stylesheet of stylesheets) { - for (const rule of stylesheet.cssRules) { - if (rule instanceof CSSFontFaceRule) continue; // we don't want to bundle any fonts - const selectorText = (rule as CSSStyleRule).selectorText; + for (const href of hrefs) { + if (!href) continue; + const res = await fetch(href); + const text = await res.text(); - // only skip the rule if all branches (,) of the selector are redundant - if ( - selectorText?.split(",").every((selector) => { - const classes = selector.match(cssSelectorTextClassesRegex); - if (classes && !classes.every((c) => usedClasses.has(c.substring(1)))) { - return true; // signal as a redundant selector - } - }) - ) { - continue; // skip this rule as it is redundant + const ast = csstree.parse(text, { + context: "stylesheet", + parseAtrulePrelude: false, + parseRulePrelude: false, + parseValue: false, + parseCustomProperty: false, + }) as StyleSheet; + + for (const rule of ast.children) { + if (rule.type === "Atrule") { + if (rule.name === "font-face") { + continue; + } } - css += mutateCssText(rule.cssText) + "\n"; + if (rule.type === "Rule" && !includeRule(rule, usedClasses)) { + continue; + } + + css += mutateCssText(csstree.generate(rule)); } } diff --git a/src/utils/exportUtils/exportCustomCSS.css b/src/utils/exportUtils/exportCustomCSS.css index 4807e316a8..bd0de64265 100644 --- a/src/utils/exportUtils/exportCustomCSS.css +++ b/src/utils/exportUtils/exportCustomCSS.css @@ -18,6 +18,11 @@ limitations under the License. This file is raw-imported (imported as plain text) for the export bundle, which is the reason for the .css format and the colours being hard-coded hard-coded. */ +html, +body { + font-size: var(--cpd-font-size-root) !important; +} + #snackbar { display: flex; visibility: hidden; diff --git a/test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap b/test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap index aca4e162c8..3958005c5b 100644 --- a/test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap +++ b/test/utils/exportUtils/__snapshots__/HTMLExport-test.ts.snap @@ -12,77 +12,73 @@ exports[`HTMLExport should export 1`] = ` Exported Data - -
-
-
-
-
-
-
-
- ! -
-
-
-
- !myroom:example.org -
-
-
-
-
- -
-
-
-
-
-
    +
    +
    +
    +
    +
    +
    +
    +
    + ! +
    +
    +
    +
    -
    - ! -

    !myroom:example.org

    -

    created this room.

    This is the start of export of !myroom:example.org. Exported by @userId:matrix.org at 11/17/2022.

    -
    -

    + !myroom:example.org +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
      +
      + ! +

      !myroom:example.org

      +

      created this room.

      This is the start of export of !myroom:example.org. Exported by @userId:matrix.org at 11/17/2022.

      +
      +

      +
      +
    1. @user49:example.com
      Message #49
    2. @user48:example.com
      Message #48
    3. @user47:example.com
      Message #47
    4. @user46:example.com
      Message #46
    5. @user45:example.com
      Message #45
    6. @user44:example.com
      Message #44
    7. @user43:example.com
      Message #43
    8. @user42:example.com
      Message #42
    9. @user41:example.com
      Message #41
    10. @user40:example.com
      Message #40
    11. @user39:example.com
      Message #39
    12. @user38:example.com
      Message #38
    13. @user37:example.com
      Message #37
    14. @user36:example.com
      Message #36
    15. @user35:example.com
      Message #35
    16. @user34:example.com
      Message #34
    17. @user33:example.com
      Message #33
    18. @user32:example.com
      Message #32
    19. @user31:example.com
      Message #31
    20. @user30:example.com
      Message #30
    21. @user29:example.com
      Message #29
    22. @user28:example.com
      Message #28
    23. @user27:example.com
      Message #27
    24. @user26:example.com
      Message #26
    25. @user25:example.com
      Message #25
    26. @user24:example.com
      Message #24
    27. @user23:example.com
      Message #23
    28. @user22:example.com
      Message #22
    29. @user21:example.com
      Message #21
    30. @user20:example.com
      Message #20
    31. @user19:example.com
      Message #19
    32. @user18:example.com
      Message #18
    33. @user17:example.com
      Message #17
    34. @user16:example.com
      Message #16
    35. @user15:example.com
      Message #15
    36. @user14:example.com
      Message #14
    37. @user13:example.com
      Message #13
    38. @user12:example.com
      Message #12
    39. @user11:example.com
      Message #11
    40. @user10:example.com
      Message #10
    41. @user9:example.com
      Message #9
    42. @user8:example.com
      Message #8
    43. @user7:example.com
      Message #7
    44. @user6:example.com
      Message #6
    45. @user5:example.com
      Message #5
    46. @user4:example.com
      Message #4
    47. @user3:example.com
      Message #3
    48. @user2:example.com
      Message #2
    49. @user1:example.com
      Message #1
    50. @user0:example.com
      Message #0
    51. +
    -
  1. @user49:example.com
    Message #49
  2. @user48:example.com
    Message #48
  3. @user47:example.com
    Message #47
  4. @user46:example.com
    Message #46
  5. @user45:example.com
    Message #45
  6. @user44:example.com
    Message #44
  7. @user43:example.com
    Message #43
  8. @user42:example.com
    Message #42
  9. @user41:example.com
    Message #41
  10. @user40:example.com
    Message #40
  11. @user39:example.com
    Message #39
  12. @user38:example.com
    Message #38
  13. @user37:example.com
    Message #37
  14. @user36:example.com
    Message #36
  15. @user35:example.com
    Message #35
  16. @user34:example.com
    Message #34
  17. @user33:example.com
    Message #33
  18. @user32:example.com
    Message #32
  19. @user31:example.com
    Message #31
  20. @user30:example.com
    Message #30
  21. @user29:example.com
    Message #29
  22. @user28:example.com
    Message #28
  23. @user27:example.com
    Message #27
  24. @user26:example.com
    Message #26
  25. @user25:example.com
    Message #25
  26. @user24:example.com
    Message #24
  27. @user23:example.com
    Message #23
  28. @user22:example.com
    Message #22
  29. @user21:example.com
    Message #21
  30. @user20:example.com
    Message #20
  31. @user19:example.com
    Message #19
  32. @user18:example.com
    Message #18
  33. @user17:example.com
    Message #17
  34. @user16:example.com
    Message #16
  35. @user15:example.com
    Message #15
  36. @user14:example.com
    Message #14
  37. @user13:example.com
    Message #13
  38. @user12:example.com
    Message #12
  39. @user11:example.com
    Message #11
  40. @user10:example.com
    Message #10
  41. @user9:example.com
    Message #9
  42. @user8:example.com
    Message #8
  43. @user7:example.com
    Message #7
  44. @user6:example.com
    Message #6
  45. @user5:example.com
    Message #5
  46. @user4:example.com
    Message #4
  47. @user3:example.com
    Message #3
  48. @user2:example.com
    Message #2
  49. @user1:example.com
    Message #1
  50. @user0:example.com
    Message #0
  51. -
+
+
+
+
+
+
-
-
-
-
-
+ +
-
- -
-
" diff --git a/yarn.lock b/yarn.lock index 11678cb0be..b6585e26ac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2479,6 +2479,11 @@ resolved "https://registry.yarnpkg.com/@types/counterpart/-/counterpart-0.18.4.tgz#e3e331b7e0d5496873d417839f3b2bbcf555bb73" integrity sha512-aqBg5oAGo/qh/+wxUfuMadDu2WO0MEWOblyzwaM1Ske2xilUxBfgPqapAFVAfrVTDMVwa0UMarzGot8m64IAzA== +"@types/css-tree@^2.3.8": + version "2.3.8" + resolved "https://registry.yarnpkg.com/@types/css-tree/-/css-tree-2.3.8.tgz#0eabc115e45051b2f7abe51ee1531074b234ed19" + integrity sha512-zABG3nI2UENsx7AQv63tI5/ptoAG/7kQR1H0OvG+WTWYHOR5pfAT3cGgC8SdyCrgX/TTxJBZNmx82IjCXs1juQ== + "@types/diff-match-patch@^1.0.32": version "1.0.36" resolved "https://registry.yarnpkg.com/@types/diff-match-patch/-/diff-match-patch-1.0.36.tgz#dcef10a69d357fe9d43ac4ff2eca6b85dbf466af" From 7f959036afb612938e752ad69feaf6250d963560 Mon Sep 17 00:00:00 2001 From: David Baker Date: Mon, 15 Jul 2024 17:47:35 +0100 Subject: [PATCH 31/59] Fix HTML export test (#12778) * Fix HTML export test The masked area changed width deending on the date. * Mask off more * Update screenshot --- .../e2e/chat-export/html-export.spec.ts | 3 ++- .../html-export.spec.ts/html-export-linux.png | Bin 40662 -> 40619 bytes 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/playwright/e2e/chat-export/html-export.spec.ts b/playwright/e2e/chat-export/html-export.spec.ts index 947aa2c1bc..5eec541f21 100644 --- a/playwright/e2e/chat-export/html-export.spec.ts +++ b/playwright/e2e/chat-export/html-export.spec.ts @@ -124,7 +124,8 @@ test.describe("HTML Export", () => { await expect(page).toMatchScreenshot("html-export.png", { mask: [ page.getByText("This is the start of export", { exact: false }), - page.locator(".mx_DateSeparator_dateHeading"), + // We need to mask the whole thing because the width of the time part changes + page.locator(".mx_TimelineSeparator"), page.locator(".mx_MessageTimestamp"), ], }); diff --git a/playwright/snapshots/chat-export/html-export.spec.ts/html-export-linux.png b/playwright/snapshots/chat-export/html-export.spec.ts/html-export-linux.png index 99af1a757ba327b750e7859f9e8436102a2f8d7f..ae11ec9eeca054bd867faff22735e6a80f57c85e 100644 GIT binary patch literal 40619 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

Vo-^Wv0a^k?RRh8DoP*ZY)>QOyFh}vn6y-h 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

^EcWkbuSHXQ-SR5|3N}$wV@Hp%dJ5&E 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 BrOf~U literal 40662 zcmeFZXH=72v@QzjCnzdS1gQc7(xrF!M2b?SOK8%i_ued^AR;2YOYejpTIkXtQbX@O zB#{yVgus2_+k2n$XWw)7+54RPK+zLI^wvJ+zhO3Cf4*w+RRy5xi7*rt6!wJMUwxhhgg3L$8}2 zQ4kWb@R2FZ1uQMh3PKtT8u|r?V)F4d!efGT-$n=112!3-aIFxKD~@a5u#O(6H%6hO zEyc8reIs^o{<5d5a~>_5z)t`^M{E%-VPO4~<_0h<0l|frP1yY93W%gzg6o&R=l)G_^YZ!PJ;9yJ=l5%bG?&jue_eZe`TYC#f3$-S8!q)q z-ubeJFBE8~)E+Q4*QCZn^ZEiVRYmYU zdHcGnn!?=ZIl|Jpd%a2CO>=XkBq08eyMSHmWdj0jp}mp`Yd%b;DguXpo299qD0IO*+tFu_9HapcT+C~`Q$6ybvtgY2gTpOcZYPlxt!A7lGb|5q}cEIoQ|wc^@AqeJ zZf@0^gLpsW>D=Zw8cdz?_Na)xZuGZ^hjQjCNGYEkc!^Q9&0Xfu&&u0b&u{wq#s#B> zc0481H8?_D-Q6kV)8v@OSEFQ=qZz=vMnxt~qJXB7_eOdyQgO+nzH3{M*4KyD+V1X~ z8Vo84Pg)${8GQ5p3W|ykiI6r5Ynz$;_A8683&t44U0uhwD&@}V8}$YrBpVu*=!2&l zos?Tz?_Ub>$$i>b-Iu}N?SDwJ^E>D3lQ3&*>l~q`%SYa(h`KO5^g}=vL*(4wwvuI= z23_DrMmRJwcE*|tW(L)WW0I2UF^P9gO*5WhcaA3l3A@xS9Vp6&`+000 zZqMrw3jk^ZMm=#n-z)>wzDg|$Ba@Jj-~|ceT>BrdHv&_WWqCh=b19IUFU$`rAH8TdsKM%LtwW)Sfo z#180xrIp~};W=As@3gV8nT0rWnYE;86do3eoVUO9TDY}N z_0X@x{NpJwgnalHDkw@>xu?7Pp-}?2(d58@4zanDlS%ED#ciSY@bWMzNl7lSK5DYI zdbHGI^BW+%TTKr#;xU_%V6%`iqYMK`RgH9oOCrS&AweM%6O&M~5dndQ*%}wPK5>?Q z3H~fFCp()_+V@X3WU|l>70ngDvl=bu?&hYUsVNsC`+|4`6D{lWc2U1fAAvb7F#xAa zQ#}eTTrp?}JaLyN_V743Le3aNX}!1isVs}M^XB4msJQ)aG506(Z*FX`hyK~ydoZi$ zXgo(5bhX$JVZana#FdGNtUKpAjET)%T)=@fHC6ZJ*VfKX#7jPYgu2a64(k)geE&|v zl=*Y*wS$Ah`YSCC4(kn3NlB$VZBD63Dvux#(d1b(3TMsjyx0;Od$6Tv9t|yQcoD-A z-DqXU8TuPxb{J)mr_x|2oU*&S8-UFYC6g;Noi4SbWLB`y{^1^xtr*G0J2W^*&%m&{ zx|)MpjE;_m1@+c5Pa|a(qHbJ;eRnvQZu>C zeT$9++DJ)BNl=l?TUpuISXn*!{PiHSdxo zQj2}JV*kOG5MhtQL@{UR>z1?6$_yT!xQP` zUs)?UJ`QD7js_G&DtESI=cN+&Bp7Wv{#nOX*lx6531crG?f~zw9Xfx!V>;eB^_sa0 zIqM^fcYL-e3(Xu!ruY>}!aSUIi(by$0&MCc?D*>9VHEd?FDaAg+AKO@C{3imaEzUg zZ+I+U12tOK(;bz%YOzXBzl+_S=Ln^db9RhjQ3PD;Y`Ifv5RSBYA;+iMMjenTU_YkW zzI$4%pP@6ymwUENF44~B9XF)(%@0Yx;)V96r7v>b6BAxXJwmXX8BHN_jlg8-#7eam zGDJLkfBpq{qbFv;o8>aLuymKv+`Ww`hs>B41sW%9zkW&VPnP}uU6L;8MI-B2k(0AJ zQ%fgIdl1jv!gOpCQVYV*nNjSF7kz9EVFgrk+$(@28N99;=o46^?HmyiF=jJ(UtYHi zWIgsNlTO6m_f%~u1Bz>IZhpXb>^V0DiR)HP;GsP@dJ@%ObHHz8X~B5t3&njyrlzN- zn*|SEs%&ZT8D?rWX`e$z;sCEgQdOPNS_)C214BYktf9w^i;dhw&e9O*%$(yMl9M*F znF%bC6-6i3id!IRi4VNDyJ+$oeu>-(&hTp0H)dwqtDd2EIP{5RAnWnh#grO?&sO5; zj*9lga?LJVwS{EZCHzgoEU9T(H!U%nRDLx- zg6ZV_hi`Ifjt{{&aHO=47}MsdFsE3cA?a-PBs-ewvX{SY{-SsnM)ryRdD~3n?75Hl zy7>%Ah6UPU%u6Lw3GYxisQcFl+hxmlgSWW|xCOPVkNBkBJlCfOh3AD*45y7m8FZWQ zP3PcxZ`!M71)Ng^rM<)BW-|T3%cMH1HAQ=%EDCQ$r`)f`71-!epnHNFcVy6o0h?*?GSy)XLCHiqs3 zLDc5zoISFch#v{`YDj>;GKHi&gs;04x_FVTvKuzWE!_99o{Z2&gIoO6u}4=i<{Oo& z);>-V4V+i27x+golj0U3LdT*uA3=RNL|a$xy*7W7VIah1Qs{2=FCr3KZDpu`1|ASl z{3pcC=kOvp_pVY7C8S;LJt$?LeeY@sYA;6#(lXK>R`At7 z;>t7)5s;Cne#CVpDbuiALh-Y;vTOe4dfo}Lz^4y|R}rQ!)sLG?zn_a; z2+n05pPGT_FK6~$4tTvrRCF=Aay8L2W`c`>FIQdeE06vQjS-bg2q2sJ)*A84HjhGx z+b*j9rFo1nLE;hj9zXBB%U8WjFR#0_{-qmhIoVSUKf6_^P#X*RP5l0 z-+(OsYBFGXfM)@mM%e0RM3ZLeJwZRi3o!=_t~sY~;A+LDF}Xr*^5Mg=DfT?-(zi-0 zb$ycO25UsFzRk|;Lg4+x8E*B)X>8I_BD)1zQfBAykEG-m2zWxb1RD%F7cKIO^~?2( zG|*xq|Ei6b4DZTzd3#C`M!C88l0b!* zL#@Z2)y}peF1|PvTrD_+?wTuOl@P`tdO^CC_wXF^xyWs1+_&s0aZ|Ra_pm4%)WpFH zgK^l-6HUbL*7#6(U%clTkAcc zwvejIN&#oH7K+i3wx4Tj_n8$ypqWW0sg6!Cda5$d?BW^q2YxQ6@=qpo0{cia(K4_R zq>ij(bX0pfGcD~5=`*kqCvA4XszN9;I!-gO>PUz5UYEsqSE5K zz5h!!(V)z<`m~2iulV>Db7^VmIgdNn5){ipcjqQ^s767^jLBnmHYgCJ_#R{Au#edp zWxUU}Dpz&n&fXjrl84Nd)>Z)#^YKPo7GVMG2@_gbncwLA`P;WspD+%(ToWZxTW0lV zl}|v#G4aXPyU56|fLw$ZK#s=7nZehAt--}~T_baQ3_FAm@F@pDHvq}RrDIWwL82j9 zWW{cli-OBTm%jIy$l~U)radMzMBj&gYwEPacFcbiH{R$8T0{p$N7aN_CuW zZXX&_mk@UEs^Co(3#@c)AzK;XZ`B_KM@AkLGbJ)jwFVqlw5wFZHu#&F81Owq#qm+- zM6k4vY@ylW!pEEUUP=D6`UM1{x0olvCU}(8YJ9pPJp;sXp~Cv$(qQb?KQ%Ox`_j*?f1Y%r z%zg=A{+Ru`5{j4}Fb*K4Fgw$$2LJ)eGyw2^4uihdRRT+g$@%JMup1dNfop~ChpFIJ$BE*w zs`+BC$b_;PfCrn8{LC10Ap+zFs&zR-ub-FYa~i7e~0nV<{-f-9@F;h zSvzlvSczWA#(V%aE`in~YLAPbjeVoN1y7W~hu1%uYB4b~Fra4cij01KuC%N2Vyguz z6~ukAg*m;K-pHxbPIQlc7Y@M|9LSQ(kC&Pv(<5R-$p9J@4mJ}TX1;_c$C?&5#a-|? zOeF+DEq|ZiwA8ySrGFR*`hB+NUQVONv!GQm2?_b7al=kq-=B3O?=j3gG&{b3|2|LX zR1Z9uG*C4T}6nR6V+<6zLqu{(6KGsjz1P0C>)FIu(qBP}JH ze8CKzg5aOR0efz}i{T;;GhL7$(Sp~IGj*aUCJBqAs*y^|fYo7xhO1EX;`WWDX1@Rf zVdumrT66VdyU}(F7Qc+6?gIY8BeP`WZD3%tM+lG6(TJqIwJ2t$)^*(yWfOgL<~C19 zP9DwRA9GkzT6+%g#EdS7MJ5I2+kzP?H=qyBx4uY7M9WDV*Mj2bnC4YwK>FzkDO_s( zb92oOiNgR*DO%1Iay3OfMwKVa@ihoUL;YrUYKrDUG$tkGs2_6a@s^mP*nazQuWY@Y ztE;GZB}z}v@KtJvcQDhtJSwVIfa9Waa|BU4IyM$Y#u;LzYLwa&a=UkGzfW4f)VGp) z`y|N?y*t-nH0|x~&ShGfl$^X{W3@Jx;pWA+lZMOL(=!EU`_~qCFD%qEx&g=SI@{~a zpwpKqGdcgOsYz^L*k)#DH-j4z8%}gum4O)%TnOBFGd9rM8|WCVU!o`KSXvf;CqGav z$Rc4PX@&m$t)%450Oh-W$g9qScN$(15|5|M-(l0ahSeCEY z`weXT_Nc4mpdZ;glCD!s>epGKU>U14!g8I0IOk8J45cbzq z4hhjD?ss!MenQtjTO390#=m)DmzEv)*n20aF=#GGQ9p|`Yf#fe1Cm_ zv-M|5v#+6_!(OP*0x4-LYIQXTF^RMuFyOj1Hrup<0DFa?!oE;*dmq^3lC2bEPA0f} z2GlU=j4;&K%2_;jGW<<;teQXLSqHbka9cxZbHe}LB zAE~j61so2S!BNoO?a9f>Y8wqE(ZCuC!^A-RkQ8M%bX+{i{z?zMUkM!jy}j!IqsLo} zB%1M@dKBd4{p$ED696pht1F6`qz@%mcBc>Q?CeNn&EjyL{QNK`1HS5-8eddciiiV+ z>*-fA7D;xSjwZB`k9xDGzJ8*; z`sT-fld`FPf^+{Gc5^6w6=BpjI@$q%N-so$l#gSXNmD|lI=OO>I^856NPKazH6}JT z7F5Qko%;gs@3lFY(cl8pSl3$Kq!so2^T+%nz-&*v6$VJlp;VEPx55Z`IcgECxjl;N zN8_8t+&W+m!H0WC83Op{)YP_7N~`PZhJzEBzxw4YY;7U#ClHZhgX*f9n##((y`!W3 z!@-`4!SiEQwjAKBfnES7?QJAA6H)BftDTu#^i}iA3Ken&>I38y`}t7{O48@$|3neX z7B~L~sqH@$JeS7v?tT*Ce{oX$pMd0HyX-cg_wcuyb-gR|%5feM3S+y#8 zr)MSTfq2d!F|N}YOsXpN@QD2wWOvR-LYRkF-Ka`o50yTnU#_b~9FrVhYllD$Fq;?I zffBPdkh8)ruOK$ZQN6zw0jhH{+Rw!whDuKnF2>e48`s~ja@ssU4(%F6IY-fr`?=p} zIrjH^?b{V!vfQJQku2s=MaIG^bTAw5ATQr3LaUB=aLzDW_bTDUg;D`LjC-RUY!2m>E!TaU2!JN zA$`^e1R`ceDa|j|cwt>ym6MBx`r|q05w*kRe2QUYtUa0!f8%No+7m5TS1_k(giy1{ zFW+uSQ>VqHt>{#Cv<15q4q07vUXq^g0>4YXn5*~W-U(LgY^#?dH=h^O z*ijvr+#tje4Xi<-Z90eufTe>X8wD`aLOp1|ZMEEec^<<$E?H)`od8Sf5Xq94osFt3 zH~~J{XT+6Wn=K`9=VrO!@x;ub-Kp~RXgQZgYAPgB?|evBMwk}!GbT^VmyzQBWjS;MlFKgFF?kp`iSpQdXmSY?J z$`_x!Oia>vc?P5DN&g&R%7Fota`;eyb*e`SZGP}-+-*B(=gQg{sr?uqpBGi@1%pe< ze2pS$CFcw!D|an! zNtK!P)1i*+saR>#accbDtq8^RFVfSmQ!_GB@_9E_N`XXe&8q~;9_jF?FW)4nJvn_= zyK)}`((H~VW$XsxwTA}Cjo>`}2#fN5rNNIt%I;8t#2wD5R~72M%`0^@4_Jz7fliU` z!-vTLc&bFnl+gjB3@b(^;oa;YKYp26S$(+};f`0ab}k>Ww%wGSL0~lGT&5n7(X1g> z^=hj$C6102nr`p-yr+>yI$AXWq zU^orFT^0Y?5^UNOlN2{sVOrK&!@0o{dW^(A$^1eUCsXORH>{Wr)F^0SEgOC8OL7;9 zNLRJTYBaskcJn}`$(N-q z`NR422TxE?Tz51!J6n${zQkk1qMVP=_T$%1ip=jx$?Kn(MnKz37*5N>{y*rjyisQm)5k~SX}yDsY4zE(HX0eIy&>;+IneZgh)`Q1J2c; zwc~A`bUscA>yu*4K(H}(Dgv{kYjA5~0~zq+hYsp27~NBwNW5H=s*!L+I+ zOTdPQ>z<{jAVFdQRp(2DGGfltC#`>}R$-=pMK;_EsD{{{RLO@w!!JzLd%;I23sf88 zx8T*d2?sH66ke}PAL6`>M(MkEb7cCw9cu<=;^&=H(=_{AEC4wd;EF?;$;<&qhYM!D zKNADQs3whetNy7Fbb~9W)xuyOj8P2m9ju=ZXKS%bng~eYguM^s$EwoZ;C4j?c@j}& zkLF)3BV{>Cqahua(lbrjX^0KJ{6ug@^rG>`RRZ=A-T!LI=KlnsytG_`|9wTH|KS<@ zv2f!;A($BA+t^Y%S|G&TZ^%BOuxbrXNw{44&58qr0?*CxKJHFMe;2-2E(3Fg0-FhJ-u=J3F8N@y4;V8bPcMFmOzu7KL4Q&pVV=XQ z#DS3u?z%xhad`*o%DuM5@HBdh%kC})y zBj7ZFA)qJZ>4AS2?`j6qq~lzjLo1oZzVbmwN2b~GOSipSKsY|Rxwhsf{OIY{7=KHj zvSFA;q6`q^hIZx7Nx96Q;~|UaTg=0MnWP9^lmt>=vhD9e#QmAcruOg}w;4Zgj;Kf+zW^6g+#O)qsF4;?Qz^cw7a zfAR!(heIP1>VeJpC+XZK_dQqjXKlp8l5VFE@6=58-6S`QnzC504CRmfpX0c78qJ{~ zDJ-Mfn7xyeqdODc>fGQu?x=7L`S1Z_rQ1OHTHJkG+X7jc#sqF15E$+<-ynDFUT6yD zM=YP)EW({iFPatPEk@&#GlQ$QLhOaAfk2c=g8b1PAfL2?DQ5`e(iaa|-j8@!&D1P( z+LI|Z{o1G?H=mt7?=c%27CjHmwmp&N2BhUU*NEuIBa@<=&5uIJcvIu^-gZhTy!zWYkou6?`)BLc$mV63U9qjBJc={&#j zZNEQHMJ3q0)|P^u*&-OT~#9H#*kJa@a1mTZ*x`sAmd0 zFO>Fu`*u&RZ1%@ygZVN!01_pa%d(g>Q>SWmQu7839BQ|_a{$l|fJ{L48uU_gty=R= zP4}MI9rg87^Mx5V2YPL+`Pis2UI5^=vZTggV!RWo3)gU3*jmsccEc{6iof+6s%oPrE2^3n|d z4t_!Vj`ibt)fOZdQlj(na})E(gw(NgPO=sNBI}PsRTeVj!`bg5GKj@fZL3S*<ZWj!uE>&!2rqLcE(KwPy-NfAcor+=^MfmU8s^k|jg>M4xzfilr&0EXRW zZsv*`7@p)P$OW{d2i`H7n@}Xys!qvFPM(fRg?MCUYZn1cbWZ)2wOc{YB0k2^fPs)zae{AJ^f)5(*j z2DwwxLcgO#ZY?;YDB~+3pcbh>L`c$mUrpP+Ka|vllL;to24q^ib#nZ?wWtWRx^DwS zkS?~|p)bbrFRCoj-(*_3Z~)8oLq|Iz)#weB1o zjao=`fG4jJ-8$cXGr0rzWhB4a`+9w5*sq_Y4bUdR64guEcV5ZU-A+JVlPRn? z0;?04lHh~oMQP{1*iG-^NX7e=^WhGsNvdT74U%i_%hOBx?SOr5dRpyELn2H^yXMYH|s*vW+}2A!Hlh|l{T6g z0lQXjkSTf|XwH?bC9THs?P_X92RlnAAe>kdp{px3ZJO>Y>NV=TSvWK}Q){1+5hLJ$ zVqp&b2sJ?$sFnK%=xqUn(n=mTM#7(t4k5sLb0gT$Gh@HhxWJ~CPRs>%Y?T!iuh%p= zq{{`ANcINlm(l8pIn7^2jJ3sjepUIlK$=zxg4>^Es;b6p(5mA^hrX&N9&G)Mu(6vt zoX+GErMbhVa-VLl)%M)^>XOs#j#amNP2&JP8Y`4J(mm7eJ`)o& z%or_~ZuE0yh4QQ1$3q{}s}iU4gU9NI!;FdxXH|&m**l<7q>Bc?=*7heM=3o&y}H#E z8!Ps9Vrxst#>A{=#aolnoyS?s#$?eR3BB0h3;SeZ1`w8!`FAfi5SQ@a-JQoK*PL?y z{j;At7DINafj^{=0to)WF!Bp*zc2qpQ1m|vCO%wI+Q$zcU$*`pIxf@(00bKmP-8&* zUPVp}XXQ-XYp1D^UI0wM>}!PA-gJ3rE&_&qOlo5qU2i>i(3ui7>y4zAS37@e`ug~Q z`~Hn|zJRX!zFQG5VNQOCBXlc1Sd-X|Z)-H|#0<|14Y>7h=%V?Uv)f$GXIVQ%-(lwb z{)*4#QPuW%?QUDvXBWQhYEe#hOyBdD0!09x2=cx;JUp3sxAD+F@dyYsW&J#NaF$T6 zI3c?bb#&KuwGV26d)HJt9G!L$$3JM+ZHl)}7Tv{e zvzhZ71-GPZ(rBCzR_U7~O9RXRZ|VFRJPAKWny3{#kx#Ww9wiX#Kzkp9+%8qkY z+!AcRrl*TEqsxJ|lL(BF4~n#fz8H=e@UL&3#(L2qx zH|FaEaJ(NeNCVwFm6j1oF;%97NOJ(bkvKj23V3r zd4Rc5*LcYwQJ-nlx6*wIXjaE2_;e`y;;#&nd(uqCGxJD*a{@T5p;TeV*O1AsA`jU> zv=hK6$cGo=1TuM!?b|uV;>_i|_Xj(t>J?QDJkfJ?HX^OIU+c(L{1w(VoB~FL1jlXc z0m{`#)FC(UFTB5Zldr^~xnrOm_Q&&^huTHDDmZ}VGAYon1vp(2<~uh#bGI+(rof-g z*wCB!$ji*@tK-M%gtEZR!F{vMU=AdMpxmxZ?MdeKANOPZZ94M`^u)adf47>OL@DW1 z`^N)om7dMbw@c(Rn+Hh7%nKKPkBd*LiDdxp-Iem)Raz_Cj_n50fzu-+%LQIW?wQ#m zZ-Htq;O0vAH~R5bAFTSUH?^B5y_mmiv@-()E&C`mJiHkiaIuW-i9S7C<(w!!E;qf1 zBwGOxP-G%_IPGlsYu_qUS2t&#^IUT+fJ`CEch0Q3bB~--_)q=AOu=HNg(fBWjHtXu zZ~Fr!>^J%FCM+tEPtP5|S|4#(fO+%LPvBE8!SCRhjKr{+LU{aM&gb)*VAXMaQct7* zvUYF1*2e(oqy&$&MNftqN3+P`svTvMw|%weiG7)<3@n{C>J&izfS@_PF_;$EOt>Um zjF;l=lM_?Oa8-EHGU0 zWo3*qbuxjjWD2M^-%uYK^$C042Y zSr|?mu&ZRLW)Uf3Kc4iqi&kV$Btn4Q{wvfH{<`wRBj^iq1y(K<+eDK$vpDlWQDPF7 z_9Ux|)=1K7+hGZh%;~+xW^7vWOPHgx#o%z*&0~Ll6XDODPsz0e=9_M8ZEsU(xxRuQ z=jt{XYvq^+kczQX0e6qM;ukWI;k_MmHMzN8!*`K0rFZehZ>?S^pqz(c2PEN7cx481 z(n&JGnhMWMu1{&OWLwMzG#Vx)Q^Z6kN`3BZNW}jvr(_WpwBYb%KqA-N6_a1YrKMz* zqNqcFldo#HdIB4PsU*~eXR_ZAp;>zYccW3nExB3ioTKhcl~jp-*m zP_Qz0wz0DVE`6jiym2eqz$HAiP%}!Jng&s7ajSZS$!qDe@1wUEC^NhC>nRh*`(VnJ zv!^g`kW#|$-rv>fBuy(bJp(eFY*F*;@GP0swbW!$el9*Ou|3S5zv-(#OVP$h8kVi! zkP_hP7j%I72nZHfculUQQ^p$MEth;Vw{rS4M-Q65VIySRAm#S0k9n=VFxrvk#7#z1K}S&}EW>If6JV&v z#!VTqBgyQzuckoH_c=UHC0>DrmzUexo+ZsKl zAh~n5So!s9-9hJ)&DaUsbH#?13`ha4Y*t`Wzifr#$L4UFuEEtsAc8-dIeE7#O0~-u zHnv^y%Kiz`R1Kak4(m4NGu`z|<}Z=9V%-*Os|&VvwyfquD$K|9Sym7T)m$pa zu+b`N!}5sAr)@CX!9UNUq`pT~{_YsuErD&08*KlIs(gH(_Dk3LjzwiXuv-f&D~eSn z>wWDLh3f%c=AT-CrM-HFW*LjsSZnu&kk66@<_Ni2c~;h#Em-^?mdd1b5ZEm7-8Z9< z+0BvRUtOBa1G+f!Cxg-7QX?(xlAkc2@R9#wf9x_<6GfB%JRtfHB1TW}Avs$?KGPj3 z3@9csE+IL!_V>g{QE6$T|7x9lR@}h)@HeMe?a_WVig*>OV3`kP)0IF%CXhlZ&+ygj z8f#oee}D0g$)2xqMDDOMTa)-S&`DmdHJO&R-b6WGdD@5FZf$j)G4cCgO8}?9iF1R( z&eofP%0IO?jamuJ&~Z%<_aZn&CgnV6KAF>azr|!aQFGt~W0Dvw&9&SDEs7xqO$Lnc zUwx*^%C;BFl!U>u3Z573OujM{m-f-t`XOPMz^KV+;ciH!=&{D@{`89b-U0C4Sdroh z=K!RQu5xB##%D(!;i^h!hKCFWIqYU;AscZK0rx&3XMDQ4x{hO`dpso4TH5FHsHn0W zL@8oovfdmz4FCRgxKkIj`96=kRYZ{DE4}0+Y~R>#uoxfiY%E}!G@*Q^4L*jLl?pef ziC0;F<09qxW)Th9{XRf7ntVZY)Qy#P}*sGdxZ{; zH1m;#WDT~W&R)+zclg`UN8IN?$caIicKap*mL&Zi3du3=ML0S2+w*00|R8*rv6`Ej_i`0WlEfV<3 zfYJ#lV{&U&_7i5YmhK)p`{BL)^HomDC8j#pkL984kyn@;_~#acH8TGc>JSj{X60f3 zxivuWuI|~jf9!(*M0o4!zgQ3uy#4EO+g0}jKdHX|YeW4dD3V}7u=(b#t5<)kzQx>e z?awRy&6f%b^pHXB1Zllj(0%l>$^T+d4F0^yQKKOa)4yTP0UI){=MmyoHmS0NWvv## zC`YovEgA#9UZgG`)Yvnn9kkqDZgV^2=UNY5Sggb8MB#eN8pak43ZvtME#y8Hlm_J& zSxV*#y1O$MxT0Zp7e~)9#b2?uyxLFVF}tHQMtDMl#Dk>~rf5bnN%^DGQjXz}bjUIP zRi(|jVvQJ~2J{EiZm?z4c4ekXB{M=SYT6*=9#0~7wk74~yE{I3eO)BfEKqc8WTE`! zs+0fAKDz}|ROCjmwn5lx0e@Vg>czs(6m4ZD*h3xm@mlOq)Nt49`rvhH<8Plrj4`|Z zykaalOdF!I|H${Z2B`4{NL#zoV>03tv76!Hz8z(Ell_zy+s%P4Za=%VgA05rm z4Zk=b1D3CK8Lsnp7w8QbY6g1+AEGMRG zn`GcYNTVf;`ThH6_Wt=L)t!YtM3Wvo-XHj$JYDLq4cF?t>0jd^;eO@_I+giku4W|6 zB;{UV7rCJ)Xo&1sJYt-Lk8x8*9vqP9aZLcnMqa$rbm$4W}lhyL89M9X6S3 zQZ5UPs#&_{!P_%XoP_Fw!Ba`km{)IW0zzJ6*rgdY`4TFsQllhG&|X$B*tM4t07}1rOPi@S#SB)jeOJ zqw0JOdJL-VG+I#sI7EO`MxWQ@cNVm#fn+&4bB)(fIN&7lpcG_u-iRYh{SN0_b8q1E z5n})Pu*LWM&b`EH^q+|6MJ6cli(A8ES4xY`5XAY!Yb!fqRSBrV%P&^RU+_Af zO8(iV!JQabcNXbKQFPcB+q{!A=KB`2)g2WGpRJxBniX&~7^%EvigMoZ9G{qe-}&?* z7Iop`V!C@EiJPu2Q+zcKL`;I9$)y_qoUG3 z-n7&D;`F8uq|#o-_wU~DEWF4~v-ySRJ&vVDV8c4sz7NwrD-@JJQ1)k{7j-UQdRA?0 z)^B(pr2+y1M{jD*dSmb2OA+&^O08a9FM;gP20TC2)KE8jYP-|89tqf1pGRW&TU`0| zZuy*e)s4@=0%E*Eh?${Tk@DFYY9&0!Wgdm#99bhw*usPx-5*I9wqfUua@X0PXWp~9&Q-QE$L6v%F`Kg+Mt{Rq)(BHpN;XeJi zh%BcbpTYRssfEs{aGt@zIF&qztrQThh*?uU4rmf}crHgx`;a20DfQss>>7)TDs2Dl zX2&LiQtK6*pe{DNaOx<-`GHNo0)UH#mt9fTa>ot@NVb0sL7abA((LcKyG(xV$wxeU zPbfK*LaqfvnN*?VzQ4$$C3*PC&CAVd6U#HGW@19`E6v#XbR(ZvMa5xZjYn8;XAAjK z;oFh7dqcL`V{NpcsOT3}wLZT;;REYx^kP5K2lPr1zjsEwZf(&}QSv7aL_A^VEAsy` zuhXT{LWuD>n8PK`y{3qXv?(A7v}Dc!J7EIzsL=fQVl^V zK*VDU{S9o}* zYaACF?rTZxCf~w9aNF|JDy{~VJQkM9+~&M6iCO(ePv3|=*0%Fk^7gk8#Z?xo=*w_8 zQhWk?@OZtkwzhcwen~NlFf+Vg!6GV5A-A9;NA`WAWQa3&d@(J)`b3W0t)8Bx*wnlu zX_>myWp^f|rareOwiQ?IuU|Dw+hhge17{}3 zQv!i}t0pY*)8Nzh>G*3>xR;Mdp`X7o$$HyNEd}pDcPn38R4P1rT3Gu35ck$$Rejys zFeZWu0xAsx0!k|-t+15_>F#c%bAv%CA>E)fBHg(`O1e8XoqMzCj&B0~e$R8xdEV!| z=e^$V`>xABymYO#=bCHIG46ZZV~+7tSAgS~GV`oTl%5VcT%dP2hXJA#kZlhEOS9k0 zE??mNW&zbV-<8jK5YKzxyh+m}NU2(2tr&2$l{tFLOp9RU#>Gj=^~4mg%(ExX+#sQQ zXhR=-8tE&nRPd_USFB|t_o~4f@ad@L1q(=|mpu9TI(h=}k5iw0N5 zTyWD{a?Do;@QYh8G8O93d`CvI|0%zd)scCI^WgqNi;)`Pc&!0#UCQ<@W_>LmJkr?O zhc*{njVQa^j|HW|&lB*FI8naR$D90%29-N<&>~tw3KIFts^Z1S>guuygIhMM9Dcca zzUc{expV@q%+>=$UcJg2uj1HO|<0$+qMmz<;A; z)XQ+Z;*7sWU0jh08p{VCvj;tEu@CdII*$NMd5AMimiYh1E4p zw?F#M;K?P<@tOU?IY%3{0zUs>mYRG2f?4hy@%sH%HrCghsA%%Y9q}89mZMqYA}BF~ zp*ryeNO=&obmuN^^Q20rRJ#!a(3w=ray`LgReKoE7(a=ro; z8%yA5jCuv3qx9A}=5})5s_*&;$H2fu6wMFunVq3%uU)GN)f+qh6-C6ycB~BPFLiud z4yn*ZI?{!=_V&8Xlm**A;J^TL$ehw#0>_e9RLK8`9BnB*Tq3eDwk>=J;5u$*|C>IG zq*Kyrm~u^yaA~Ldn)q$wkFItTw(G;owvk*UfnMdy`#q>1j!(ldfp5SN%|s833u~E2 z1raK`lkJ4#i=ta~)i+Bm^15wL@5}65w=x_}QhFPyuW+}&4ERfL;I)da6aPRpqd8<%b1 z7Il}zqmK?3txZs^TcBSgkDvvd?>@C*0@&Hf)ZwaIp2@8OEo}qCdElScX5brtUzYyA zV!6Z9xlK3EFo-!UI+&lhc(k+ZHY%N)OSE<7)By|@98ocPCaZFH0UAzD>LA~rw2E7yb_ot>`YU_T?4bm?D=sE@&_5AN|FLvpui> zb>UT%1^Rl#G`q;<<*I^NMxJs^23`&$ZVR!iCQ7I;n2(dLijEE(8P$}NjT+bj2CT$^ z&Essj`^y0M&Xo{SS1eKi_XOXE?mPCXO^R^~Jupj+1?`+dSqt1An_{%7smKvaz&5pB3)c0D$e?<+mpjCjINo+bbPoR)?+^ zf}m$p&*b$NJ7T+O&yE0{HAB(4(@e4%YMpT9spt3xN|JD7z<1PSiua%!BN6~v(gfgZ z+E6_|)LF~In=0~m-MB06DU40rpX(S@vCFZ3oAD_lkL$FU5Y`3gL-P;-@e0PLnZsPG zkP~}{F0S(JCbnyM?g6f|p|XfkWyf8V^~!jvjbDRjS8k2tz#%z}Kk3>E;%h{({S$;; zv`BxFR|{}6$Wdkb`=9mFJDX`!0moD$&f06nnq3{@g$UZL06x$#W8=sf3E(x$olqN2 zD#RQL5I1j~!@cDZ>Tk(nsod7v@;0X2^(=>nE_&YB1*K+k)uE%3ra?(!G(7*2L9*a5 zs-1Yiv(=jBZ9?VxJoXPtsc##pm0CWg_1qhK}TS{TG@m2EmcZ zXFtUEYxqyh&l=~vcM*so`V8@%N7y8MCb|qH&%a6Q$ZVX}(6OstAd$ z_M{SC3?|2m8xEe_jV*DmsN`>T53%9YJHWSf=GBxnbpfAY=ejaY=#Zr>&o5j2U*rNU zY6Zq6QiX;fE_G6I)ct`=&Py;E-D7TatXLElIWag$vo#4$LNc`JuMF(itNDgcyJ%ZCZquXT@vw`9G~1eo~^(M+Wr;rBID&M&%~9iFt6V%Op|u;i*6pR8^2Zu~rY4C;=gRz3(z_wP|<0JM&r^?w(|l2iQ8=4-(`B z*k_G;WvinfU8(SAZ9-uIQa_8{qnzr^5NY0_X<~+Wjvub&aFEP zjP0L4i^s6fW~=27Pjp24#*vKLl*fJeMM*{VDq7^eGi{E<<6ZN`=PMKM2VA>{Qye}4 zgZf{1AySLP|4b*hT-MS9vBi4 zJkT=aqeF0wA6A&=XUraOLVVkc3;R?=OfvW94;R`LVOoL26-obqfEipl8#3M*8!o)& z0C^)=vEDr*LYER-3Q9b^??I8Sz*-1HNHZAt@#K-E(r}ufZJC|Bm64u733-%wj4~NjXQt6-PL<-U|^^i7%J4^ z3Tf2!b8%*^XYsyzjgl@>Bq)K`aTD>nL|sWZUE;B+rLKDQcb8Y}=cFPGa-WbCpEUNH z{8K{RIU6sr)B@81o5K_gpyURU@R*tCaJc>EVYigco=Dk!+1lFRef3HuBg<5wbb#sN ziXBo>UfT%v;|CoxcBzm~I!H)ssz!*C`*%3+KjEX|;bV=pkiC%7THCZ#ujH(~m81+N zBB;uEtCzxVCYD-!gpGLz2t@cyT4x5$nw&<>AVVjX;P!wdi1k399XA1C<%_r&&%x0h z;%%&;=In_=k;e}Sh>o4T@9u-BDv^}02n2%QY)rr_N#S;{#+Sae$iiF`U(vr$MveOv zC;M#8sN^j;uqFK^X3B#am`kJk6%`ebhG`Z^N>*0i*Yyk7P!s^{Vu4t>OKf`m4*9am zru?L}N_HU}%gj=c-mA{??sMv&yQWY zgzUBVj<+``zsS?d0}G@+S+YF#-NNyFE*wQPINB973zQ3e-93JNr61Z{o?h8-RQ@NDIymQ zp&4AJ{)Da9X@%&0$5_iF7^}c;Y_7BYO<<^+O<}ey5PJl6lNEolTlExVmKGihaU7aOpGkZ zY@#Ck#}!G_J;dxh^golb<>h5yB(-W>+8TQjd`XZG`e z*>_=PXFbHhJ&=aQRY2Ud`wYo~=z~S(Z5n|_FvssK2I&B_g%ERT-p`UONQo)9K;U7R zUjs0}h}Cak5~{052ly$jUaLv2o|w<#964BAEltu~O~+)4R8vt&@aV**<^C7@631V%YoDr} z&a_PL-Ys#zzXFrC zc03E51X3-hUMo5_KgPLqoA_I_>naZpSvHlq+LA8S0c8`MW$IqtnEslfN>` zceMOP{0m#172#Rm-z|0LaVZd?#tHsdjqHB!4ucm6F)6XlZX9}DUtU>RT3PWY<5*9( zs04H?y)w&vjAMKA<2N5HM5V>h`^N99AQ9pE{(*Y=!&i`3@8e63D~yn5C;Hm8jyC48 zS_E=RXLWoPYg|roBv?E<=YWyz$c77j9`K6A*8sTg^6n-A{Em)f;}J3xqh8|D$oCm7Jj7KSHzc`2aXpGidHlssf1aZ`b z8J!Xk&BD{B3<*RMwsm=NSl?za=R)RDhFf&Ed+V5(;%rr!sV(#7j zo6dcTn7sB!-WFCD)wV)`>215zp1qf!tSOp14r-eAXyq*qY00x+4hWpx;9D|r%GsBr%09Rvr{TggqImxfzKV&9Na=@c>iO|YB z9Fx4^)d)f!ax^u7rUB!=OU4@!9iII5$xqeNxc$jnLPB*`uGm{UJFj)$iDqUL6`7AO zeV4+rX#AJ#&i4r=-R_>a(gVyJT3Tlx-%+WS7J<;MPhfnYxCGAn-3rH@+-GxunSA-| zCoLx0*49>9oDYE9f07}M0^Ai*I?V|}SFe5S-BO`=TeUJx$fz^DShe>J|5J{P58vs<#@psZcVIbl(HCESc-8%m8JlLtVVGjt7 zZ}+q=X&EYj1SH6VjiPTcuvx#6OyDhA9*g6!=?JJ}J$|b-p%!30J0SM3mdWT@;}GQ4C>-Ci}ePbI`XDL=>(Q% z)X0s{DnQc=Y*ZGiLlU6o{cBEe#>k~|^x<5g%9m&kHnBmvhMA?&G2=r5ueE^UC zzoShK)5qSEkrg{k?-S63ZQjPJSFgqqh2ZCoJ0)n9*|Z$9fB$kHvoZR%k}ptsfaK~= z$nP}SF8W^MI54s1B?NrnMe7%45sY!{7Bd~cjlC%-0iUydg4o_}!8=zNLFliEyc7gE z${NBxrBt>(bg!`MK`h?zV)yRjEUOGqSgpGzIDE{qw;=}@B@9c0?cMlqD%wtYg%-A5 zm1=adApFRv=VmJnGAJxwM~Y)G>(pNina^wz6wKPR9LaS<&p_5k=fPa^yjCYM?<4)K z5)E9xu>VHvGu;OA)Ftb4E7vwOJ*?htH;6bDH!Q z#cRgxiIe8v+}SXlQjp<0t;n&aJdaO9=|5|GsIt_gPb}hpT5Dtw7iT@lERB_n>fIq*}TZ<4D3q8$Hl2lCdW?Kz&`*Vmsg^37*qwJ)28-|s*vg{0)>8a=t^bWSqg*LrphF+XK=omcK>Yf|rW zHv110k>_hj$a9BWpvLYVySkRR?pA#(l8_(b`ok%gs-~4*YmglW^SIU(jNFdsh=S<@ z=%QL$;O5buSK+PFHM~krbMA0z)xQ6aq{bCtolL(*+?`Fs|CQ31cF&%jg3_J>kju<4 zh`h4A&GGgD*kbBf=|vLyCOS=u-F-s}L%?7|9tVruy`%ZFTajFZGCa*lKi$Z%kUZ;$ zz5(T*oJ>ZXV^p`j4jvulj5QY|Mg9lag~{PAkaGdD?u#%z#+`kHUUVyD22A)$>&=^P z!6H9%)6=tn8cFLiP%?65@LTTQ48|mhce4Cbzb8PUVe+jY;Y|_v8Lf(;P5MGtd`Jd4K@1 zfd#i*GNPlO%N||W_?UMGT5v0ARE+gOYmkC5hKr<4Wd&;236US-|COzd>g!RsJo~Ep zjFWq`;4B{Roii5>;rfAn0^XbYkWrXxp7ib(b*e$Onu^T}5Iss7-k$@Z`ih&Y z##XMh95Si0KuQL=*5*3Ry9xOlq995Dk^d`!lMdKM0M0-vmsl!r>oS$}WI<{}cXRA_ zRFn+JnfJ^}E!*^MC@bzm`#>V5mUI`$VrHT^&nxuB4MjzWrvw&56`eG|&)>Xxyg<_g zdT)T-Ap-9ezaP_j(;H6nxKDY$()e@DTi!gPYDDsEFfw*{z46XPB-XRssn3Ip*XLr| zAMX$hGrvHoK*16KQ#L*f2xGwSB^Ra({OZXG0f;<%f)V8nQ=V|4Wtf*5{<2qxh;c7? zQ#@*sJK?{wG^#P?ht>QH$7tu>35~2hZ zpg*=!_dYO#feJEUkAhIzV@f08qq-BJnz7?7!OW?x9V3Z^x3f4S0o^@gTT<#XGu`%A zuR#;1)_@9EdRk(2`t#{dsmr|bxJEp)R`t$EWY!?lSrvxf?xyuv@tN`DmYaq~{LKWs ze^v!ez%J#3N|6pl)zpCG3ku=D#Enhs0Rr!)U$P_ggIMw{KO9ilpi4=z=Ie|4`0INa z(bH^Y8ht*!A_17N^`MY&K4?UQ!l0ZmTx73p{VAilKQZ~3fVXU>erQ}q)F zErhQVA%<;#gP@Q8%fvratkxqmg6X}bj^6R<-pAG4t-3UdvjD{2cw-h&%EE!)DhH_o zgDo}4vB1lG(<#R8-s@4mRY#TW!vc!N6dBdx#uQQc9zT^}F{r46$d!?7kfA>fW=1P# zzv=CxC3yPcKi^B;Z5q=1xlPRy9@Nqy*+NB0@7PvCn(ZQack1>|41?eWHv?s0yZ?!1 z?J`}ST1P|6{_r>X64ZlV^Y?1Lyna3R!)18~G_?O#gZtkW>;CyF^Ro*DJU!EMSg`8P^xzxVUiZGL9Gbgv7(KRU0!mwZ! zjH;O#C}k3+KHGvb&#sD9!j+okua|H1a;$3Px^imL7&`7RMfHdCk(_yc!R2+8T06Vs z(=9AkOiY*8b#q&BT&c->O3AP-OGOl@jMHmoT1)JE`LWQ7`eVgB!!ZYPRA?>9#Z2w6 z`O^2XvF}b>Kg0P$TqUO@`EGE#ne}V6K>e0lyJV)-l4F=C|2*8(>hTpRkaPRH_qIoM zB9%CEie`)DXWzeu$nJiXA?xeeVM{)ZigLDWPp1m4zN|Ce_61u*LmSOr#+zyrfLrdf zCTe9OqW2FwqtaHgr*(T1I9Iomx7H`vOD?b&+LYGkp`wXQdAs>YC3qRn+?NFRMLX)G z23tabYLC3r)Hub82{)iTVJRfl#Uw=X9=QNF2M;YygkdhSsmYz zhP}t~yqn8~x>B7k3+7iOJ87}mLls&0X2&6pHSHw6vg@#uJ2+fT3?d}JQ@G=_(*5WN zsdY0;WWe=s!{3M6iqib@=ZrtmNO`s;_-Vc4WtwHpAjN4Ukq+Q`7wH?vU5cZ6>r}Ti zpm58M2q$0#nUPgbirZhJPRB!Z`ni+|$sfD16#Zhj%Vq1=H)`?&r~vG!_GM*JToR9C zB3#VHbg0$1G0c-( z?oANr_-*vUA62>Lkw5n4D}C5erx9+?Z*5^pBD|RtO&pD&FoYoGrVX2cfYcJIz)S`8 z{=I_<_GjNGi=xpw-4E-(F@9W#r%9^hdM!!D@n=S*@C0tCY94%c+$~s54DB>h6xD~= zEh?{kd;O}Wo|oywuF{0cIkm8qYyn@~F9Z2Ce&v_hyC8Dj2O}kHKeNIGGapkbWDk+7 zu7ZsBj+}$8FRmH4?{3FdM-Ts5u*K}}K*ki)lUBxTGb>j21SJ6@N}DD9Erb30l)ZRM z_hg83BNlc$5{-tqwCLD88i|(QXp=iX7_JHbSp1dIul$IYtI~RJWE;%l;J^=!v4@cR zi7K_waTi|uuJY}@!;1Y%wR=5%zc#U$7CM~b(r<(m#Zk6By!nq;?1aalx$f8xvUgKZ z>WK^KwM81LoOnCOX*y6SgoKwA&NAdexi-W50tZY%w%6Vj1mCo%h@9V<|{!p^WV3^}; z5x&rt%L!h0G@ZGA9>RS!K3lPSn7^9HtZxZLc~)32^=i5sI&8R>)?6R%tt&E_9e3oH z%XxeANM%gEt={!ORVDiNF#gr89kxWmE3lCci~7Y=ctADG$c9ToSZV8l+%4L-O63Lxzg5%j9@G$QV6f<@_Yf>XqsQ*Rpj`9RM%Uj*&M8o zqwiwh0n;^uV&*eBkg?I6tiDRQnLX=O>vENJ@nvON0N&+$7fIrEq2cx9&qsEhS!ZGJ zAXp3Ax>KuT@`Nt`zgtj}_nHLcgda&~Txa!T@;c-G$-+$z1*^;d{#G2re`S!hKfcWQ zNj=*ur8`387S56G3Kyql0Kw7f*#@~N#j7R)`(F}(#hq>wQvW#0@fz~ycI2eURSAf@ zkt6bX=TYwVy?v+;P{IGnUQ3?c`?&?YH%8fL3Anva#*p^*Bx{?xqHM zxf@oXZCSt?2Om{^YZE^=cUtC*{FD2ugC1rEdNBL3z_gXiulJINeV0P{%!V~hnwU%X zMJ1onnj5H@Vj@RVNKQ(E)GFod+O08?A}uT_0ab3*3r)+jEn;afHb)8<`;6L|o-lyS zZpmJXiy?b*^z~jJ9vNvF8S$GK?CWFYMC8S8O)U_88mf*lQ(NXGs|Aa2~oUtL-0jOAHO zCx<0+xDTR?q(?_fTHKG7Clpx8P>PTgP$c-kHvI)jrw_SwG>^yh06o61aovZ;Oh?pd z#R+G%z2B~039uD`P`o&zt7j*Ba>oLFJf;0A378L%}* zE9_U1V;)pVMca4q@fX)7u8tMuFAo$p*PXb&2_%^OslxjHyQl9b!S630W%R^CC^dEm zBHj44q@__4--STS#Z*}nDD>6-fEg$gjT+3(ip^>Z5-?|=V{#F%zr-xvlp>y5xS%m$ za&q6(+QgIJ)7Hl)ZgQwJ92wM{}(l!Q$X0@qTrpXr<7da!Chiv9&@y~u4hw;@kG&GU|e@ulFA?{Qp z0U_ba%1WGoV};B2Lq-S%MIHEq>o>PKzn&|o)UK7cRH{{4vqk}usQpA#DHI|>I}Wzj zh|4|qmYm@|RP<<9Gdx@Ygu?6U5>ER1`piapL%{K#vi&6)CY+6fM5(}O*_vc#<^4sJdydcfNePuh^6U}3HLkVJcAm(JaQ0+~UBuPx{xaR;r zTh}u;S65Wr{mHe}-rmkOC?O@~=UYXJH&WjVg76Okb8=t)3-#yXrSQ(jep8V@sII4Jo|5G%*S)2jLA zQd0bj*{}5=H1vdjz#w;v(|Vid&_Tz_+9w{FGyd6kyj*W=4C_*+k_ z;b5{uL>@boSkOox8aMdrSn)i$v_xkw{$#{}19j_vS=4`~L2SV4DLefE{AYB3N@@c( z^-r0J{~$X7Ah9v`)uqAq^mx$z_Yu8+XjuPrmJb9`jXDqeTbndz;h?82@q~rT8}IM{ zcRM?Y(Ce9RpFlw;VBuVTEGcBgjT=^{%SK*;J&*bRe75gR{MT1OhTOIZmGB*-(#7_8 z6av9!(W<|j{4x1tb$4N8a<4s8Z*WjCA|k>}k+HPcqVMsmoHN7vE|~e5`Dyy(Bog!& z9dfHqsGpXIf1WAIeQ83vIsC;2GMb;9`6OJOpw9EjwQ3F^9^}k9m~ECm=DG1^vck~9 zVn<0R^9@aC@z(l*_OJcML}qRAG>Q1rCwm(sea*4!m$QpDDg?3xhLZF0tasy_Yfd#t zNhWS$xo}c$a;PzdwnTuXvkEWH{+I<026xZXXZ`p=NojTD2=X|kG%7syH^NrLzokQ; z+pZK5qGOX{AST;d8k12xA7^G}MshY2_+r=Vny~^c`AM%qM>pFlcHlR6?quTJjBMir z#}TFZqm!6S1}YRpMO)xb7co$9ZblBMV0Ic|V)JEt0{6rHI4qToEG=tnhY~hW(!92Z zWnT)n780TSL=MMCs2VV1H1r^{`l}J7l58z>9xOMb(j^mjjz&UDN-S*11r!|z{F^Hu z;Fy@3yPb|d#q!yjZkAi<)N~X1}WFxZDfUqIH~?dIz)Btl+1_ zIH{>dWo0iMQ4fdH0wi-2_^{UCtTqknh8-~&cWyu)-^aXh^;N(mNCGLyt(n_8aB*=# zVUdP}hckwYfunoBay4VYt}M0Gm{8Y%9_#4Iyz8OArna?nC_u&+!)Mk+Ow9dfi;(~m z+0ab8w6tW0xo#w2^Mb@f0N!6|0_o=|8_HJ0=}YV4c3)5zHOc(=(S5AMVQ0_KZ0wD+ zbkGFHLrlMnlp;3T#rI;Vo5%zt^bjhj*>8uR0u;tfqIs$3{j5wf=a~l@HY2 z%s74x3JMClftD+{F)F4cBc0QJ_lP$9 zM_Edg@0~k$`VD|_x8L~&s-H0(g65^Hm5!FE-qbBEqD$-I=^%9V7?+Al2n3L}7NwM! z0Te;J5fQN#5y^v4mb-BsXLUc=!e=-{4rS-M-U6L?DMJ)R2B>#!XX=LCe4r|EASjQ>|oR5H9%L+B(nZYn*4G{#eSeup0H_$NA)qx*On(Cfgvd&0|FOcPiJtV{gQzVVlYY0}ZLo(HJeZ zjpcH+oI_>^2iXKAz8Fb|d%_*oXp$_(93+nP7myiC0;f**ah#9(mszh|IYrFo`YvsT zueZ0m-sOVCa&WAzA#2X2n}>(Xe*Q$L*e*mzM-SvE%E;t9OqBAuTn~?o6oyPHo`D&! ze*f;$pd9b%U~G$*sjp2=z_OLgU3%xFQ)K->*Pl2QR$9r!ufEXH<9c99LDyV-KL}`m zTvzSFpt?_p)n81G6mn;UYi4H?59_Qq6x z-zrj`F8fCahSwWJvrKX`A@OaG$<5iZz{?)>Q?NV0*4F{t*2(-txzaE^I(j)(T*>k^ zWNkbjX@P!;Pu9tO2&YOP3Ba^fmRdncDAC8bJYyW8wC-%W4SA)c7e`gV79{zHId{Tj zyZqq)eD0d)=pF+D@8yR5Z*9C+)8sY(p+}c)z7__y_vK&zb&mVL!{wqMer9AS7rSI@ zz5Etm{lz1_R#Lzcz#z$9){8NEKGc=}@rLj9iq`49pZ@;si(OkING{t&9v&Xa*yqtF zOH;=1-rmh(mo0OY>q7rCP~sc_E;(B1y=6RIOUuEiJk8w}{}BMwpfyXZpfzwt2G1&N zgvDwN0lKoB?j&3eyy&f7;?)!8MFe6FfoQN?U0#lkjYYrdV4|)RL@w}@jt)dXynb!W z!p%ZJ>7ce8&FT`jk>2Su_+-5IYkPwLGWds=8VrmQPr`0y%VJ`_L)^N0HR(gt_Z@a3 zU0kDIkLY}jyHf(5KcT}yetPjGDV~G#WA?od??jUBE(|if|ZlE zC--FP8$*6m?VR!LOd~qDR)4x57mXhwwnjk@rA4$L+r>`zhecYa_HP5`P9tlQDdZV0=I(kE&JJp4$)8{g-%Q6GS^g#@wfuF`Kj-( zuu~{P?O%A5{C;~v6jf?5R+8;^>T|IadATru+yv;eN%~IaajMPEkNZ44mGPAh(orv{ z=|R6C)oKchzUD-PTBTvC?DsOe1Do;jJHEH76jB?Bu}cC|s;@z-(wmNTtXk zHa5~qPcJmoy%ylJ$83}io#V_wB=-dy8mk@Gjt`Jy9Am8(k*Pn++?E9*6eD1fy%Uv= z9tWw<7pL&iZEKXvZASWBF2Hg3=vy?-^_~1#qt3V!YgEGfNliiDhEF%N$a!ik)DAbp zsPR9Gt7{CLemwqk5A*d-_2H#W;IW@vGVSv zH%2y-MIPoo1UmD~KX?H5IQyuXyJwBET8b1)h1LXAL*v5k!;Bmc%StEX9uSwVVmM@6 z{1jgE9qVfV%X7zfwv1%gq^G4dNipFI`V;c~sFshZq1Q8%Fqf1>u79hYYZNUh>EguA zt~opj(DX<@4m|JD<*?&U%Hv@ESOi3zeCvGk)XK}C zadv+fa;2wli$k;@@pN=_+(m!&>OJ^F6tJ*9oqQWFWTBx$99}d3&PvC?fcjJSv;6+n z4mpsuIBK8SNk9yhqbRKj`p_+m=zCDVD?A3&gnsx+?7F zcJ3R-6Hj6mPEL4ea6-`&E(W(4#jNGtRB;JAd1Ynadz2RS75krFPvi8_)6>t}IBVB_ zb+(1$2yP?$Tz_kyHKgcc@16Sj-Hx$|yt_Ko4mHwTAAT3lJ@Q&uQUEl~>v2pc=eKA} zy9-*xSq!Wc&(A*y#KOXv{w~8xdFFY+m^?*|`?iZK@8+7F%KPifA2Nz(4XoG=JXb*% zvPBTjTA1s{a-@~mX`ThbrqT=Q(E%CRB$eFpFE%U+Y3SD`t5=b;sI_N#&h-~dLG+me-cO@(|K;FZbeQ3b zK)?88#Y)JVPsA~FM(ND~gXxLFgYTs)?cRajV_PAOK#5IqF4QPD?T{9j$a6nESh#!P zy=fXDx3!B$UuQc!BM}EKnTJO}fP7XEY^v&?KijR%sX`^ASaJ?}?+g0gZloS_OhJcn z94__b#&AAAAAi(+JW#~NcdXQ^%Rd@9y_{v^K>W08stS#n&WcW1aunSDuVZ#svMriG!WSD11@!4c=VOgS&_w}3Uq zv2n@IBX&PjDvdUEJZ)3LA|u-Vtq)B1LZ`dc%%^uuOia=n7m(#8J><&xOAU>QeLo6X z>4!O*;UOm@r#0?J5>YQw%Tge>^8eWMe7BaKdM@!urcsYaW&`j+r?Ne1aSi%U`^SYR zW=gqL0%5PmN@!1aEOc~aq;}u;y*_hUD-X=KT_8HWkH0rLV!K#kHCDw#RXr7pceG~| z9nE)0PN}yC_c&Z`iW@0RXk9vASKru^(JZG{^_silxMD*>5VNe^BP!uhd9`(QI%6ev z^|Ja(7k0`k$*i`U!c}1S#AV$KbR+BCm8JM3K@%#LiVf*AF50-g2>Nx2KMv{14Xm(R zE>O&31Z#P_EjKAS4V!3gb+DctSn>iMgCL28g^t8XCbi(GvTxwqNgHgRf1U0aVDsK8 zE9;w>EFm^}60~%k+g@t_iP-#%8Qz-dx@Q?6EJybM*sb&L zjzQ5%Pgiqxie9aWnx2GrGlz?vxRIY6ZhY{^;^#jw=;HSO%8MXqo3uovlrKYyc&v6J2J{q!fNZjb3|NyDs@0g z(Qp!40qnQi{%E~$AoO4$zg|n9vp(be$!Pa$v6n!_itum)DTjrV_=SZ9?~mWU)qeZ- zGT@Ev{(6rWhN$h#LaG&fv#d0)pa56U7-hQZ+S=Ae&d9}!LAt~<+zr~4xK!6< z^*T>~fYp#bKiCky*uiOmSIgc*PYx$5)3dU(v(H3&2eO9l^i^@8!>m_(lEv|b&CFJD zs5GCJ@1uhFPg70>t2N;bYIbsTUiV(VPS+SPrGO|X4CK$2$8+1eOcj+m>QeoJ=U72E zTLc7-VdN*XAN{2q96Fx8J%1M#uKTrj_YV%Y5z7zRSve?9-9gdd&~&L2`_o?;gnemm zK3Pmu2xSd`T8C?i2qfr6;_!$Sq*eCiorLQ&7IeKtrHu=IUmDF)>MCB9jaQI*9?jrv z@>!k9W1sD)Gakv~m}3Q4ZOMYgUG@u9T6@dbeFK} z@AqY)fQ)+Ei={s2)vY-Ds`IRHa)WRwo&fgpR!^xkisIu50A-6Xa(F|fxiTzGE?ufl zuURtc{&NPF+A%ODCZh9qT5mS_AJ}7nC~io^kf^$>4i->WwLphP*;e>$}`UMzxP3%e`3b51BO6gpH8#^A{JHJ;V+7Bd2G$6-H zjhfnb*S8h8Dgy|(xPcY!)&hh)Dhx5bJf<;FujeT(I71mP6&a~DwTz_ww7$E6jS*1h zfwA3hA|pp-gg9BJ5;#M{ADU#Y;RS$0P$&a%IH?$tA2trIbrbX!vkPJK^yt`kU0#I# zX#L?Zh)h_!w1flCdkClCa!N{^P+gIE=I|_~R3JVe$BSKmH9S>`K2jf8xoZ;3f2t23 zWv36vY)oy7oL#5^y;|9MIA|E{Er5mU5*W*sr_0f-R3vW&Bz(NejhHw#4si|8V89K4 zZH79}eY;1=v{r4q*kuJT8Bw&XWH4x)7eC7{DsX!d{X;A3XZBfFpZocYpmm!9SWr9E z9GJ*u%Rx;&(romtu#oPV&ijua>q{(_FZ^6ij_KJeC_vbr--ULec}F`_LktWIDacg8 zThS6U;bP>zX+6fX_?@LCB@rTzleI|gmwOEW%myoaDN+l-8FIGYL)kuND-{Ck)7eaWna1#R?n@^tBED5$(xsvu=B0r>FGDIm_T8~5O6--cHC#*c^(Q)M#~ zQB;}&Iayht0c08UB;D6H4~CNRSk2B?D@}#r?OECeT^#F{xFPCQ`q@{wLb%h3;KyIkMuE` z8k$4vI01N{*y}o}*E$qG?7TzKFqq9lng05Lo9#?9dG6diKFRNPFj_Wq59&`Z+~$@V zznodNGT#53Q|+>&UdgmG*CH3mq!Abx%@_&1Qb$iuep%UL23=J{#obbPf_h@bGmF`@ z?$UHX56-U4o*NU-!654HyHT;Rs1^}v)i9EW{E}G%cFVogG~9Fy43JyFB{~{zzmnE{ zm&3!uL7o$f_V224)Gdm`-DN)gJP%#j0w342hK3uG-gImWPX@=6F~O-dWT|Q0nFCP};JYBeCYtaV9}a z#jtMa5AW+XV1bdEPaUj#AI(gHNC`k7?A_Gy%s|vW=^TQ<)dw9P zUsG3ih3#+tmP^OH`yEtA<}$I#XdOY`aLg?Vh?R@TCE;aTnwH@2;@V%yI5X*6fE6O4 zQ2r}IKD>>z=YSY38}o+sHSoK$wBBIHmANR0?HU~&?IKxqX2NDda48zRizLZC3alD8 zsfDo@88j-4&))x3@KBqbo)loT&%QUa)wP?eQN4Nk_MydC!v0XHm)C2q5p*g1lhyJ? z?xxNI)XIEW*h%OZc)O8(q6;?@Z$Z44^>oEU0j`sVt~6#xW?NV z4}0{9;32`+*jRinK5ka}%Bm#6RGXE_YPH#(FflI(?uxF1L-k3H^MWzV)YF4`p?m0P?%{liB?!qPf}&*tvUxu1acfIZe&e zb(7uQcyM1^>stR_|6o5R1q0~Qx)*ppezb^}0vZ1oJcOa8<=W!n(ZM3u4&T9z8ywH0 ztE*4&f-a(T5;$NfLu>f?Tq|C8_;)bxF96STbXxAQFYX}FZ< zOdK6S-=e##VPXbO4R&V~^}2@DfO_&ggTB9)1irS=%_CYG>Mjp~8b8O8Jg8*4RQ!kL zz*v^2`pVj#0C?zVY+pMa&qZ}^XD@~ld6T@HCjZH&nv{e$?QcqO^#ZPF;|^cH zc&s+=B^*GbsT-Ee`y&rKrLkO|Xk@{-Uwi&!w9uEAk!Kc+rkZQ*Mqe-fvFrXH4S?qT zUr+tV!yG*m-+@-e{1c^T!5*pwFWvzw+vLT_^b~_+caxSJNy<`t(t>+zmEm(F?XIS6 zMCintNA4ZpU-XJM={H;DH$l7cyCW_x}ewJ_BZyNdA*IGz!9-$8}-_m=%+Sf(3 zTAQv>@ghP=o@6+Y%gw1fbSMLm9N?1o_S}v)(wl9!0^RM0fmDF;@mv}5!~pR5-^XVN z`CO0D0PF#vf2RXjy7iAfA^6m9PcHb>J16x0SO14TAgL^+AwR3n4-bw>ktX#ehKNfK zO%3*DFxPM3N>BnVpm*!Ir74KEzKy{2hG%$d%h#pPuDc2)(bSgNTuL|mK9 z9>*6Nm*-#$#K_Y_`Z7op4wDB#n)B}5wnJ+ec_;i#hiVt|1K&dg!5nPo0WRre=fN-S)*HZ9D}Z3?iXqNBY&y=mx-KAI2y zDCm3c2;v1`?qh~(<;a4t2a(Jt&AmVJohK44$A`D}JP=~=UHMB%rAVs%?~uEssOT=> zz=)q>63SCkQ+XC@758QY-}z-_je2}d6zpNwUiu0`?ohsc_S?5_o497)6Ql_hP3=Wb zGGQCt_u2v>1Zv!tB_&~v3OkjofryAn?!$Sd9+^H6RkdH8j;XM;ABit$Djcmch*d@E zZc|#EuO74;>mM<1e_;Tjooe2@lAsH3*A+6b{q70gxqat%N5_{qviRt54NaNvvRwA4 z$?Of|e-Hkx^un_hvnC1`$*rWL`z3@f%q?Cc?$S*<`Yb!{_|QT%cWFtlton}t4W!ZmxpKtqfEX6}$_zU^1jMD@`v!pk z-JjuK`#;0?Z#o6`8>jI#_X`68I%fZ$-Qxh6R$xEP!TiGd`1{r0OSW#^sx@`;L-mOs zZ{AvSD;Dw96+S%`dYHY-t*7GYTJ!rFdU`AOZ+JOB_}#J)F2$~{f4_V0uUfS#`FOFk zrMtd%@eR{GIIDY7U{LHk|PxqH^0$y!Z_qXc0Uf)?OFOU}u zT!HpM8t?BPuHxgKZ&vYQ!`19-$6efgdpU%imgGh(579cTyzDo>q?qw*+4+t4IzMu^ z2-N=mB4>2N-cYmh-|vsUdq7QhtI}5@Hf48OJQaa6E_;Bfv Date: Mon, 15 Jul 2024 19:00:45 +0100 Subject: [PATCH 32/59] Enable Playwright forbidOnly in CI to catch accidental `test.only` (#12762) Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- playwright.config.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/playwright.config.ts b/playwright.config.ts index 0e96d62c30..ba491ff82a 100644 --- a/playwright.config.ts +++ b/playwright.config.ts @@ -42,4 +42,5 @@ export default defineConfig({ reporter: process.env.CI ? [["blob"], ["github"]] : [["html", { outputFolder: "playwright/html-report" }]], snapshotDir: "playwright/snapshots", snapshotPathTemplate: "{snapshotDir}/{testFilePath}/{arg}-{platform}{ext}", + forbidOnly: !!process.env.CI, }); From e6d9eccf1b3dd44e8c842cbf33e9ff4253644347 Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Mon, 15 Jul 2024 19:23:20 +0100 Subject: [PATCH 33/59] Add test reporter to prevent stale screenshots (#12743) * Split up slow Playwright tests To optimise parallelism Deals with: ``` Slow test file: read-receipts/redactions.spec.ts (5.4m) Slow test file: read-receipts/new-messages.spec.ts (3.9m) Slow test file: read-receipts/high-level.spec.ts (3.6m) Slow test file: read-receipts/editing-messages.spec.ts (3.1m) Slow test file: read-receipts/reactions.spec.ts (2.2m) Slow test file: crypto/crypto.spec.ts (2.4m) Slow test file: settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts (1.2m) Slow test file: composer/composer.spec.ts (1.1m) Slow test file: crypto/verification.spec.ts (1.1m) ``` Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Move around snapshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Add test reporter to prevent stale screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove darwin screenshots which should not have been checked in Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Fix absolute vs relative path mismatch Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Revert "Remove darwin screenshots which should not have been checked in" This reverts commit 1e189977fa9ec873339fc02b2b231a314809b2d5. * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Revert "Revert "Remove darwin screenshots which should not have been checked in"" This reverts commit 5144b9b28e31ca543b2c5d02820c3f957dbd8c04. * Iterate Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove stale screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Revert "Remove stale screenshots" This reverts commit 9beae9974557c1ffa99c2372da280bb0da407bd1. * Apply same sanitization as Playwright for file name consistency Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * add dev dep Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove stale screenshots Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Discard changes to playwright/flaky-reporter.ts * Update end-to-end-tests.yaml --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .github/workflows/end-to-end-tests.yaml | 5 +- package.json | 2 + playwright/@types/playwright-core.d.ts | 20 +++++ .../general-room-settings-tab.spec.ts | 2 +- .../preferences-user-settings-tab.spec.ts | 2 +- .../security-user-settings-tab.spec.ts | 4 +- .../user-onboarding-new.spec.ts | 4 +- playwright/element-web-test.ts | 26 +++++- .../appearance-tab-linux.png | Bin 49677 -> 0 bytes .../font-slider-11-darwin.png | Bin 2120 -> 0 bytes .../font-slider-11-linux.png | Bin 2032 -> 0 bytes .../font-slider-21-darwin.png | Bin 3840 -> 0 bytes .../font-slider-21-linux.png | Bin 3708 -> 0 bytes .../window-12px-linux.png | Bin 66194 -> 0 bytes .../message-layout-panel-bubble-linux.png | Bin 29016 -> 0 bytes .../message-layout-panel-modern-linux.png | Bin 29029 -> 0 bytes ...event-line-padding-modern-layout-linux.png | Bin 52562 -> 0 bytes ...ent-line-zero-padding-irc-layout-linux.png | Bin 50908 -> 0 bytes ...nder-the-user-view-as-expected-1-linux.png | Bin 17497 -> 0 bytes playwright/stale-screenshot-reporter.ts | 74 ++++++++++++++++++ yarn.lock | 2 +- 21 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 playwright/@types/playwright-core.d.ts delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-11-darwin.png delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-11-linux.png delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-21-darwin.png delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-21-linux.png delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/window-12px-linux.png delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/message-layout-panel-bubble-linux.png delete mode 100644 playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/message-layout-panel-modern-linux.png delete mode 100644 playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-padding-modern-layout-linux.png delete mode 100644 playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-zero-padding-irc-layout-linux.png delete mode 100644 playwright/snapshots/user-view/user-view.spec.ts/UserView-should-render-the-user-view-as-expected-1-linux.png create mode 100644 playwright/stale-screenshot-reporter.ts diff --git a/.github/workflows/end-to-end-tests.yaml b/.github/workflows/end-to-end-tests.yaml index acd59406e9..97d9692a38 100644 --- a/.github/workflows/end-to-end-tests.yaml +++ b/.github/workflows/end-to-end-tests.yaml @@ -190,13 +190,14 @@ jobs: - name: Merge into HTML Report if: inputs.skip != true - run: yarn playwright merge-reports --reporter=html,./playwright/flaky-reporter.ts ./all-blob-reports + run: yarn playwright merge-reports --reporter=html,./playwright/flaky-reporter.ts,./playwright/stale-screenshot-reporter.ts ./all-blob-reports env: # Only pass creds to the flaky-reporter on main branch runs GITHUB_TOKEN: ${{ github.ref_name == 'develop' && secrets.ELEMENT_BOT_TOKEN || '' }} + # Upload the HTML report even if one of our reporters fails, this can happen when stale screenshots are detected - name: Upload HTML report - if: inputs.skip != true + if: always() && inputs.skip != true uses: actions/upload-artifact@v4 with: name: html-report diff --git a/package.json b/package.json index 14635fdeee..e483fb3948 100644 --- a/package.json +++ b/package.json @@ -213,6 +213,7 @@ "fake-indexeddb": "^6.0.0", "fetch-mock-jest": "^1.5.1", "fs-extra": "^11.0.0", + "glob": "^11.0.0", "jest": "^29.6.2", "jest-canvas-mock": "^2.5.2", "jest-environment-jsdom": "^29.6.2", @@ -223,6 +224,7 @@ "matrix-web-i18n": "^3.2.1", "mocha-junit-reporter": "^2.2.0", "node-fetch": "2", + "playwright-core": "^1.45.1", "postcss-scss": "^4.0.4", "prettier": "3.3.2", "raw-loader": "^4.0.2", diff --git a/playwright/@types/playwright-core.d.ts b/playwright/@types/playwright-core.d.ts new file mode 100644 index 0000000000..0ef2ca0ece --- /dev/null +++ b/playwright/@types/playwright-core.d.ts @@ -0,0 +1,20 @@ +/* +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. +*/ + +declare module "playwright-core/lib/utils" { + // This type is not public in playwright-core utils + export function sanitizeForFilePath(filePath: string): string; +} diff --git a/playwright/e2e/settings/general-room-settings-tab.spec.ts b/playwright/e2e/settings/general-room-settings-tab.spec.ts index ec3c14b2ca..123c214288 100644 --- a/playwright/e2e/settings/general-room-settings-tab.spec.ts +++ b/playwright/e2e/settings/general-room-settings-tab.spec.ts @@ -34,7 +34,7 @@ test.describe("General room settings tab", () => { // Assert that "Show less" details element is rendered await expect(settings.getByText("Show less")).toBeVisible(); - await expect(settings).toMatchScreenshot(); + await expect(settings).toMatchScreenshot("General-room-settings-tab-should-be-rendered-properly-1.png"); // Click the "Show less" details element await settings.getByText("Show less").click(); diff --git a/playwright/e2e/settings/preferences-user-settings-tab.spec.ts b/playwright/e2e/settings/preferences-user-settings-tab.spec.ts index 22baa19a8a..a67909b47b 100644 --- a/playwright/e2e/settings/preferences-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/preferences-user-settings-tab.spec.ts @@ -31,7 +31,7 @@ test.describe("Preferences user settings tab", () => { // Assert that the top heading is rendered await expect(tab.getByRole("heading", { name: "Preferences" })).toBeVisible(); - await expect(tab).toMatchScreenshot(); + await expect(tab).toMatchScreenshot("Preferences-user-settings-tab-should-be-rendered-properly-1.png"); }); test("should be able to change the app language", async ({ uut, user }) => { diff --git a/playwright/e2e/settings/security-user-settings-tab.spec.ts b/playwright/e2e/settings/security-user-settings-tab.spec.ts index 381b291e97..8d1f442ba5 100644 --- a/playwright/e2e/settings/security-user-settings-tab.spec.ts +++ b/playwright/e2e/settings/security-user-settings-tab.spec.ts @@ -47,7 +47,9 @@ test.describe("Security user settings tab", () => { test("should be rendered properly", async ({ app, page }) => { const tab = await app.settings.openUserSettings("Security"); await tab.getByRole("button", { name: "Learn more" }).click(); - await expect(page.locator(".mx_AnalyticsLearnMoreDialog_wrapper .mx_Dialog")).toMatchScreenshot(); + await expect(page.locator(".mx_AnalyticsLearnMoreDialog_wrapper .mx_Dialog")).toMatchScreenshot( + "Security-user-settings-tab-with-posthog-enable-b5d89-csLearnMoreDialog-should-be-rendered-properly-1.png", + ); }); }); diff --git a/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts b/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts index 09a140d441..0799dc0f60 100644 --- a/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts +++ b/playwright/e2e/user-onboarding/user-onboarding-new.spec.ts @@ -35,7 +35,9 @@ test.describe("User Onboarding (new user)", () => { }); test("page is shown and preference exists", async ({ page, app }) => { - await expect(page.locator(".mx_UserOnboardingPage")).toMatchScreenshot(); + await expect(page.locator(".mx_UserOnboardingPage")).toMatchScreenshot( + "User-Onboarding-new-user-page-is-shown-and-preference-exists-1.png", + ); await app.settings.openUserSettings("Preferences"); await expect(page.getByText("Show shortcut to welcome checklist above the room list")).toBeVisible(); }); diff --git a/playwright/element-web-test.ts b/playwright/element-web-test.ts index 3b12cba8cf..d6fd1b48c1 100644 --- a/playwright/element-web-test.ts +++ b/playwright/element-web-test.ts @@ -15,9 +15,10 @@ limitations under the License. */ import { test as base, expect as baseExpect, Locator, Page, ExpectMatcherState, ElementHandle } from "@playwright/test"; +import { sanitizeForFilePath } from "playwright-core/lib/utils"; import AxeBuilder from "@axe-core/playwright"; import _ from "lodash"; -import { basename } from "node:path"; +import { basename, extname } from "node:path"; import type mailhog from "mailhog"; import type { IConfigOptions } from "../src/IConfigOptions"; @@ -298,11 +299,18 @@ export const test = base.extend<{ }, }); +// Based on https://github.com/microsoft/playwright/blob/2b77ed4d7aafa85a600caa0b0d101b72c8437eeb/packages/playwright/src/util.ts#L206C8-L210C2 +function sanitizeFilePathBeforeExtension(filePath: string): string { + const ext = extname(filePath); + const base = filePath.substring(0, filePath.length - ext.length); + return sanitizeForFilePath(base) + ext; +} + export const expect = baseExpect.extend({ async toMatchScreenshot( this: ExpectMatcherState, receiver: Page | Locator, - name?: `${string}.png`, + name: `${string}.png`, options?: { mask?: Array; omitBackground?: boolean; @@ -311,6 +319,9 @@ export const expect = baseExpect.extend({ css?: string; }, ) { + const testInfo = test.info(); + if (!testInfo) throw new Error(`toMatchScreenshot() must be called during the test`); + const page = "page" in receiver ? receiver.page() : receiver; let hideTooltipsCss: string | undefined; @@ -354,9 +365,18 @@ export const expect = baseExpect.extend({ `, })) as ElementHandle; - await baseExpect(receiver).toHaveScreenshot(name, options); + const screenshotName = sanitizeFilePathBeforeExtension(name); + await baseExpect(receiver).toHaveScreenshot(screenshotName, options); await style.evaluate((tag) => tag.remove()); + + testInfo.annotations.push({ + // `_` prefix hides it from the HTML reporter + type: "_screenshot", + // include a path relative to `playwright/snapshots/` + description: testInfo.snapshotPath(screenshotName).split("/playwright/snapshots/", 2)[1], + }); + return { pass: true, message: () => "", name: "toMatchScreenshot" }; }, }); diff --git a/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/appearance-tab-linux.png deleted file mode 100644 index c16b95d1de3851c50706c36823ec9127b92c5a74..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 49677 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 z zfta-+f!RNg4HeQSd7=xg;hakCUV%b6&x^ba@EaK+J{{feXHIqk9PeZ!xGhicSaIJA ziA?496!N;iitjO=Bhw&Dw>dcAL`-O&-|#{7CY!mzV;X5L{bu{n(LzB_sG}YQ4L>@1 zm|BWxqMsQs!Fs;s%U>SG7FQtndRA-<#pAgQd@frusB7KbawYEH-vw1a)}J=xaCQ$3 zq-10id7QSzp;Tm&=pQt=6u#7{P~(vx6Qip!K0DnhN1T4Z(sWP=nEYue^>CY#5gMr% zKz=r-Q0tduIS(67>(4zoK78KRW*m4^Qw}B}Ff+H6bOAJwhTVKccn?^U_A+sz=}1P_ zv|LrUTu!ODrzX|VP|fXP35}l>@;vlw(JnEmQnRq`OdMXjZf$GZxo|tn(o|A4U5)au zO9AgzC1KOnP~zM%f7MrFT2}{mR_#JLA-+{WoXTf!x8vzRwL&-=BrmTEmgNF!fIh1l z7_4PvH2kP}^iVT4I$WdLiBZAVUP)2h<)9!hPvz4mS;605f9klao737b*$x*Z&7|-t zsIu$qDG!xyhlhtv?`pdeIar>?_43rrxlhIb=YOTXhw)O^y0N@A9fsZ|;9hKD(}PRm zTfqlXT(O?+@`?P2Sy|Rw>rEMYf83(}IghsMif@>;^m9Q1i2ZHh zBJX6Z)3qPnz3O8!lRBtAWt(CDaL!6lkJ)2Z-ML5PbYiS@VlaaTA4X@zm|cC6uk&_N@ky_B5ZtPJJ5&2^>m4&!9?T-{?NC%Zy;3_?7Dp zmWNx$>jD>fxOyvj(`3!sG2fEF!kr9U!-t=;W=1AQ9Zd8A5+XLF6QQ?@P;oUKxmqJr zxw)0!KbVa<8W|mX)efl31Y2A~SH=~~<#iMyEzMYv#%W|6szS(8lkcL;ulXM{XkXs{n|@^m1# zvECI+58wM<>wNxbYm9ztOrn8;_i%^ZX?pkl^yza4(sg;|^Ere{oQo7Y4UOo%dztzf zAt^O4I`u+`SE(2%@e}vHWB*JKuKbDw@d^68@!bAG`(x*&gFjV1J)h2~mjl`(a8aqx zWSoidA$otJ(3XU;^jRoD{*)DFo0!Lzk(pUX9Tfkn$8tRw<5-Cyo|=)-V{;~2ZtXhb z6{QkWa`Bv8p*Qbg9MLm+%`^PiZa$BTq0!$~TN(y|YrS~SrN1_P{?E~f6dB3cbCE9Q zwe4f0*w~K)M$22*xUck?N$=b@;&)3Nagnptb4m&yX9G<)DHlsiS+1X(GY>v%U{gM) zoZ^dC9Vo#Ua+o>3+*zeY-k;*K+v9Yfrl9}}BcmYEEsf`&4=WtBWX3eP5Q{3x2ZHOq zOpc6wuY-BcfA!)Z_mq9i1a1q`{qFGi@p%^>G8|{h2e@26GRZ$IuH8_ z9I8MLz3}0$x{)=tANY^!_xBJW2J!m-+q0|iEB8O@hA;4d zqkH!ed@cQt8l#u=|4rQRJqJ`nBupWX(ksG(U*=R)jM?w~0@{IxoHkrZX)Vy+#Ks(j zw5jVT0cI_fE7Y1Usb@$?3Bb2R`f&~7X#tPh<01V~Z@%X7oyyp_$(&E#ZoAA%_FKn$cFhuDvN zfKp9D6klD1$!)!eH%dh2@m>j@QBV*xZhoS4NWh@nr;0z*v^Kxs(dYdnsK*zR1poQd zPwZotC-vVn|J;`C`UM3Af%2xOLKSA`!U_udyW_Shu2BgI#B+HSMT6zPwS=?pJwV1J zcys?ah!i1;%FMaH-o`x;MSOjX^pc4cVQ-i{fVQ}V%T{)jpO>F# zGE;AuTAzM+Ou`8(E%kmcbUAT6TM75;UKtx3Q<%8DjgR32Rf5OCaiIuAY9$jFt1Jg7lk8GLQLK zORF%@eYp?)kpfDhOpG=R4cG7p2=*6yl8)^c(=(Qr+u!?zrm&b(jlwAJ<<9y&A$|6g zI3_&Y`C#Ok`}<+jFHK)5qGDo*iB-+6cKVNwl%!HJoWzsZY{$lfv&Qol9wDteX|8&9 znfu-i*)x_~^>lt~u=n0A^BcBwe&5p1^m4XaXJ91U#1^aBuWyMn+#YOMlHpRzbOY){ zDGZ^cq|{DcH;6epN{`E$55$!YYOZVcLz$PTJU*4kC@FEeEq~^FFbuLF(hTPO=;aCF z;i84;WM6zKl$j*Eh7CtdtVD9Ygme3~7;6ifoO*c)YILV2-jFeyB+W;Ggi>x==Ivse zSYCZ;sqAm9pCDkCInlq#o-sJ;Ybd>s^g=}IH@@#f@5+ni&S6Ue;78TDM9XMs?D9GD zSmMUEFLSK%X3Xk@7Hj1 zO^|YLib>QMkuWotu)~XzxVN^-Z!cp^&Rf%Sj-}HH9)=3StU+NMF|N5 zs6qDw9v+^(nB>b-fqC1w?iF;A&Vd1~(#r9U!KGO>_3fRV8I;gq04TAb%=Oh9?9 z&|EFJv9G-hIZAEI@|H)nILF7+IMMX<@06HfRv)$pl8Dl zyAvn<6^)MDGuLSeCSe+>{2biM##bMykdW+TfYJLQ7NN&N$fWXXHyeYHNxieDr^c1j zWwoFfi=6w<);zO^naf4~1Af0cYG)4OG;I_rIi11g^G36?or~i{P(`2JpTui(G!d{O zh6$vSm>4nw2lw$5_d2d_rGgvh>tcrfI&)#;7Sz3*+`Okk_wV0-{5Wum z@&#nst3Pc%Yyi|a;ZjS2aZ#(+Db$1$K`!u&{m&AZ!ra`|ot>fmN!*rZX5!Jz7{jW^ zJC1>|1xDv#_mRBTH@8J8kOu0QY#CKxQt68})$MLlRaKaStZ&L~*KgOd8cj`1&UpKi zD+dN9eu7W#d$y?saLR^jlz{VPo2md7OD}$K9{#!$=gk-CbRunuZ4wF@S8(k4)XTgQLkX?R2|i2{kppGxcLj z(NBbo8f4r2Lhyl+<{^W@#g&l<<-}R-D>lNR`$Q~ecz!K7Z}I>Lw$gniRo!cp%Ce7x z!~<3I@OO|}>FfKsrCe%9nfwmkU~Zep3zno2@7pNVN4Tx`=2@e{;Ky-bp zum>Bxr2N2&!v7vlua=Oi`D-CIwV=?Yyzma+a^nHu(ZHkm0EU0BcG)s_%Qcdh^xc9T zF2lU<-dD`+q+-0qQXl<+7gsSdj`nHQlhU z+18_NBvQ{0e~%&sp>2b11|CJO6_wT9g7A>fHD`0fsC?nGz9oET!qZ0*XceB>Pt)Gv zIsk-<$-yIujz;7@GH1YOUWuur86H^=PfmoZE9WklC`tmYTnS@kk^l^Xe1q|ubOc<< zz1Hqa9{O(OU$hRJK!%3HsUc;fcg5;~P!Urc>ki;I>k4Bo*lZQw9IOfWU=Lly?*R2? z@bBvLZ@_UH868|MZxrvZA|{FnkEZ~ls1_#6%m!7T95Z+G7gH3+igD}z0E zoHP}#+b?cqEbA$K9{SGJky*#8w{tMF#4U0wDvO5KY%Y@Hr6fmEH%0v_eRKSrQ}zVD zMGc-Ij^i#qL48b=o{BPXABiX^DMe>rvj0eZub^NL>ZX?cb&*dTU-`6By+ub4eofD) zs3@DX%a^9^OL+HCezX8bw&}Xkj?3-pIUvtx*ljVUCe3_ZjNrsj68KSm@j9DH&Haka z{w_wl_<|jALTkGvNiJp^38Gbdd;2s_3(L6@&+AjVZL@+twWCnixDWP>^d8B{i2^QX zS{j-Auem?IuV0fdwg#^GP1Ay^!^PD>OIJ@p5>STN+A`@+*;UZcSa4*ZXQexBXBS(y zyXc)BG-NtIMVN9rw1!Mf@>rY>3A6cCO zDB}8Zid~J*V^x;qCG{)*qP!vyY34l&@RY8K$-0ng;i|5jIU|4J_Szr2!nu0 zRXL%JPn>07SZ3qKI>9gP3!?&%aTX7Lf(n_eb_ReA)gNT}%y+0IrEe&G^bA(GrjBD` zViv8cK-At=EEW(T24IWx(9f3lMI9_sa!Vk0U+<9!RTtUz? zF$uf3Duu-cy2ce`J2@*i6kb`C%J--(n`Dw1SP5W26$H>yCIQ z<}S%1lW#T9DA!2cFuzSo?z2-mGRmm;f@xHqr_*4rQ?1@wFRo zpWB{EBg*LAPi({znYBY@qD!GkT%Ju#Rsm~Vn+>@?7oVD&V{EbrIe*meg00O)M>{bc zRpDL>D(8|UOIE^47O~D=?kGr@Gn9`nMac_&&w@&kn)j9k6`UgSK_rF>>7>c^!6r4w z05YICM4%+^o2{XAt=~))!wXdgiDSD4uF%x1iu2Y5))#GhQA&ymFq3^OAh#}Pm}@XP zR=S0^vcKq~2!?a|9G^@AF<*O-Rq;4Au$6KF7%2@W?h$gb6fY6+@kGbF`uqS68dFEP zopkSLt7Zy@HdE}bt`HWe!U|M5oxz~hP5qS^4kj@u*OZkCS*)~$fCC zTRFzg@;89}0ell(@9wyyh?mTGv$2M$9vkq}O;X!m5$kO+h(&(b;?+B6&*I+VRE7Y{ zES~l7)9uHKhg~wt1 zF3LaTvo8VSKzZKRmy<8#PSsHzcn{G~s?SE1WONm=3UD|^vksTOp7dU;C1MZ5>v7U%!J4)hMO{g6LEO56iG_Val|-ed~PkgQ}# zMZIghqX~SxwcRId zVV9A>fJ$Dh<5*QHg@4U*!8z%G{s^ik?)LJ(ZZw<{I4uh7f!I3Q20A(!Qsp1oLFp8* z%?B!H-{!u%!M~CeodH{1V@*d(%?aS+yi<9S3Hab-XUbIBelaNkmWv)-veztK>6>1j zmM5~0$_ehp9R2mH&VB-01~J14KkZYi+gu)K2f2@41L4_FUa-O$Pfjya%%DL45Ud~_ zwzd8I?^pQgG(VN#;5iJ>j2QJDiH_vClW#RvAjCx6#PLb^M&x;T-`(A!SATD;tl6(g zd$16LywB68PlUe5#Z8>%6C75I)uPdIEXYV3ebBZpDUDdPL!ccC)&D22htfn&YrS_1 z$8pl$441;2CPgTLVEFf>L6fFGD3L&hYz!zvwwFfNZ2(@ zD|{pml1X8<2Oc->ThXRz{VCa_qoeGjhcY%@z$eht%VRZQ;N~*SV z1vDTTk*>RlMJmw!*y(@8?IEFmpP!)Lg=~?TQxI8J*3k8z!rCTn9Pl$FE4y3NN8wi! z;6KV#DO3cHiHugRunKwT{SI{_>jlF0h|MzpKRFq)N@6igN$<0V(I7T9EGVJL{+@9& z{eu<7^}!V}HE9iukXGN%t(33$B;1=G=j0c%+jg~v5QEu%XEF{m@ko5aJVGh}#0HOw z;d4H@l015F`(v-G>vRscePk;pInmI>Ohf^cGTO>f+!X$|Gr&oJhY#`>7gaq5 zm__E|<~l8h*L1J#)=&7hAqNkj-Uecl)Ey4Aig?a+q+Kx_9N1Lu&MYB17il{fOzP*wG=Ig-(ki9gtOcGRa7>If`TVlOY3zx>xy z{J$=`I6@XP1UJwA`uBDXOg|@n!AfcfY$&*{6xjpy&39OpSv;JQ!;B#rbeyV1pSe**1k0=weAb2-!C+Ng_y z)PULqNfW0U?zIPuGvF&B?cEFRHh)8t#%eaXad@SFv6*=&5pVXlCu!snk@Qb*{!H(9_ygXWJx?pS;mmt5Og6(Qn zYL$lCU&FZU>Mup_jEsMd+T@QcskaM>FZPS-lCWi^KSy1>tk+m;r|Cz93m1R{Ii$ zYGbQQ(mY_EKt7G2KhYR|M;;Ic2r86{JR5R;scB2jBHRCaq|IJLUf!<0FEk>;u;;34 zrnEBLf90VRLbZ~DB-r`pstxj9n3y>Jv}Eh@8cRSyUY?D_bFHWz9H`Oa%3Ec{rkbN7 z1pEc6I=||gn2;Qi&l6)~uaCgnCd$SOxNQRi0-UvV$y!|`5=_jdx<_VQ`o<53hxj%2 z@T?fWqTG!H9|`$YGbAr9a1>CxwV?gwD)_x`NM2D<)~eawox1zuTbErR%BFe- zAb^?{QopyndqD$|dhKaP!x!m|`sQ<4rN{MX&^c;x^j z0I3&TKiL~AD>0YdNmnoIQq#2xoEATzW@mm`@cEpH#~LVRaM2nuon`MwK*tM4e$LkJ|K6o!wbS0+CA1696=|pO{}U0Q^X&#Dw_7?c(TJFw~ZO8(N4-y4csq&VK`e zw7PaZx%sokq%rnb$H+)pMa5;~AlfjuAI1V38rCd-a|15sRF~}GBfo^i#BV;n%<)gt zp_rB&RFDs{vY-~<4|@nEj739}3u-uJcCc{C2aVWHn~Fv@n=MzFt_(b2YcILL%=p(e zF*ENErbG8C3)IS?f}V2{5ziU37slLO9fn%@`=%B>oheshF&asE+(x?c#`m<}1EuNH z-k+IZZDjBl0Bm@BfkG@aG!kx|&x(pCam?w<%gZWHBcbW+E-xj@E0@(CV%<%4)aaZ$ z;Lri|F6mmac`wwQGdeI}byHaHs){SLyu1PpC1!RRK}B(`EhwO`ak?%hlT79pOCP*q zOx3KgE2*xg@l<%h)sU1l69(Dsmz6u+J%so;N$wemir;flRRuJ-y)Dk%(OK6MAji$f za!@pHi<9&UoY)QtIGATo7yyR3TlXzr@fM-c^MKJ07wWBcUQVmu& zivXbab35tm=-8{6nw-?AvHCMO2$@%z4^MAEM@Lt!ykfW9O>%kXUOK6&~tFArQN?+@@g`})3M3;onxbeGaxwy9<#HXp2uAB!tot!asjiZ9gxu(_ggHW8b^;WR<}0X3mDF)Jfg61~slrnDSjM!g`=WaRdKtp(eX z)YwB5WlZ#!gf@g2q`MEXmZoMjh`U7aw73?;5pCYRmvy(7`~Dw5a$I{Uuq@~#0HHOV z2u*LJe6`QHijN0=rjARVN&~=TwKrvIJWa|~-)6bBdW~r~+bP7h42FgoSmi2EVLn-5 zsrcd|A|=B?N%lFPnY3IqGUS7%l4;KyrH>!aGpPF$G2+7Zq~)f6B(#}S;Cy&^E9Iv$ z*PyG^Vi8%FUB2Kq5h8Hmo3`ir2x*TJ*I%b)Lb_NZFfJ|*u!~&V5LquQbuv(p ze8)xH6CBI77@Xi_CbY5<5j)YMF3^~7xh1g3>+fkrK4CL;Un}&d88E%a{cCXr8Z0$=+OVbgvga!`kNG2dq41f8wQU)+ISeS>T+{61! z&t0+{FZsi|2K!bg56d#zrGO78#{h7!u1^8TE<7Wf|K|KW6-T3cEZ1*Mp|7t`JQvZr z^+)SXfouGJ&3_CuGJTD6PPg~BKTd&H8R+p26vNp@R_LoTuFJ) z+#xU&XCm_aAyu`Q^O~c>#)E5lFc?CeMjR)74zQ*Fm#7gSDDwWoUEyAJHQqN6|$DB$aT+=ROl-bYUI)GZDi~MJE zzzYS4ReNK3?u?34*Nc}nk2m{K2}iga_lD_$Cnl==Qz9{fdwLmM`!#>%WMueMcAlPf ze(|2c2Zl>D108B| zwehCPExt9W+^#8=T?YIScrw*(@~iTRi|_w`**b`jH-KT^JIOzfusS(jtqoCT3F z65F|Xkda|#DY@%Wc9$OZNhA*5+asyDpaO%b&H~n$P-)a@(UG%D4pn+?bdl)RX{q;?u z#L8H+oG+6cPznTTDswXzKfg!nZ#`G-MLY9G;WCLQ+p~>^h%d(iw@zCIXQ!s)X7Fm) z+b`b74xj+CEil%&p&j$vH#J?6H!;Om6$=oq=Y1ihwUxIp%Dsfthu+M_LuJ3`!@N;W z&o%2`HE9*xoU|-B>`uWP;a@PeJOiq5I9yM9K+lYspsKb&tJR+B2bZU6RaU?l%go-) z)!DBE=;Lq-#nNk>ErkkbK7K;r78SFste{X1WWYTe9VA+V2Z~pFKqZ@mv{lYL@OyBD zz9UNB`-EK%hND^ERzvcn$P<$a*hHx!$64&Vmcs@HN-HgMM|mC7=advNNlx~wiSPHB zZdH)_g+9OB8P|Mi;p^fo`T4dRdIK>rd9@V`(#`w(+;yhy72SmW0IqgFy$%gto!mzF z=I4u5TA<$>|LWA}QEBnfMd|?04PC<61PLT=<-WI?%SQohLbJ|ILFFU{8w8S5{;*g> z@sxoOsYW0H=MUhbBd)f=J}O3tsF+;6A(n!P9MmAhzvN3$8C$uDzV@g3!MeGikbh`f zRC0^&Iq!H|tR_^*feJ9Y-u|oP#{mIblvZ22*MJHKGADTW_|2Ac%mc&BECZMO#>U1|AxSa;S}I0K)ZEBV%Jl1qI6s(?ib3tNRF#<-IR8JebGxev>c*@l@vQ!RZ=~>+{5h z1~Q0VTR`SqWcKBy=H_HN3Pf)s;^VMEPf>opE^O-r^tw9?1@XrdDj)ID6G<^Kc!O?b z;?@h=X7a|{y!7__fwtYE8n%98!0^6g8^dHh!hO z&-n%FeL;okod+tHE~DCQ5r>v6N$vC6VGD}7Q8ZMa+rRY|GvtJrm>8&`B(u6wL6*0x z9|J`U!%rf6k`=j!c?KnzWIUzzhg6P^oI>A=LL?m=`haq(3QI&CbANX)g-?Nc?Vp|z zAM8?_wjnS)Wtj}{!)(*j-(?T;z5S!UU&{j|6NN;6m%oVKokig~CA31nk2!d7?;(;G z<_n=V-=MOi=4#fPxrWr5cz|Mjwze)Yj(j^s*N_?S54av`Lb6iqql@E|fChbFX|65N zLK&=S$;>=N&S~@7Q>;bU43H7W$A;oKUC|*KWk)-Mk%Y*#M@q8WW4>m$iQK_^nvYDv zw9>0*1O3~@#DCEE`XWcx*F!_d5UZOymX>S$6Tug5=bH+^gQ-4U-l$7a!^}=-(}7Kn zpy;C~_kFLjr{L%3r=z3ZAEaQ6Rh3hn-iu5H@lv@U-;SV+Ot?yPOiW&WK9I~~Wo4nG zrG37=<5UY85`xrrckOoW*!y4=BW)efy$I;}F)}`IX7HX>laot*%>N1IESnz^f?0>! zcYR5|$1U!DU}49`!pcHoFtnK3FD#es1njOy-*!B(nrUeZ<5x_87IJv^Qo4FN3JMC! z%CDVDMmjsgX*nJS>D4o5uWxw7iDc#dlvP*n&CA8P!fDKfV<1FRK;Mtf&d$-1k*Y<< z(QebPzynI!cJlZR|_~$$QlJP4<+FJg}bUgW@HH zsOYzUFxT8&$8GFts*-~h?8KAm>Yjt(?AP@fenUuwfeLi&@>F4HNY*E8`7Q$!QUR?; z{ckqlAOH+r0b23_QDJ_evb@^Q!oqjz8n26U#GOy-YHhC37C~lH91U$#ZB;x~zUESE zqPL@o@me*}oDZZJHrzUa#(|2Z2ubhVY)qx2F*X(wIj^-5jSeNp0R3Zxvxjpvqk)z% zgT__wEU!$7^?qXI70hViN?(jnZWc)K79GJgEpOI@L1RkEqobnS+<30RmdWZ{JDEjvXH9+|g&Mmw8*!_Hh%R<>75d`G1)GrJmN@GRdH_C9!k zB&g@#m4rcdm&%R&bEs$u51zE2pV*4v43(3u+~JS9TAu9fSch{WT*6QCFq%krTws&- zjz7r(-P2JnY^^->8FN+X!L!dEH5`V7awx^ z`oVuyR6NDS%`Yf$J9za`O3Cq0kTI{L8K`ZB^E&JTSBs~HhlPcOySf?>UPj0n{Zv)u zx;@u=4gu|qoRXB+#j5G58q5efTDs|!jG~l+f^F{!E)6j=HMe4o7!1o1V^N(tFUOaN z0~L#zppMQy(*>D_f&VA|3p+b-S)Pg(4jGLc`@}q#S5}Tspz=7G`PMn7fgx2fcsMjV z3L?Ycy2JhT!9nsY&N8c4)6hM{pI62HN>@c1`-hb<*y!*mz8i=w(SaK2Eq~>_02aik z7YPtfe)*3@V|4w#3E8fxfe~Kkj)E9R!0ars@%=mPeURuQbYt)R)Ads!9CUP##;dKT zVaVs4oNDdRYWrDy?cE%j!o>t>`c+b~_nb4LDMx^d3X0rK=&?eM=W%sJ$&+j`+ie!n zZY1>mf0t-0cc~2}=L4-KX*WI0W?Ei3b8`b`GA~Jf@@44B#%%uJ+7(B%IiF&T!Qq;C zJ%P>A-oC8~?d)1#Lfxeolcni!b#D1`)VmLWVr=AWct-}F<6-L5yRq!e!vKAT6cpGy z^tAwc3qI-vTVqV(2eckhk1M@{sArA06;1l{UPD7etcHCgBqYN|z%{Vl|M_UkV@g`J zyP^^Xq@k2AuWN3ulW(SutmndgeQSJtS^*?QCArtp(=%0JE}Yn(&>8i)%<6`T#3M2~ zoSm7u!IpEgV^9~x{e<0xrj5vbMulJ$px#Fl06XkR6wSRE|^74Gb0EdS#_KS&0aR106r+&ccHuoVQ zy#EO$nQk7`WuYYKxxD~Dji{I?Ng~m#e_gk0m)v9FQuBwm7EVFrwfmIbT_<(2prAJ5qP$zo}E<^#Z3;QFz3VL@NUe>DS5X_Qw)QC{@Wk?iDM5zZR`h zWlL=`|H4t-9hdWT0k~j)UHs-1oBrh5`E|D603-&VLAm+N;(yO7d6J% zmWAzE$KPqiu%ZV4@r+!+-MeyS=ZPr1$YqZ%oQDSkZ3;kY1T4Qj#M}rCQ2(l_#^QX# zc9_7%{^CWLfIRF0;3Sj!Qgv0<@JqN?BlgfX_ltuMhy_f(PkUum+;`)68X;?Q__+Ov zsRw3>=N?GlAJ4^Pkwy?=Z&G6Ew!1dCg@0`)cmD~zilJvmJJTGF4le=3Z1KUO4_SZ} zw*^C>z@`jlyy+X}66*ZuOifueuFm;zOkml-1?nK@KEzUb?QIzoQx9X|+@07);#Ytg z7yyV?OZv?*5fBywg-l1$7%4MX&GWw!(fmUv?d|37!t=GWaFB%J_(_S<5@CSTmsCy!Yv=xmpyJl(m<(2LC6YJg1n>Kb8zM!DN+ka2P{$k&u* z7s;4O=P4H$<}w|k2LSf&wt1mzPM)0u6e;<~AmK7QFU4I)_a964nSjuB_o>02vG|*o z_>TpP|F7h2)x}BuhMS?_BpREcKOer zmlt__Jkw;hJSUCJrs!7RnYHTy%Kd;g;7HruYbS?}mv6s(mDs|aLd0+t^yA~mhWtCu@b`_~398gI|%a3>A`zpqosp z3HgMP0D(YcEYni{Hv37gXGjj|1oZH|YCyFfc!Vckhx=<(0#2{Bdf;tc8Hrws2B}`r zw=0oKhT)Kqa1Pp*riE8m>m$w|6GTTv?Qxuw32H$p55An-rX~ zzrE#?`LEz!&5tPlvt$Yn1uw7PCJ=->-JXS4!UX}vw`7Trl?6u3rzWTD-nCm-@PCB^ zd?jr9A8hZby@w?AH$QUC-~212w@S+T<5yXmRq;+v01Q*FzB^jIsqGjudQ!R0X+4S9 zgM_OYxC(GN<+A%LN;XKz2<-N+;>Rf|^A$aX%|SSNn^KQ5c6+r{n79BhR)@K-?Ovl` zauDn7oNhH-JFFBYY9Fq895*5wu%4jfxJhIBEiKtPfrd4)OevrT_vP*-dF}~l75$vw zX1h|;)4%H3<_fp=H4_QRF5QcKshMP8b|y+(F9lTZ7oUs1Ap)XpkDp+2J6WaPj*5X& z@J&mBC*6JO0DIv5rF|`h!`W=mpHdAPWG3QNs<4cpS)aOxlD_nr2@Sz}o}IhDu#>Q|MCb#oiCU6O!!OxOv}_%P@gqg3M6D=FFVq#a}q6A0t7!kW%`)hYJ0cl z_j8Q@P`YP~_Wl>vwOY&4fnx5rsOJtM8Xo-RE^Cre6-79Sy+uU^@o~!P4K~q)3**6_LC-i# z7SP5>_FTLN%#wVUhDSo50+9H__jQKm^KTz7v66e3=oib4a!x;=9os2H?sjJpWn+um-eI>na^h4XbamwgDJUMEDW5RF zMegeEuBVn-J6^Wo8l@*l?6u&6{~jFtQn@|TczZ9krI+7GRZ7WE1u(mE!F7&~=o#oK zDk@G*c_eY~EH48Y%zHQW5A}}yYvuAci8n{SMrFK$eE8plP&m(@Z-+cTHsA4XV`X7^ z*lx_lA0cj#j|nF8K+}hk2`43u665K)ygZYeKL8vRsNA_WpRHtJ8A^^N7Br-N?YUKD zxl~vUSC1<-I!q3mpUl4@w9!7jCNW2)q-2mlrSVi^%stp2-UPIxb-S87qQGRS^YCID ze5M{3pM-Qn%H35moxKMsxo_l-asEC`} z!ORNa2>?EyT-~2?2H@Lefb=#{UaeLua*-svaa<5fh7;bJ>`^Sq1327h`_qj$dJftWjC`eq= zqNvcE+$0v1JAkJ4gYcG|bywWC{8#3||01H(ync->G#3?>lbC*SxP^pIeTe9<}9MT7z2Ga*jR_?y$gY0nFds&GZB_aJ{I2>vw0` zUDp!*DH8UQqykHL2KBmskZ0+xja!e?z^TG^0VrbG59_DG8N0a9^4j8ZY z1Zu|8t34^XKYuPR*%}RNsuDf%H78FDBa9#^Mn~1SSL&qsJWLKl#NAQWm27PES@dMO{pu(9R+p( zbA3%(K_NLViN$#_4p@MLE z^TVQXN=uI$i}R0-KdSshy9xRh6!4Cb!vsnarlu(KJ&DD;GOMsNhmd0vu z7N82@TCZtn51NXKW<`I?J@sJ*qxJruY=yN)y(*rwh;h{0n4=7wQtiF7)R{l%0yIW* z-YC|%Z|gNP`E=h9-^K#I`1~Q24Pw&i;E222>Y@%FlgwWykj>=gL^A<$QRb+;1Cz|W z)QB~BrA9Tu#kRAG`mE<%ane7mco2^!RQkoX=Ooo#_41x5HF!#)I^P_Op49tQtL+BS z-~y(uXWWqnA!@VEsLwY|0O$$dRa9!y57q?J zZtTm=37;1v)j=<>U~2<;l(rJVTb|zudvuT9ut)E5TFhc#2BKmHhQ&nKINFnOk0^kC zBG{lzp(rz#-*L?E{6)=F0tttCsK11r?FJ#Xo4O*@Wo5A%Fnu9_3#Bs@X{ewuT8B6$ z$^3`O2Ic&x+&haP2WaY;In?hPWZJgPq}8*@aE>x$F^HbM8i^g&dF_P>f{k}hRl$tWt8B0 zJ%wy$;LDtOe4I-qMEy;JX8koSLDdA3%m*G31hxxWhV=c1Ly#~i@y7pA-FHScwRP>H z92G^1qN3CjK@boSY0@<)z4wlaw9usYqBKRCND(j~0@6W4FCj{o5<>4pY9J6gp@!VW zIo}=MkN1vm+@JS4WGH0s&0c%2wdS19eC9LLr{Gxj6?3br&=5zjj|~}gC!=r)_eGhH zQX>be-KkfgIp3yeFK&%wC{sfuBhP!%()caajY~=m%Nb>6ObN7@)!hg#cem5hTeZ%N z%|L5Z-V0hCto2NkFzXFNcfU z+8kA(Juj?`@Et>Ua%)z^nQSSrQ2m0|vSVv_wBKS5&*3W%Hr(%Wse)3H6QHUd59_V zYuuIoEX{<5 za{@iy@k-CqUVA&O5SMhZlCM@}H5D%2IOj$80q$iRr^&jNj?DpcXy|bu(%)mnjToS| z)5-_XhH<&wNdf6X6G1aAd*EwvyfkZ#$oTw_wKk{=EyNM2#v-L6{zE6Xf9lf0!b~#! zvCu1d&5$omOI?p*+1UNi~6E9 zA+KOVq%^RgCe)lWPOfCXcIj!^#`ll5Xer4G&pcBVu7J|CEdUHML#@zmL$9FWOtns*kxN^eL z?pcl>Jsl4ih=?Ko>JI^Y4~_}NLxkgy^5C7ezV<$qUjIH-755>GF{po zHZMvMS)>C6U_)s!yX=RKwhkO&prvesvr4ALRA*-w9g76pu*Cf1?8oPcgw*&%1gxj+ z(|cEL4MkAPKn1CQFsooKrucXhFVM2DkMoRiW(r${~`t<}ARQR2K^wWN42~6LI!%!QVI5yO zA3K5!#@CvIG1-+yugEZCOH52X@Ba+-pj+ALoHUL}$lttYQ70|Tck~f;qTJWu+~`s| z0la{a$OolD%yoN9LnS32Kc19}WPrsB05BIWE=?AxLJ9Z>@eu-WyB^8hGW;PF&=K-U z)fMz!@T_okC){@%4N&;xfT4$*z?ei#8yZOQ`NmY5+znAuVP&$!c;gYRdAE;PR zTq-{?7RL?%|P0PwH#n@DZViNTSKq|LVxgWhy}n@)YVGnif;yh z`;3lvl{vieGcO9m7%Gr_DUfxxcHDmR5u&A*D@cb>zKdt z_3)YE>mF|3>1cO$i5^9j>TY;Kk@(f^txK7ivKiHP!LY1;-nxkS%dF9_`S-7&)%;&{ zg(6|}(-v!U3N$~eT|5u)J&|5FPpdL#bS<xQHn*n;;|eYlJTUE(W>kmTqWly+x%d3lk@ z$(4cri7w<0@(RVqWg?>gvksQx*2A1;STX`?G5pJOfrJyjO0x;pw^=sFpk0w8V|6UqNyEcWeCm|;% ztFgY8QY%GeC=z~U{bW6u9B^+I!!GBu-j&Vgr5Ak7qYzn?y}?Pp-yP zPnXz|K^_`5@NKtr%HOjmmQ_k9a6D0RtN6q>L@*7gKGuv-R4?8sRLl6t(^$ylgu9RNz6`*7waGEVNG@Hw-hVtY-Ue@aryh@=n% z(l<0E1&})_WKPbL3B=d0x9``edZ-mUf3U0~EREF%SEAp)e@{)l?jXl571Y$ztXN`T z=mb=ptc_2W1cTE>eA9^AnhwJedrL(IMJslePV#uAe5cgJ#A0|5e&?2<_j>)UTjOQi zni-&wLAOB9b2Wc!D=Op*8s#{Vm41|hI}a4vt7_AyHDEAkdgue zeZ}}71RoF>2$KJjHmfaJ^5=J#uE++AYH4cHL7u3nz_hjdc5d}9n{+a%`#ud<$t{%3 z`33m6OFuaJ`ueJ!b1fS@l#>Ax2g=r4<&PMlYMElztx@{R%idr;a_8k zLxUf*j)q!?o*w<`?AM`s4jLnnU`|fC21R`Oyg(!R0wEdn(gYe%88S_tx_-pVmb=Zc zDasZpKVO(!g{PN*pkSF6Z;>;Q8Rw@5tKq7#u_-kqYK_rYlI$gB=0k1-REJv7ukFQV z9@&pjDfd~@_YkVLllLBFw1Gcch%!q3L)cFJ zjRZY+;F_2`h@$y&2S3`^1$t2a$!adofM=!qEMYzfm`n0qivlFm!NH37_&>207QJ$E z4%ib)YRlm5-EeAYq_mTxWB>Z(@-#Bt>%;u~wIr20`VzkzeT8RcbGvZ8a1U2kz=fV@ zEMFXFA4FAU+Us(cnO8riy23V%%uX4RA6HEvZiQFj4mksk;fq5+@P>FCp8t-a%^}b1 zZPeNz&kh7mmW6;vc8Rj(HP_Fc%0LoxeZ3cEYIOVW8D(ADuuATVHBZ%(JaKYH(8H)De&IXjN*wg0MxFtH5e>&U2%kRsupNx$qcb z)oMLzsN-YZQ#(ST88(q0!u3T}=@BS`Mw71mE~sW7Ji$bgPRaN!AzG2qI6ob5c15wR0V>oRm{YvtC{ySx5UFF30vUDco3y*&PJ6#CbR z=E>nJN+ubb00o6bDHoK`(SdQqY3XZ5qRnlK zLuu-fu^A#wEBApZr+`^US8HE{^sn0_CMNp&`+iDIy#zV=;bV+1@qo0v@hz`+vjRdD z6qsu_=aOh3Vd<)o6ml+3x!SuouEZP)VVk6a`z{oXIQ8w_KE0fW8V&0gi$!U1QQk#F zNr}2q3cb87c!(5Qf(j;%fYDJH9DJo2J2KJI5~lqf{QQyb^XS%ydqBnHsY0uTmpvBU z*{MUNZD0^2F3cxgTwYdf8(Oy3vfPo)-D_iwEw89pV!8T|l?w@YlO?B7i3o=`u|MO>IdHBz1 zO^_>Gf2H9Hfmv-0w6cGs>f&aBO@5blIgF+jA1Qp&JOm>&JR*IXJTM?i9l z>bb3LIdF>mei$AS@foS`Il_XFhn6MeN#38Irpw-v9(F}>KBrG`z&fW@!DIEhu&}U; zARWQb(nV8PcK~?bQ*{wyt5G0U5@GTMO#&tM+{)eE2G(u#;2_4xEdlP->mXU^+X?Tr zOMQXe9T3#&BzeYCj%H(bb9WQp&(qN~+3-B{^zEs`g=7y63W_Jcd*TL_HCHrtKuBV% zb_-=c;hdy0^nGQ##&cvg7dxeaTA5iq+{w=ZjnWRMR(TC|MG*JG;=?$@Zps8~V99&P z=b?v&g?gr5tEBDr%<0CD+U4%x7ks%R+{VZ3Pshg3Cn(6n6N5@!nqLAWd_iTM5shD0 z+Iv?ed_0;yU7@Kdoy+5BmW*sT+}a*5JBni|lN5*WJT*49ceddQdt2`%Pc^eRo&_yv zNR3}zoqzc9StjJG<_ziUp6v0_Scl!7ZJXFLyRWjqaQ)jO;Qkj^utY1QQp5LDqf}Lr zl4#7jDbL$F+rVrcraIBXT_rNT!heOd*?P1ppplcIim^q5z1Dy@3}V|UB_&x`$^OpHty$1ybzt4V6t*m0 z1p3mM>zN^(MuNa;YtP}F%7@PhHlU|Ro+3?U6{3#bU72cTdFJrt1kKGyHX0TIFHGVy zQ&gpF-GznGEtumDM7|d9I%5ip6f^TGZU}wgda`|n!pAWoI!X7Io50~x2_e|*)5Fj|WCx0x( zBuRx)DsADGkgBp@U$tBMn*#IZrs0p%D7nnwcn4$Sf+V_uh&`M0Y+7FT=Z4u?9c(P9 zH0ST?nV%>z9jkIjh>;-XDV61AN(m@z$SF>A^mkLJGL7w6;sHcAnq@WPCn zWtvq+_FyIRGW@LFVqy|+_?!00ui*)t?+iOB9%T!C<@-0jV)!>l?{_ND1y-`)zY=3h z=l&HPM*gcW_Jy%+7nGVPd7ztoYYr&QqTFRe-#q zcej`AmhJ(NR2-C^XuU53I~F`>FR8X1=%08i#NBLg0`du0xY^2z<_Ar;83VNns>PY- z8LzQP1o{1H7z4M>UUngn8`$+$V7@}|2zNIZPEOKx_8u$iYB)WBKwy=UCpHOL?n43q z>;Ulz!TRf;5g^AM4b+`O@D=NfyZi|jP9v`eO{>9f0-zdO^~{&2z{36r&XO8p;g6Gtv~1;)uR>X*e2DSBBiqs&a?4fY4u2GlTzb1Gceb8$cqFo)-(o$>T8-+m|i{Ncy2OB#i4{ zi!#85esqw&&N|f-Eu-p7^>|4ElITwl8sX&w98S;@sWTKIHf{6Sak39Q&QrwjE_f*@ z(xpf;8JU{qVtYnw_q6PdQ^d_0RWh!b;#hcu!NADf0o$OE52s|IoA%Z;*bxaVy5!N)ufx~HEj$}4Y))sVq}u3ZX$2kn!RUNzHO{TYM| zqX(95)nx4axqV>gb$R)Y_SX8)W6D&UZAF5-IhHOk#E&00pcM$fnibYB7(Ak7^LPKH z%8Hx}r;nv2s#q^nnI9?AGUq!TPwvL_-&syg@^sld;mG=RW}Mg?%}l`eTTlsk z?R;N1bcwe%PRJ>|=&%-L!f5=Ed@e@8%G#PI?B;{->j^FfzY%7=>Ofzy&Kr1eJ?Fu4 zFu8jz>KDnMZVf9Xi28dAx|$Js<=naOUXAp-VM`PBM_Jk2?%P{nW%Yur5n;?cA%{r# z3>FRfD35%Rh87rNJj>Pj)p@P*iPg{k)(Z=n{HCSpx4Yb|b5%`;=U)qO$tg@p&M z^Fpbpsoeqd)WA?s47QVL3Y=BkTyFa8%ADu?zP>f-vfO_)ZhX$tSDbTvQxfxa340IPT za4NeIFw@OF3jsU17Bl9+DlAG%=}&Bh+vZ7&zUbIxzWDC9JwOauL>(~$*%8CzIMXsD z01Zt&qh?Xn_A(ITj-hW#Lnzs;D44)kgCaTOt&&0=kgPNU)&V6e(`eFos9isV)c|g^ z&jue;2>y1qK+sOFpobxI7(G*rqqEI7=Gwk$L!Xy=jxPtF0$|(;&KgdC{d(ubvNxE$ zw0P`M?$`hzHCEvsg%SPU5MP=ffp(gGO-<5*WnW6lvx%Aax_B#9U|+UZz0exT$sm^wls3O&R#?Oa|@OA1`qYPm?@C=8>wuU zk8KOEj@tuWpXw?G=#y3pfd)%Z%_-@(|7X|K>vKK*M|Z*X!S23Jsw&13`q?Ubs%x>083!-uE%vIN5|czQ}ONny4$Fp`ZYr}1<$ zwuMgQQ|OHVqdp~WG1hqW6LGx=Bt1W~u(rjri3KPHn^T%Hub{JD8DZ444ol*gbjrZ)O2GjcBBRex^vJg?FJ+PH-8PBsW0Vevf&nHY)%d1&-`2V zKR)>J$?z_^L3LDYykhCU2AbLi%dN9Lhs#Ww)3DOmEz2HfK8=V4COPeVHlG;6eXRtG z*v9Xs>vMn0nbJ_M5B#&S37&}Y0GFi1@D}2qNJ^o#rp?g|8MG}(w$Lf*&ma36!jtRj zerni#UUIPq?tI7+J_ZSbjcsebE-oop?HC4i=p464-rOvhpeks+iP7h0Ub+vDD!fWNI;Qim0WD)Dxo8hz7 z`Frb(P7_G%BcT;*0Pc%3e6-a_#qdcxVt-}lq0RHNU0=AtEP`Is-+sVbbp=skQEh$l zm5%B8)B7e~Rm0b>Cq-zSxvAhA-j5z0|JT1tela&pkou8QW&nS1G{yt$HQzm6kR4~0 z@c2`%%dH3ZpWQi_Y&cekGqwc5H1sU#Xm5FQumb{pE9EV`V#jjJQ#(s*=Mr80hj=qB zAJi4Aui-E!Thm@cYtRKa=()Co6!X8nnbG;TnbJq~*b^sET(w8_9+kS&YRDH(zmD9D zJQL^-;CyfEg)+JJP6W87D~NDtK0$;eJliuu3+$JUYN`a33 zB@D*oIvZ_LLc6mEm#}UC8y~F4OtKn8{a1;?(M*lUI@n(@8K7X|9^@(igg`L>w zC>i!Z*LlqAq4CxKj7SMP!1#Itm2W9hX>GVKF8(JEL)+;1xSc$4h4rMVT-PJj)6#Q9 zWKr<&*+GA>%%-gT$NA;qlhLtJq7y3(>tFXn_FF`zmo8Amv>BB;=1i%S9aie-*ZM4P zv5z=|9XokpN6Pz-GQwq`4wjyiSfOYV4k*w0S_UM;lIq@Mf$ECypF{)uLD-gu?b-ME zU417vSM=y~n}|=8bilW~vr@dn`7MB$xu9abE2WbGm&|Htm~BP{G5Pa2x6N;6J*K-S zHd~4XER+?t;olQo+3M*AAG8^ZL~A@2OpbeUZ1XfeiFkRuaKi(bj4x3I($dp1F9@jO zR6@Agf;k1c_ehW3a&oa2KttEVfR9Q;yE71!-!3b^&8e*OJ#!>!MLB}@tVmVY2!lLj z0}cEvg$cb?EkfJGz+%_oY511S3k0#)4qeO>=;x)0Ov-?}m%-AH-!v(jw2o~H+4i@8|zq;yZa9krR zNj%MDc@v}@t(+=1k{BI}OTy_F7Z(8r@~-jb2w#H(YY{cgrMI!juOuzpG*oy5J@)v< zZ2?&x5llPAI7H#9H%Be9+{%>OAHYi?H(HFMXc(RnMvNk8@e_Hrd-I8=mL*2!PRYf6 z(*3-Wk$=Uq$=2W#HIoC1jy`|(EBXpOIP@o*R=y@Cy&2j+^s(0@h5vUPziIlz^?%9^ zpX|ZRlaf+^N4rK?fP~!@5V*Lt7xOTP>jAIV?5H-KxjD?lF9a1=)sJz86VGZ-wVwYn zFg^A-At&4R1@stcQjHK57shSs*#(Ip%!~_o@7}BP6TTzzGadALVM_gRjhRR+5k?>! zG}ik{fR6XFZI{84g2Ph90m)pS?%(XDzG5ha-1oNNMfkirAz7uY-rL=Q=HnI6Hjteclm7BsNL;wQywcgpw)r6q#eFI( z9x>qRTfEoImmpbY29v%#JsZHh)o3b6SH1e#jE>F_#Mppo_)prmvawM5ABdsA>4rBU zg1)Jl+fl#L!L<W)a zc$2@yiww#pbas*KlE5$ScL}PY599&!na0$s%H69l`Q}*mu4?}WL zeIcGVf@UpPSjc)#u)fao;*c!wsgNh;!f&6oWkFtngZ5eLA&a4re^SPib%A;K7Fxo1 z&<61=coGV|Mx^UEz~K~ZEk@4S{nOLi#HN%Yb2TO9dh?S0jjdPy4l`Zn3q(#28O*$L zof%4H%iS)AEPtg%wx~n{0MSZ;_TUfUoRdj4sNnhMN-r})n-@&9utFSRz3 zF5He~6JDfcj&Cf#wOvI?p>+Wy&E#z5<+I5Xh#Gk&Umk4TUkZ5On|SJ#NG)jn(gx4uGG1Zb(jn9s z^lPfgpS-C_E~}|A5_cFWl>z$VYfB6dU(A0ReV-!Ta9VaySuSASxOKeB7%E?X2$IRd z)`y@sDoi~gHEFjkecgjFT%N7@EHfzdMldngq+~dJaCZ?T%eOO2Kl+ubj%0al1LdB9 zJnY}(pBjSQff7r&K*KM9`|8FtaA>I2v!&u4#t!E0I4UI*nJbi8(4gY5CzWG6#C5 zH-d~i^ew+>HS%D%9`vPW;Et~M7q>c!g>xueKAJgNfWGCpqGFV-`C; zWZz0n9oIK&@Hj~QJz!exEc*QTVK@|AF$3I}s9Xt?wB55xJ*#&0I-g~?%xPquH=UHb z*aI#uBD@;wv(oc)=&Yb|omzFrw;t1he&^kl5ksl7Stl#~p7~P&;^HGS%@GPuSl**t zt-5uylY{p>D~X_O?UCDWMCYk2Tc9d{Aijo=YXF|fSxU)YkdS3H$o>=$*WVPf7<|qF(Ppm|0l-*i9j%2wE20GP3O&b}C() zMjp|2cXbVD6p-sYSYg%TcSQA*7eJyKeDo{J++oVT@dN_?KP1`5Uo>S{XT6e{W78YA zH&WmqGjv!y99)u4R!Ro|CC7bHj~|qOT#by4Yinw#AfG?8R9dpKg2>xxLXsL%A$~vw z0r~5#?d|Fl1pi4}kEwk%=zZ-W(_)U~3cD!^%OS4hYjXewL?8jTv}6Qn*-7m+G@t7U zYe^Hb2(n*G$n82LG7pv;#+91aU1pYi$jQ0?IMwRK3o?!*XJTR!gqk(=_dilJH`E7m z0Tvk<(6_)tGc`88eq%a#l(xuvtjY;qByi-T4AbvLp{>d`AE#qOPH#Q*bj_B>$(~Gf zt_Lqo)($Lbb7Z7GoS~z(5EK*~LF*I^C2;awOCT0O3uWJ|q?aYDL}9to($WT3$w+Uk zpI`S$8QN1pj!C4K#=}V7wT%x{ zQ^lp`^;8f5g~bFO7W~kZ8!A`aFEOoFQ!gZoxsrqW>UNpSTFlLN4&N+b0|WOrWFalR z4kJU+AZaFsYdruAlN$|(o%@?sMd(6Y9a|hR$1GQ8C~uSFj&Du|^UIj?%k&f>+%3Uj zA&cEz19N`IF@SPHeUVo7)kZuJDJz}+B)8rgUWTd!iO_HA@Zt{(@)zhLNz2(?_pYLTL*OA-F+1a7a!z~x*G#N>uYBjN!BSU3jhTni=lkXkGd+K&n>bWmMLp!^yLpt%T5d1 zs-x3;&TT`2WBL|DSIATLdk|pFY3~YdE^osgk6?!7NE_ z@)tvR(`0wcWOqeUNhRkk$(YTV_$M55@lOVB|9(KmQHjtn8Kcq2vSPhk_d^vgC{mWP zp3fS#OH2ZERC6so{OEYwcxMylUG%v~&dYD)uc}jn3H9x9?(oYgK0ODK2--I{+Mi^7 zM`%$|3rjI~`5!z*(2ISZe5KU%>LF)e#eEw}J0>^ksD~x5e@To@BqalWVPXXB3m=w* z`{%(|5HRixS_L|WcWHc!&VQM6bV)Ha8fmL@GozVzSf&%CmB6tKBAErGMA0~8qCIyXVOsEhDTtrtn zK3$HLzp4-}f3*#;)F?LW)UI7>Q=n`M{jVSV7bow3@V3GWvM4F+45Cyzso$$O$llb0 zD3=h536A$xoNYcAhF?gdr&XqiXicJ_pji%bH7>#NF@X)~k3sUnn{VzW*)*0~dc5NB zpCPo7oD|KV{RbuO7dJq)RsKnReaT7!k5{Fu^D^rx!|;*2u8DSOM<-g; zvzdY^?hUH;Jm8+f8fL0HMG~{%o38}tiW(7J*P!08ZtEGPcytKHA ziCYPr*Pu!T)ekPSo(|yA_6IL<`3@+AQ`^jd>AHUp#`pAgL@xYDnNwBi3I_+@NVsQS z=M~E6eENY86y#A|H-*Im6;x zhxT*oQzatMr@!n=L1!mAMpLOT>E<_t7lLyT)&rDsx#O5^Y@3_cDWt!>`PzTfY8|2R zntP~oxG)A@nWYQD!cVjP{T$rAMWRf~R}u8ktKSmnp-RvWXhLTvFD;A2cK7J>OW{oz z?K2`Wh6DFoN zC8@s%!YU6perzu+T!$W;*i#wb4Ff~F1L0Jrg5c&CGbI@vmhvgmIF%D#rfz>)e3Wd> z8)GA%t7ALO2kHoUit=;%?_Y~i5Gc}Gyne$LH*HuT8WBsm)cUUc2M}RG!KpfCM-;J_ zlsllq@Y`m{4<56Q6=@t`EBq!{{r!n?!2^#=$AxCbsisN<$z-M0GJ-(P7N zTqJ%C3VEr$9ogZq`CDp_oxe;=%o!vMF!3rXfM^VG$=BEdEraAlgPW4)Fwel;+GCUS z6kbkt?sQ3Ms|2hU!cYvhixag5Ufr2suK~TRSId|xWO+8cq%x*534E2rRHpJQoKl7{EMPBB=tqFR{fMpE+5TdG z-&@9egRn|^GHZhN?(|(_J>&~W#X4O|IQ=Y{^6b{|NIWga>gnAmKh=0r3VrtGe*yOf BGNS+h diff --git a/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-11-darwin.png b/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-11-darwin.png deleted file mode 100644 index 12996f4e5b8bab65c7aacfaa80d68d165a78a8d4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2120 zcmbVNcT`hp77rpSD0mp6ltFA!NiUNC4vT4L=7xW3?xVp zm`Di;m`Dn%K#&0uB_q8`(b*sZ0g+*dNJ;i(&it`^&iu9Kyz}n&z5BcO{=VP(2q@U<;bGdZYbs!@jRBh>F6CTHWHu_<={ByVGK{Kmemr};U3^tVH z63N&%`QkudF_)!MlV=CLCvQ4PTGV3Gi3 z`6U1jN=b782!TQ?dI68EBW9}q@WoEcQl-lM3zaB;M9rj9K*0K^E@a9}w`#q&HmEoK z%s)mrKmJtqu=3l5BH7U6C~@8{AmlkMVdzqPv(ECN=JBTpnbCFSdvc`rqdM&beNLi_ zLS3Tb^{e5&d)Ggfb1neZ=e0NhR^fHVWF*J1 z1NZF52T_KXph6OfEV{80NtkRLdV-k1uGSxQHQDIv+d+cd>}Tu*uDkNYTinO#=^8d0 z^{LyAO#N9Dtm7#NfCkj{b{@R-*bYBz28X*+6PLrYuP=-;lh1I+1X0lawTaMlC+7j% z>H0k5#WV7%8E*?T{`emMRvEw|$Lw~Rt)l*sP|1xMo?jg)s^MPa#p3a+!$HsuZih6E zFviE2dfS>?6Pr1lDW9;guy^ohe$mq9Y=;}aRh}YF)!f;+H%6)0;?!+2uZ|D@eQ6Ud zh;-!f`6tC&a%)<-vN9_>doq(bfVJL>-(03Y%c{^DpabV=#m~V+o%aupd|Ua12@EuE zxADJtv4RG@#XWoIr?RpT@wXYYSGiL#1_Ko)u-G3Z*xARLMnnvkuuV>_FYmIB<} z?>+9T39m;NM=rk2Fr=I!toy*Dy8W?O7GF@|K$;hRuM0tGN{ptG$;nb6$xQZBbbTVv zL!P{dVTdeXu)*m!1>kIqg~^MW3dDUh^&}iFBm{|ud7&)*&=lX58F5`Lc0BRdwtK?J z{2;inI91|e)Or6+Y-z!TY=0>?)ws=fPh!u*%W8mXE_}{yrE20QVz|deyb<98+ z8egWXoEzs^1^Yy-5=lpC#$O(m(^3&jTOSbI8Q@wBw7J1e)zP*bpVy+vaD;+I^e~;q zZ{RVEe8;Dj7G?sVGUf^j3Z${cL(vbJ;wn+oMcI6ktfE3YKJja))f>qO=Tm5SF_2Md zJvj^)vIpWZVrPkx3&$#}ru@;;iYpj-vYK@o09YHWfvWnKLE!mKBb=(_u7Xu!&FJ2K zK(w5i*CI%&0v3sz^LYuTitFB?_FL@&Ro66dNV3-;zh0Ld{2A6u8xMd8;AzlgE|c^)YZ&*$yedl za>KTRH8ZZYfa$uLU{qaO;-wPrMns%969N0=S@*WX zz-B#9Jx_Z2U+?pg)q^F-u7*-_uFAogFaxy+x3(m&wkb?B5e2!3u7-^@cs*B522({- hPhA`H@{3wch5AT}4`qX|Nd;^`D0go+uFK{0{{V&=!P5W$ diff --git a/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-11-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-11-linux.png deleted file mode 100644 index f523146348832886dac36198939a7e298a27e877..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2032 zcmaJ?cU03?8xEj?XizF!KwHGYP^v-*0nreFh_WP%0D{&)7$GWU7^YeTL7;$yA*2R^ z%mf*UiZZlPlo1dENZ3eZ1WGFqMkMrx@ARC{bH4Na^Sk#x_j$*?@9%x?J$qX#sH~bS z1OkDgtx=8;h-598qh+>%Z#$iN5)2Z-j#fwrgRMRdfk>C3QD>aO^X7(#=P}C~Eq`~y zC%^OsZZ~;CKd5r;+)rvUHp0{QvDV~vl!z8k?O(3=!K!r+(>bHVtdu)hb1z7>o1o;G z%Q1HmVe&pm`@4V7IbJ2(%nXvlS!i7n4F9NZE;sm_k~{q5_@ zjTD}+;TTA#$^O-q{ba+SC=aTJnw;)Q1BIkWu}d1Q=%6lqdhF3Hv$d@_B>)|i zf$sFf8=DI1>1jVowdw)ryu6x9I_x;!+ot_NTUwDe01Fl0+7|BR zP3}&`P_upp{|^&sfE(yD_|+CWz$`e<)6R$pk%B;COCv{OR@AWoY(goB2bE-`m{RC~ z2adf@%Ibr~eM{z~%jGVP#as3C^c3;?UK~L0Q2u-v26N%@aIKx4sUax9 zKYyzytkV2@O%%ewxFl@3zC1T~dE%yBbj~k?0q&Er5DbRk?C98i-**cL%h5(r=cb;O z(cPbxzIYMgI60|*i8d4=IDCwFol^sn7!{%uRJnC^b?7WN^vtuhxS5%mg52#8$bQY) z@PJ~n-c4KIPD+y7-4aDEi)Ezm_9f3hV3!qNDWjXqEt{FSbFqO@xAw@ygkh<@2Ld^5 zDieqFKNW@TY>%*fHTo`_mw=@b@OaK(g`Ob?h5~jszOHOv6>*AnB1ihtw5$r!H-qJw z^i(V^o?IvO9W{i(${QPF2LDdc)xa*aVilD{C>&04Z6(95AYDtx4*pk^*M;N@+^XPs z7BR+VV`ln2@Q!x0u}KolMp=30=jXzR4be<~7HMpCvQXY4{pZyM!Tj|(MW*L-`S+&a z4o`Hj^vp6dsqOvd2~(ZWZFjKsBxYhFSw~CDqB!><#u;l88aY24_TWc^MSLn}hO6AS z_?ZO@`P}Yx)y)|djKamUm`n_{D>gC7%jxoEYHn`sA1V1}5zhSH`o}wz*#WO^2hR1^ z!_?$yX;-2OBi7;;_rV%d@S32~u75>(ZOpEA){6Yi(uRjG<(tQx0R^tsv%%qtWVhY< z#J)Md%aHqY9!6R#EjEl1MGnx7Km+F^vQBq$k8qU^@CT-!eQ>3r`iFe@f{SMz=etZj z`F-$}#cu65q?EtkbDBWV=1**_xP4pF(9o!~veFLL*ih=y`xV(n*8k9)q^uPsY?)^vAg&iIy961(!?!A=;aTjt(jd-OZIOfp$%dcgdyxPf=O9kShG2-D?P zW!dX{Re89GLeJ*s=eKrrU@$#C8Xq?hg#KzwTh_5uEah3u#gEB*VNTA@)UmO#Bc53l z3S-x)m73}rRX8ZdN{rGnQMQfE?tOgW;p0e8U@sPzSc&n5u5*q!9=|mr^vfryqy?pb zIj*5Y2WaZpx7Gb!}Gl7a${)z#Ii6dB;|i1jn^p<-9kcWa5IEWzs=t$NyRGP8UU`D%RL<6qk2 z;$mBWDA@M-Hw^MWdUsg-2pOowiIv#0X6?@!(?l=r3bczUdacELb8=wLa!p^E^aD$#;1>)(X!jF2lk^StXLiU#X8-7 zWq_P6$%fg%vopzRe6fr)J-8q0>aI0sWT*}A%>h6x8hrt+`SAFY$dP5MT|1%iifSr} zI3uv*jU>}*Iajr{w`wxhiPX#koy&@{P@P#))mu;lh^a$URVIb}13yjqh^aH)>L#V~ z2|s#adqnQ2_<7#1qu1uR-&=RoSk`!t`CISTo6ku0XrsU%&3lxiodGxy^jTXJ1L=MH EABc#Qn*aa+ diff --git a/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-21-darwin.png b/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-21-darwin.png deleted file mode 100644 index 6b1e058c6a180a507de7200fcc4201af4846dd02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3840 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 Q2T*_@M&`FGZ@E7EFC+^@*Z=?k diff --git a/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-21-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/font-slider-21-linux.png deleted file mode 100644 index 502e60cb1f881888b925ad95c616672b4d35c7e0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3708 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 W>W27c{KhR9p9^YibscYbJMq6pnGXm6 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/window-12px-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab.spec.ts/window-12px-linux.png deleted file mode 100644 index 7d9400b0bd80a5dfb5e64b59dccd06d22a302f5b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66194 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

D3JMAf72^*d&f)gQEjZxUa9i8j1LiIj^Hh^I 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≧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 E0jO%<{{R30 diff --git a/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/message-layout-panel-bubble-linux.png b/playwright/snapshots/settings/appearance-user-settings-tab/appearance-user-settings-tab.spec.ts/message-layout-panel-bubble-linux.png deleted file mode 100644 index 3f39a3b01d077335d220d9cc96ddc43f1a474c6b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 29016 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 diff --git a/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-padding-modern-layout-linux.png b/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-padding-modern-layout-linux.png deleted file mode 100644 index ceddab3312b791899cee351506175543cb744ba9..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 52562 zcmdSBby$?q_b)n>AdN`3C@2jINK1=?Gy~Eg-QA%`NlQzEba!`(ba(gA-P}EX&$;Kh z_niCObN~BYo@bo#otgLD@7imx_4$0(+7l@ENfHa46deMAU`f3fQ-DB_G$9bgA+$%} zh}kpJJ@ABJrywZ;DH8ophKjz zy5lK6XG~7%?;Mk2sRdSc`QeTQ&SCE1=Ur27t?21GyTens=HBV=BkK4Tsd{?bVx|ow z$L5-0$LM@^8;P4y)4T0`*c`&R$hdg$zli73dAyKk@W1p}l1P?+ubw?--~P{wpSb@; z4~45Kb0)?rd%xymT^_6Y_`cDWDn54_;!S#HAwO8oHFIw6Hz6-0-#<{6C-VH?z2v=# zr$%clH)mrMAmZC3Z;g0J60`ZLVW#%_qvCh$Bk{2t3Y|^kyFR`De4Hc3=$C!cyd8;9 z=#2MmqDW(Cd0A--U(j`$Lv_~AP6;vaH|WooyIm6#g^1$>9V=GP&TDrm>RGqdXmF>1 zMk<8Icv8iOl_8MGwJ%_wky9)!Z~QQnnbXzNYp}vwUlZ(V679C$>yla95ai0iHiPXL z&-IXK@;z$ns;e8;%l~o2*6~`Z4jEyJ>jbxIkY6d+)zypC&yvblgzoicWBBz?$$9MV zpH%JgdXI$V6ki;K(uI&IJE#u&=1aYrD!q`C(n}LB{B^#Cw}59^^hv_xVzAK7dU-@S zV{CnI{VPJ_vtR|Na)>`ovebyfZCLr`cB70$uG!(-0-9@ii2M%RZ0VblpZ4|pG_PN; z9cOC`mzGs@#OW5dPi#!PkFUv@BYsM*^(Gf6+L}^@`diHsqG6pzzbO*6d7S?D?-vgH zJ>r0t^XP{;ezVpv=fqg;ZC6ODD<`8gDR;rhnbNv5vB)vZJT~;X?%8F(ME*f+;H>r0 zl0(M0!w76{z2eh}~9YwGXcI$*~ZJy(9~ zIrvreO~ChLJ+kX?G@0(jhNK^hT>I~mze1hRF@j1gE`*~kmUV>*EF1_S~#w@QM>N$R!Ia+cmd1++TvyKvb(-Da!0@8Kdx!5!9UoZjQp= zZ1XmX-dJG};@oRq*=;Kqr*v70?IWEvufK%#4SYnSFun9BKaeHPzIADBd-0NiL1Frw zU;gD&)>|nNVBX(B`F2Q^vj!X_i0O|5TjgKGXb2smO{A+9lNMr=&FheuP!nv>8#-;A~ zO@6wcV5>Z+Ty642QH34<;kg<7jxCYuYuJY`HhuAYR9RVcmxn%&!GK6R7kV$3 zmPHFb-@W$3^u*Zn@PI%91L==;%&gkl+7OGe+)-?O5t|?GQLk}`0}2zkQ(aCBU89k_ z-7fa^2j)<=#>-K$DS3nSkGhAe7xQ!E+bNMAor+8M33rgc4S0~gLKiAh&EuMw>vox{ zyP*bN%(iwWn4{KyFGWSEduEjoo)j6BMQNF%)!+NR9PW;+`QGP+Hme&J(H2;+$-*+{ zJO$HhkLbxz2XY9+h*hcK@^Esx8E>K$=M2V^R|p%Jx6kOPxQ4FsN6g{EjaRTs-luVx zkyE$-o79NEPl^m6Y`4S*silZ zBmKfbqEe)a&c~I@9b^(+J;(U9_eqZg1Li)zoJA&3PO@>csPDZA)C`o;3 zX~|pn08^ZA5%QewK9gMqwlhBTngeszk*Xuij9YIi;Vwru)c%aO(16N7VD>2dcH38hz1*EEErs6&9dbBBW(A#cy6PPj zdcv)D$rs0Gh4AegU)x}_z)Xc@2uo7?(%$@Bs$*e6ff8`)w;tD+kW{zo_v=;30(Gl@ zi<`P~N3+jZP$A=a%A!7xUi|s8H-p`4fsOq_h>thsmf&(^_8F(iWFAkSv`ncFDyL41piK zNnq+4~&rz9B7BpIybGFJP-Z>r@wfHqR_0Eh8rRAlqcc?hg#bGZJ{p{MWx1NwfFfi=M zgOyiLxjOCG11 zWqDyTvObrd{6z{XAUjV|z+Pc8N?KZKQ&L&3yzn6|*%Jr$Fy~E|oDA_UC@?plZ9>Y* z%8Fxa`jW0VI`xn$gSi;ulohTz-G> zg<6hQ>Dlx;j4_FaaL&)qr^+12Ea&S&iklJ@PE3@L zrGrVWOhKHmuD5RIblu>~U~9&jtLWWD@s(gwP7~gcY-V$ zb>BjTJ#+Tt@I@DQ{Zl5)TUI%|sCLEOt}}RLNb6VHG8vzJKm;k5_UP0l#LN0dEzJLS zSn$RE3XSG`Qf7WVleRY1?NxX2;l)M!gvIR9s%*Zll~ve*QGZJh-T?$6EhBSuQ{0@Y zy}0n!^BDpL5p!!2pA(zy8r$umN5uz^^5!rJYdPwHq-O6FFSY!WdIf{4tE-i;#mRIT zn98NcylcUO9qsMiUCHvG1H&Q(zIrH#OIt3Rqcddknj%V7nlc|+8w{Ft_O2}$r22uo zmtI%P)Yz}P5{TvXW`}V5H7pQ~GaRv%!g041^oWs@h*i5iPn&xM79VtYm#(Z@?@2b0 z_<$-@IPdKrAGRb{{-}XJMUbo|%@FI&ne$O3i_EIL%C_qk@toGG9ZH@a|Cev2P0HD= z4PVU;FA(+y|4c$*Ia$OfCuS0bkzjBE$=aK&TCH7sH(~;~A^;&yr6L%sYB#I*G-+3$ z1IuHD4$su_(lv1_8K|o`VtdY(AOT0GMQzS=N}7zcT8?#47mKY1>(H?;O ztbE-bm39K~%N(0e*d!v^lX8t2&wDi21t_GSPUkUs8o16G3X~dD9e8g@)JdY^heQHJ%+O&wVDIu5GuosW*7#1l{~VS?s|N zcO(G$-;&3w(kzP*g!*rLJ=`ole3t3a^A;oVy?l zKenaXq`A}bn<&H66$Wdl2zm#2N_c#awa_XJde9FsDkFVOiZtOSG_2$Ce1TGpB(isg z&)P$xW}khC4gd2cV0R7y_%y@(eOk@;50knUniT!NYG}(8ahaGHE=nTvC~-vJd%Ef7 z77qKDcx=$%z2Jng*V4Lr+#a|{zl572H`en3A+#%{qx0`1b*#{xR;)Cgs8}}ju}VKEFvZ2>gsw&by`(tYUJLSptbo5EM_q=Spq`BW!Gcoxj|=0t;Scve*R^- zd{Ep^TG}5ss`#VUz|)9I0826mXK@Mr-8kQrFti;k@{aL8gw0sSj_Q z2ifAYD@oygZ{9zqC<89NyvI~<=gc>-hj&ra9fOzb{JIX+l&d0=pX(n3R;ax7@`6CL zwkf^>`{(l}5{-v7I))1Uey@GvbV_MC=J^WO`xCwl+24wbL*ktkCj z{b%eSKhmLnlN%TQj|kFO;Os{8?~RD>arXaS;7JAixBL9xJ=B-S>m571DtR^4{G4*~ z(_BZtU2ZrLAD_+FvdWHdmZjL=AGXwPtyrdgpuv8HTSyJQ#y!nwCM zJT)c)P%*DZ$O4uKGq^8^tp^p3$Oi2qL<#rgfE_nC0 zDgUy0NqkBW#>PVNNo2pBf6a(!X{8kgKXT9Nj5lyl&rsJy+x@9!z8}Rxy>duxqGJph zL>)Q~{J6NhPkZO{>;R>5*N* zl&YA;OPcVg9(H{WzB!Yr*xE^}EYM)_PsIgN$0wy56_uDALxap)5(qjvy3N(+CzL`1 z?c=|{s6zAoK3AGjvkFn2!FUlNmWxv2SZ;hTkrC9?rh7aR{R?)@LBz>WDf|WTZn$;V zXtJdMTmam&j*(eLX}`iZ>VUc#TW)3wUld>GxOfz3tY3{MElP3-S?j=ripSNMz3S&U zKoFH)K1FQ!#pM^B`N9?iuAR!~5N}C+ZXi;iLMms^EbwJFR!tQ+%F6BJCQGps$tEU= z!>G|ryJ4;E(sS=?QR1Z^;c!EzW@d7dXq~u;3RjCl1En7U_%v1w3rMIw*dcdSCI49vgz!rzDdrA6ClAfrg%;?_gzWV{6olzO?i zJV&t`!NGL0Z56OUprm|lx5-hj#@^wb5bjG;T_bvGI#*PSA^srtg8d((4Ynz*Pbs?t;6n0n83RoK$;bmUm~Wss`92+w0f9@$s*u zr9Wg%jEy04nvHqa*7BJ0jeTouWG*OR(zP-Qx*@@llaoV>50rL^?ghj%WL{%gHJgin zj*Mn~!(vY6qiCh6%FCB8#k8~p^PuGlbmTiTOzQ`;k0>oe#5xyJwKS)uXVN`2C8uVl z-lc_`F)#LXJ_hcWuIuBPqnuA?`F!zvzMUw1X0Ol4mv>gaudOAJR>NjD?t=ZjF^w0- z@GDKn#cmu6duRQo%e?EpuR z>q@r_#iVc&rlD?5g;Y&U@csp?0x#m!IrH!PpHHkv&f-i}RE+o61EbWP7)VHT3@t;` z>2ZwZ&=8+~gLLy&MqItbkdiGzj_&R0`A&@n@vd;Ykk8K&AUB;5)0M~LpPyga-haeR zM6`a9S>bZ~7N^s84_eUC^LNl+qv+1Dmba3^`sUNG@Dz$nQncs_l z-)VUY9zK7p$WM}e{3c{_uRgb=x?D7$uzzT3o&dcT(OJR2j)%j3j>^!mt!su9YiDv? zEe0N>e#3*5f|6Xp@wJWNAAdVZC)D3swPAIXmC>_rC=`=LXto;qKVjm>V}^!SmOkh( zt)ZhJ-p#a5bdl~CvD8Gy6xqJ$>6^o3_g|$(LuBgfUtXER1(6cy0-gJJ{yO>=A?fMQ zz9V04yH~iFyCag06{8*)$}kXk?UstcnPQd>CBfpKd&}=#~o&J~CEw5q)DHS>0e!NAB+*>PhgFx8rhVRt2^zBr%>V%G_e{4=+%-N8VHtXH~m8X zh+$V#7d5BlylF}L(`rHF-HjtyQ3Z!@M0}}JYjV&C2?+^y2uG9C)@)Iv|MG`w%_`yr zt=slcE50hWsGs8c`06S8Q$m9FJn8hjSCkH`FVGOt(SwviS*eV!*hih_ieJ1~)!m>4 z+UScset71R3Ids{qgK2TU21YT<)IBcMqGor3=Ol4_s5ah{a19%%#gemxuSoRp0?k1 zdKEppyZ1mtPt`|#KwtmDq2~J?qgV20(9M!|Rbwwh%B`^*W@8rDS%|ozt)ZTt0*&s- z)3CaupMSoP;bOdzVd(`ouH~8 z=JYM@GW=~S!dgfkC1bAp@o=O54+WjB=#9Mi+8uUW>LtZrlvER#u&EGn!-mt}Hn+SF z`_7VqBsZ^hvgq~?pQXoQ{GZj9BfkHlFzUZ5y!-#rxXSaey>s{h_-{+s>mfjY`4k;Z zMEPG9J#~-x1Hs3~kNXwZ(l&>gmDLb)%pds}QD|i3gtj>q4aHYnnc@-Lc`-Ui+Q?O6 zHo$*PT7Cy5W1#yY*1Dj`y{sV*go8CuWkQ6R60)%`D;IBK8GTR2@D;bE(||i=bgJA- zIo0RIJ8bW<=ronq!J4*u1uuGWeEZh+?B&xRdDuR^x+CJsMI|{kd7{*Cpkwm%>2dk^ ziJugaG7paznJ75Tmp8ZOXSeXrePY=pgX8Lm(!=w%O`QMuaC$6Sip)Ly{eKJL{|hg8 zGE;3ug-s=RJW>h&@=Cn214PVEVQoEwS`fikay8s*jhGsuk|tb&`S_b}Gplr-+O}qP zwbRFt8y1bX&|K%nM)h=nGv7<|%jddkAwOg_?Udvq+&9~U`wIob4H!XRhki6y@ z96HCU^jS7;?(VJOjOPJbLQPGcpaPI@UnV)|mvwc$ccGo4hB=tWTqFZ5cgMD!PW0jE z>^c809;gvdS`IOaO}9L*6FH%vh3>G#2|>XzK!wRczk_~f$i39jYpc%(^S3piWD^02VU`lN;i{`J9iD>r_ZV^&NuE<{gHgu@G*j{1YpwyP7OQ`6PkD-2=*Q%poe zpCuT~ztzWoX=`}OXacIa2g4U#`4dUZYflU=-4#L>_WSqqXjfjRoo~wdDy@q` zK*?ln9m)K=yf^>kwb6h=3_db~u5J?0Y@ayo&nZ(n@e5K4xSop4RtXXhc|p$iW}!5n zWKPz>`@mof>z#cmQ%$i#Srvs9r}pmW+eTq7`k*N zZpx5xr+GEsADV0im6UwCyoOnYM@D8S(9y8t6*utW3hucN7au@&r^}&c?t1#)@dnJE zJ-faD{F9Yfcu(b|%aYA%cogZVKF>pNjgq38yHKgl) zvsc}FccZVzW^&y9zBc|F0@8K+V6lMUugg*`_FyU@Y=G5zQ@X>bvge$3#$Gj?46r2% zxDk3>pGt%!3xtP<2ekU2u8w4SiH&>h&$%?*o$F{c*yDNJoOZT+MY6e>un49UkXUce zQt}{}ZHgoQlzfZPzCaRcw>gj|o3aoPfYzNR>d*eANA3&p<2RsF;6J?p0=)_`Zh%fy zHsAYAYI|W>%vJ~&YY8AgQ1!4G{wDI+J-XPRm%KUO8%`DWfV5;3FiHQqeT9g4I}BEl zhHTx}i^T_An^K$fjeLHO4O!@7rHj|?4P3sQn(hNr+r$L2ESZE*@gPF|g$5p8SPHin zB{~KMo`62@&N!<)W7m#`5wD_L|yS z-Gk)D%bSB{JX~T3|JA!D`#*Z%=&LY`#U_C#Po7wx?I=4tJL^2$6GPsm2sTC=9G{#h z-%REaz^!&$;Y#rBn~(hf)J1PoR(i3rHaQA8UfR#)WTS0hfDoYdsd6J6QXw@Yzp6A@ z?GT>%%iB|*yy$2G4Gj$lNa)Q}Y`=BdFUYwbOk{b*ZGPEiD-`PY>DoH&QysL!hkjP*SI*OlClaV zIx7gnX)$nZNK?zY7Yl4RoA*D4Z~@D#yzqFe|Ysom)YV(0m8|wSZs4`YJ8)o zhf9`GXS=+t$?mYDL>>?*9Lthqz1oFkf3QHo#l^+2u5^8|MhGq4`w=AL-lrD=A^>oW z>d#sYm)t7FpF_Z0=4w~~=qG2(hII`JJzyRXE&xw{?RviTH4vYkMo36IGqJ9g zLnWACXHvfqAE;(z&7P8JT90V>`#sM*7-2pcJ_Fk@o1-IQmM%)GqkXfnb%=IxO{V9`C@Sb zl*T=y0b<9F+8%A9_pq3$$o;@0bCSuT6%g0l+tb_Ib$#ZwveFqu%xU_3qc1)rB!L?O znJ83;ZeNREj0c=Fc;318eBrn~K6zj>9jiBoX|0 zAr{*Y2T2$jpq$WAzN~XsHgF4h@O<7wmE$DvkZK?+&m@-rr^fbl4<;4iBegnAk_e>tN(mc$deot z&Za6%UPE-Y!qZ4$1Y{Yd|B{^3N;He>@>DRng0A|)28DBjft&AMRfa!I(@S0+Z(~qf zZaGC&v(CP?Ab!}|*0F0NB*FT8j;Ak)k8C_&9Y)Yyt=RmvxmoDG$r-P?_(t?9&XOv{ z@p3zxYB*gS!+fsdv3ixcZ&)$T{YCSG@?}#foyBZb=gzoLYxg8-z2iaGFHSREV8&d< z=GLWFtB(s%{Yo52lb|5DU!KoZ#$Wprs&y{*1<ux@?hx_9&z#D=pcojU zwm8_Po&8A{7E@?#w&urUXK3ag;3vpV3TvPP6$$!yx${R3=?sT2Z%P-s`H6){T-@|3 zVoLWX@j0^|v|l{S@In&C9jbTI)@b&m@Vc+1)Y6i*B0D{|3^X0j%jM@t0;o+~$4b31 zPc)SS$jOc2ruS@E8$q$OZrifBKh_y;zHDriB(afJwV&O{@ZQ}Ne6B>N|MYz6`V0o@ zXHY44$vq(0SBj`H{L6+R_~av%`DfuLtAjmZJc#&=A65MxwHmI;#nrx5b_h641aQl2 z;{Jy}4&}2q&ylsgP8^i|;YgeH)q>W0<$>^73^)&X|9U~|(tX+I4gBN*0na;r!^Hz| zTtvF=-;4kELy)ILL>aOvo>Qgz{=ERkRcAnp1%WD+S2opqbJ!ln;BedK8x%~4(Ky%8 zsGfIsWuO;)B0M>zWVl<=3H3~=a%8w^l8X z>~?$k@Y*$kZTlIbj-jC+h@wx+jRu81g%KcdWy)@&uhUEL0TZAvWs3BX-Dx4Eol6i1 z$(RY#iRMo{1&xDbQ>GZ<*9a!LIT2iprm3>>3*J1b^VHh7`W*}SNIE^JAr6-*GZtu7 zl0r&c#~+5u3_e~~U33PM45MLVivxWzJ;Nxirbg98<7#m(+GD<|5QmUe>zlVXbq7^Y z@sJ_-1ee9!cWesYXD>^TvShF%_;i}|~ExR92~Nt^^Oi$@Tkvw~EQN<*WI_V{u8SnlF8R#w?P;z|pc zPoWMnube(QDrZDMcc z8U+HdP~7>vJ@O+I+UL(P;Vc0l@95BMei`G%H5dZ;#^wI32`DTm?T?;Prn59D z{5rRosd+5?l>!%!#25eZW7ApO@`>@nSDG-nK3;-)y73VIs+!8e7n=HpFJ+F5Z@j(< zZjzq9T^u{>S2b%L(yvHjoauVMdy`cs2>a|~VB*F)Ss4?6+4?&uCpe5=whaU$>!X7p z)p|!PI@#p!nIB_UkE0ovzwj8JPG`5KG$1UjJx4y{aMr5XWWK0S z8&YCEZF_q%C^Xe*M-M;k9-m{LdkN>8nB)Ss#O?lA?G;wdiuhPGpX%zS^7r>g-Qnd`d6}R8Fmv4ifY@_-di}`(im5UKq$JSV!l{~Qt!0ivCaquSnf$u zcTSM(WK+ed+gtZFY6(oL(CtMTA6~tQx;oBGGm0N-*?N<|n{3R~KN7Jdj`Ae?;oc<6 z$NXRC7E=J)(PWheD;Iodo;cSkGGWG31~r9r4v;qds~23!tZ*p53HvOF++ClQnw-!{ zC-Xn9s;Vj}uWqMLaSz5KuH%4{B&jcNg?60}DmJ_rvJ*M>k}6!-_TQ zxf;}+X}PM_xZ6Q9nRvCOeD58V`ym3I%&!2r+DfptEN__Ab;)Hu7f{@E`2@6ilvGu9 zt^J8CaXQfIza!xw21+O(YLXy0J;L0=0f@e6Su?`+wYYs_jEYK6PtQA$cAsTD18JN4 zb2V&da)Vj@@DDvz`@jM=I2*B$Zh_X_*o39pjNVHj=ym9xx)s(pQ1`h$-S#n?jEtJ? zED&~piS24^murD(YRf1^4W$x7fCK~v3X6TInJLq|F3ueUIl1-sAAESP#pg=$lAUg< z<%3OVT5;V9o?YlR{>er^{GyS%MoGsa|b~?~vHE;0lw8i;oAa zQ?Mr4Ueto5)U5IL*GMI{c%fp1*+_T|XW@(70E+IiQ=ZAx%`25;_Q`KF-Ndd%TQ^N= zG4KiEA{umM9&YwgQ$~Gv+Cai<&$cm;6qF{4iUb)M9RWp@^tr{JLc9@$QL#xQ1Cv|_ zFP}$P(L(iHww;ai)o44sO_CS;Q`JVSyncQwJrSy4Hsxy%wuV(fvmggo`0X*wjx`o%mbkmIZv=y)XmJyAl{joz8`ql&E)2J@%W(E z1w;^_nn_AaWAfUgbpaj@=a`l29jDs*DWeCifBvXl%?vDj(${wA%z%-P(r*9F0JKPLa(jv#J&|RjK8f=ujxi4pZ9w_2#)Hy9YO2>8ff>)4y2O`+DOu z+ZwUxAc4ms_urAthsl|Z6}93Q*G_=cDTVs_`u2KJP{63yH)P&ej37h8-Dyce9a0u% zbU|)xYZC!Ifz!~jnNAdB&T$*` zKJ823#wq+BCPN=jIY*A`Y*l8+vGS#HdZH%I(Xy`E_K3RuP|)AbD*4$C8I@Tyw5xFyO*2 z0l~pTszn@k2lMsZhW*!+VUz-GKBy$byynE8Qh4;`_-6*#JqG=?8eM64UFpioK5XbM zG@vk4FNKhDe%>qe0m_+DU>bCgve#o~LA1A<-Z6#ly5Q{CzEJelq=~@_Oa5(~$>*@* zrWq=2_ag$!xf%pv-0;N2VAiHfbR<;lF_N&VtFa3WAIi;yCRl4Y`}iiY#paJH_K{7G z4EK~XH6On|6nO)H)kbv3a-5d8mjiox_JJ;m)ZdVxzt)4-dza#Q{z|1lBalV2ZFzsc z$mtF!4`NEylmS0>ut5@SxYps zAWtq5e;0a~JN)fM3*t$zpvN`Mn>UyshqfIqx1a7yy3FiUR#tY_*yyuc-U2xENOyX~ zARw8f(561lQ^whge`lgFD4^%%>DDmDvSytUFQr38XX+sF7I)0dq>jP%XtsiU1m64i z(qhieP-Yvlg@@q`$=2~s0{Qv645PuOfZ%|4#>N4{N5*{Jrvg-6!6YGFA@g`71itr3 zTEgHvQ&Uq67ulJa?d5^lA8tTm*qSa!bv@e;0T->Qtq1lQ?!EheoQ3(JL(S|`{qARP z-aO5a2>V)GOeGOQ>GLV6jm@ynIO)hZK~{8tGk|~bR1?Q9I9IUSm=9VJ5+Qg%Mlh&- zWHvNZOU)4_J>-DT8PP#$AXK!2n->fu@b$>boMTY^^@Oe+t#+fK?|6@9KjiI{Xnp8j z3Dv#7MNz$h{mR2e8G15U&fkqJ{7zMszN2Gz^74@UnJB;2CRro#u0=l70Zr*qu|3}K zM_quJj{3P3Bch{20LBBv3$akW^4|$bNJzlRinpfojg{Y{-A}X@#*!&K~SG$7-+Q#3=fynxV?FjB{O;NM&kZFX^iyO1o>Vji=GX!*rCjTEvgZqDHwsI8zJo+s|DSg!rF#YXVh}0UVFSSa zGirRJ9Y=`cgTP?I@riE1(TK9P!Hi49rigU&-yD+&murEL>j?OLB zmKQsuA{jL|PfcE9EwcDf+ze+VWZ-jDQ_&iCQ9+5f%tsN zT53GJl84<&U2gOsH%{|@MLaPq)`4ZrMgE3?Zol`uaQA3XkHTr^sUH~I%ZCtRF6m>g z6v?h@451)GW{KTl)o6>?S+bzmQX{_;n=Yt1b|y7?ZbU&Q{|Z#Q45A+Tt+!!S79J&@ zcPVI?=n`L)xSuEU=Q7!y@A5PpT_>QSp@}?r-r0azPdY<*_dih>33>U5tvjGB#Ie(o zwzj6Bp`#1ipE3cy$9PcjOa$I36tcgom>MBD7j>m7P{n zA~&WQquD$&5D2F-HZP9=98>QQlD8FbK>vlP&VBjStsT) zM+WJ_p-Ue01L#c>K;WL8AsO-<Nt3cMHotoi(OsTT*r=NA66N7I~T`D9R*~^3pIB zWE^XkZ}dmm09Ar{!P5=R-Q(`?s5^yWFeovR-2L__8?{Q7^trI!KvabqhRFvlxJfsSJC-qkLK_M z10E@u)T=~Jr}AKtMNKP2hc+oClL8Qcm>dyYqw`UXVAf4~J-WrE0|Vq{RISUE}h`%6ztpq~6g&QbmPpqc1t1 z-}BGU%ok?|3xS$^)vF+Fklv){7gSX}`$z2jZ@(cz-f3u%H#9UXZK-C9kp21dXR6W; zwaR?jyKuHj|6su*{aPVLaFr03SZ?_efG>XMLkKF)es?!u9FJG&TUuKYY)U2BO;*I* zFZSLfv3GWNE63qL-hXWNZo{DFyPtnE%no}Eg_Qiyyh+|p*^~TD68_&9=5C>f zTc3G8C%xIKe$Wh`-G!4kW6W1w(V2VT9B|f61;fKHr#jgj^aZeW;BD`S@~7Q8L~jR} zr@wzTYAB^ZaAy#q-UN=HcC7+;nBJh2156bvgyquA#K0nAX<2lvJ&m(F>$LlBFj-)z zQ2l9@)nX_GpA#ZvV^G~2fIN8WCgyX*oG4HW0=NDuY_?XP{`U43^lHD~ovj8}W|o^h z2O4sT>9{GVe91LjED+xwb-MzOm`g4DrKbrr60??`01C_}_i zZtGj&hT|)-FB5HW>m%YjF7&`K_qXS%ruOz=_CO-ENsut*Wd+U_wX4^SH@1j-n|AM{ zP4^Szhg7-fRmB5=A>tryodE0mHlf~0XweIdJ$J;YVvoCTzN>-RQN^;!yy|J#r3Ma_ zoH|PhZ7B&==wJ|SZmWX0F)Rz=mKa-PErnvH7bTi_wNJ=sA(yI2194b}(9v+wn*Au`E45R*VD1R_YDGHYOFzYfjYyB*=+@qP zGOQUOuc(Do8pG^tX|hi!h@6Juw+(4<)l-* z#+Lb$F>Vh>)dgj>m3!yblAPPTD&bswnTkWjrKzRc=NLopZCj35~nk zHrcjzu#s=FT$?~M$u(iZi3Lj4at7+to?yA*unY|JPX32F<`)!Ix!NCu zdbpjZ>l?oeB@gUe`-9I|5dpTG^b!ZOWW=fGF=hMEX)eKGE}6ALI`{Bm_&8Az&+-bwh68)W3C_%&!tNJ!`m zr3&{>hL8$q$~soPI6xZDhq9XFm;5g5h@{5@#A~uxQxacRmftxX!B?Y*zsR%wQEy68 zVxsl!<>QdMS`Qf4?QOEw8P{vYhhZtGnoMa{W>%W0bxD~ri?JBE*PXljl_!0Cnvlm6J<5e{@HLXDve%$%ZsVEtHx7c8C z*Dlq@()icnG}p5ocrhKwLYQP^WQ`lb+Q0PbQzE{GCbdPaYb0t~W6BnPF$s!&PXUKf za3KWLvjKi5Jvd@54m83C+AP^O>ZO*iKEy(v{Gi@Mo7a@Ut+=$ji~y;Luty4Ypb$TB zvM=z7O5h%@kiv(&I}TYx?>1ZAQbh$-IPoOjO3r=RPoLyHsp}k0vL@;(qQ}QoCRsGu z+|D(~1xSN7`WxkdYFudndMesSNAV%yXD>0Ff4XnyHH!#D6LXiI21-e5&ge}T6{Q*; zjQwQ!@4Wz;agse9zZj+Q1tii=0M`t5#aamSs| zfY9VX*5rt#Ox;j$0dWYK$28B=Emt2*9{N_b_RliB12w1ck+ZnVLaoTL!ycixy~ zA7YvFEgS1>*WtD&6Qiq& zmU#_A@5R&PTBfH-KsU*E;M3>3(?JinM(Bx2nuq)Kw3w8$y(QJv?enuvQN;&QS8C7( zv7JNE8fWmv(W$))i%eclE&$XDcbHO=lHj~cqt+G$-q=n@C)bnWsiqF~0ObSmi43MM z0=**kr_!g}^OC3cfJ;)t>2rB`1Tg$-L$M6)#U@hyLX|>N%Pju8!|DGu&tJd)AG~`f zh1&`NXi(!5h42Nu3%26cIeZiwj0*%c*j$SYFgtOaFgJeJQ#2gPFFIQ#x^F!;f^)9_ zjyTO>W-?|SpQMEp#ht}7LR3q1(t7K5#>@S;YB~Xv{wEfUNT_fT8oLzKWZ8*L!WXXQ zD!b{JvHAFG`O;!}B!Ig^+WoQh2a_AqS6==lUj6*xzY7*$d!25ArTTat3oJtILGV7R zakwGGrsV&93)*sAl8(T({ND>Q?e}-=m(35Jg$=H%44`=bH?|m#6LGzE-?p`n3-uQP zz4L9n^AkYNI}6pT*$jG#7;ui*E6mmIZqC||E}cOIkqA`55U4!f;Fa3gkp4w|^r&rS zh7>>)NzrV-Ueur{UP7wkN~`m8PF$zmxL#5B4`(~$NZqTerFxwo-~~L;Nh5in)o6d7 zRt8!phU=kJ4X;lrcIWGHK;s8v;CRs*LrPKU_!zx~$M_2-CQM0v{ZeShdQY zB;80NsHj-KI~1;1$ji?!udgdFbAOpR4P5sty@ybmN|rX$%@j;>)+t2O>Pk4dO~*x7Bnx>oeMCxTK`d>O4ie`{nBN7=);1 zU?Y^}f_4VFx?ht8+)|+jpeZQ$TS7gVguvBaXNepppy zlqVfFH$s?QboBn?M}H%H*~V*R2oRg&Kx@$b!9!DPAw3kSBQ%!1t8xs$`J-*46xs%} z=cZ!?x^fhHTfFpXn>Rm-cp4*s5=;iRFLq3ou0}l&202UL5ot@euFh$|+00CZh2nBd zvEbeH%4MK4fPLgiyuP|~m!+mKlGlcB!0tu|ChdFLrYl1Rjl`s*>FgAhI&(Ez$hE$QGC64% z=N}?j8X1(|<$e3nNVKbJYQ*h892r^3_3?}Fp^u2{QKudc-UW}hb?M34F6=@# z%?%IcuIA$(??>{z&NmTyC|GE8HR%a&H3?nTt*xswUFongIM~X;5xSN88_PNg`nbj_ z)hBNpGMlUvNfk}?W&Uo(YAg6$pK)IKQ&qqQg~sb-66`0*@JP~f;wo6{J61cpzT~oc zLO5PA-G)|vEJ62r_`qwsCYQB{TJ}2f&zEFPP$~@FnY7BeyLl*eRO5)3Hl3>pVtzfll?4n^BRSkh)oxG70D9EE+YbMB481pFVy1#p{rlr&MIVSN8j6 z(Pmw{HKpYY4J5m7S)Y;&_c+R;X(h2ucE(J8HS2u+LBv?Zpq%&o2DR?gU7Jk7ajl2O z$niDQ~w;TD~t4}BEuWeg< z`xzk5TNjI7P;>JFpy%Z~EqJIepfEiwy~to2jc&xP({Tth+d_mu*wE7$-Ij$(!O!VH zbf`s$;LpSXLn!d)N6+kAcg%zD6kH$>?{4&z!ZIomqJn{e7)fp<2t@UN90(o7g+N*q zF3qFwti^O3Lb2T?L8ps%=HWEM4GsJp78Yx}YdU)z;G~o;1D`_6D%Z1$cKwEY&0GHr z3p-XNhJttE4UEhf=_L(o%V^2K43|0Ly=w^QF&38)SFgter<42w!(j8!|9%@!z;GenU(vuX2>mbb z65)U6?cG96$j>^v*CIDis>!Pi=u^k_nES>jMG3L(1mNZKKl6Om{OEPB!m1PI8twjO zf2+=`dPNV#F*1wA2IpTw;GzR}wfBtLHxXmBDZ1NU$HM#59SM`7Mi+KaNMXo_NyaRO z!rna7+2doT9ZS_h_+UrEh71g15sOTYB*`3%@1%mx)pNy799*;G(PLS4hCSgU|ALwJ z_k+lwzsYpAdWF%lFo^@Qx%uxIO~(8?vXFJPzV^5f_^I9#r2R#|k2?z6Xlzs&#$#72 z6F@a`JG(8YBt0#Pc`*yO(IJ%xl<-FbMP`aW^YB+r1eIyeGspGui&<>jfj#4BP^5)G z!f5{w_TDq9$*pS_X6shB1=to;K)^x~5RfiiMS;+JAP}NbLI>#t0(PWB5Rfh%5;}w) z5EbbiLhrrT5FnIqWk1jJjq{cF*L%kKamLwW>>)|+vhKCkJk8gQc>|UgEvM!0W;PSPJ2Ahs% z#=~2psO}Uwv42FoA66Cg?A2XU()I?2Bner7SD{|QN&0E@TYKX}=r}nswfyTNn`q24 zW7T+0a#B9?jbpqUH#p{Th{A%9(ld`VPFWeFGWm5_)t76d7b;RA=sBJPd!qF7%iti7 zTbC;@6*_JZMsu)|GGn`r6?XOuqhU%Ys@TzzbU`ZZ*3HZZOd zx-eC^;w!-pe%;6_EOYxqq7CC0FBt2+O7P2jnboft19O<9FpD_(4lZQR# zPogzU`kNA-5c%)*gxE{uws7VDv*BrOE8cN2>^$yk$c6uqZ#i!YPM|5e$}dpz?Fe_8 zwK5be62#3DpV^Fq4LdDbQy%W-(`n+gX!*tjs3R!9>td)h5NRYy>GEMNK=dVXZ{H89R0dsQ8(_;dvWr)K-Rh{V~`09lnn2Yl*Po8ja1ye;wf!NdNk27h5 z$yF~e6ZxsvX%zemejO9>^oB6?C44jccV*Z!RkI+x3iw3hbO{_jAT=AGFYWx=z0~bI z`0jDYlZB$c&&|hQt-R%=`Q}gXRZcJ%OX72x9QeEX8Sb#*Ar9)v5@*41n#JzFT)pyu z^MAPgp6(8~(*I-70s1_a|F5GwD6`RVP=1@}&CZdns^(#VT6_!js{b0&fD&F(uf&a! zK39KUxu~$vjRE}hxE+k_TWrE1by;xz#R30*h-?3rS`tkIbUm(4$S{0M|B3R7&kw~xMERHDBs#;1G=w}{-w;3wZdyYiv1(JCcSg}C6DnKSQzR$Nn9bj zFq+jz50@-ax4Zn9PvVknM*3mgzG2lh@cTsJvjw5g-0f*>2dzDIB(9tyG>}$!FG3*` zDWBWOEAK9KDRVw{ntzjed6}taPw`_SeM|T19ACWRY2TFxwUzZnE>++V8qBK;zaHnU zwKHwmxJ#6qjpjPjweO{6ANi<@GDEF8jP4I1fRKMsPfh%JkNc2Q!AP z@(y`yW{uHY(K%Y|gWpN(wUe+yi_~2<=@eJyG7jc)cB`%}d_YJ@sRwn7exDAB;pdeo z5PNL%+pd2QeS@zXk?9_nJ==KJKMG#Ono=frz@u~Iy4gp~4oGIcZ?| zP^L$>3Dr4C&EhTJ8C#;p~@ltT6!`Gc!5>$rWSNpmnmoX)R_4VeKlz*v?MSH zbw;ub+P-fTs(*Z}7WLL-+wQP~iD>QR8V!}WDyFy@J5!7A8Jtb#Wp*Mt>K`GoOx^B+ zNk1S_`;iaA*ERFm7V{*;IAd=viL9Ay{%Uad}nF1Bg%X6;0?Fi%O@5=loic);De-1Bw4! zEN{AlKJ_Jiy!&_o6%;S!ZbD)b5js&Fpz5|DMIfd+ zWcTkk6^W1gbQ~Vwp$L5w`p^e?)P;Q`I`~zUGXfvj*mT9jsobVPjDc^-6b}oET?_~a zz@(<8K0lx?fD@BNWs(2qMkT(lwVD@i2qfQL1ks1_Z~J`Fm2c(7(H?_5?9Un9F7AuOou5_vcZn*XZavX#+Get z?99$~2{%@|0^@0DLG&z0)cEb4Jy%eGU^3Jaa-#TRZRT3XU8d*M(EELl zwo9*$y(eaBF!N%nU=mid?p>wR zEY?L%7wjKdtp#OX%k(t+grNgFqKkyYkvm)eio|y7WVUAVQ&<%$W^1;E3&JE)P&?$l zf=yKnU2KlT#R{2YO}t!7uJgk%ldhPa3|AGj@XMTiB*;Vv-k))XbOQ!2X&-6YTh-q) zM;`Z?N2?_X@;3QU4U?en(f5o7r_x(m^AR3CUnLytnT0&U_DR^jleSI|&sp)>F?YF= zdYiH8m{Nz~wEb-#opIH(xZWV9eeaa-9FUf%e34pKY0Ebf(hv-Y>nX^}NkfKPb0Xq> z&|X{z6^1>W{yz3(-Qj0);&$BwhX)|9jC+?V_zX@7!}Z)wP%|d^okW+K`xpeVCb1G?Wx?lD(SgZ`?@zr z?_LuHK$K#&bQdn@>+0%e5Fu;a{w5~=>rGB>Zt6S5RbGkD|Q|KP{I@9;^OvQ`|}d| z@HR*mDb{bb#|K7=A-DS0WV~FrX1G6o`n2>j^fw4)ITCiJlzujZi|700nGiT37cNr7 zn<(NApE#_NVqC!u-YC*0w=^GmquY{kuj(&=m&*JTF*GDZf8WVmug2JLyC}&wCXYN; zOE&v4SUhhIS>RcnN789}k&kn+dOTbxUveU0uD?EjAu=`9Gy{-YfjcW|Y+`A?IxJ`I zBV#`zUWul-rI6{_WK)>%OWAEYETjWw2NldN+oPqU&Rz7I) zyFU(x#>V)ys#K!+4Q+3&4jqvT0=VVWbS&SsaNfIncW3k$WG+c+gw5IF-?wXZF*Gc* zhl`m0en6cK(}vSK&!)Nh3gx|k7}k9I7Fpuhb!D`|SrNQ`qH?bJ-W5&(0YOy3>N4NX zg0~+wNsx5Ytnv1AoohAZGcNfx;@fgvBNhSpfQSmGS)p@PU}AAEf1c&hsy0Z;WVf)s z1+QA@M3v-SElLPNwQNCjLux}umW$gFoCMgH?k&M!fB(3(f5{*Blgc;VtPf# z*yM?|vr#*=f43jL<$H1zda%p(b%mh0iG}88F!p3}9B5CjbEy%LNxqR;34T>obS#Hb zgXhf5%x)pyzw6CExt$=(^3|5j#AIL8ZYdONlDj0I8=)@)kX0z*Y;dbw61{AK-P1Sw$fiZcu-#j*7!7989=h}_FnYTcB9&QBLkJqHXJ980h zJXo~UUsjgrk@7Od)w(w;Z*^GAis;~sw;x5p%RRKfu4(%D6CTN){B@%EIbXD-V2K2p9Wkf+BRWeF}-V!N+==FAyx zF)?+juEd&OB(3*zb&&(j-Tt-Pf2jT&Z8>KJM*P2>jdHE9u<&3Z&_TD_@-pp0&%G`$ z&Ikyb?`Cdw^_JDZcUgU$pwvZa=A4cOwQjO$Lu1{Y)gGbT-IphyY*xy2cDkfeX|aze zH>J0Nb;pyoR_8yh3f$XuR_OTHP*?q&cc&qbz$CF^7`e+AGjmkZ{>P{sJ(xpR;7{Li zb8}njBcvXWRB60LzQ0N!Q$j{7QAd?17kecB-~r!;ZNb@4Z~3k+!9gdZHP4ZqF=hcK z7}RaE?`v7x3E^Q{E&F0Iy@|MhN@(j^zTaqvp(m@kIZM>a`tP=fc0;A|Ka-Ym+8lvg z!x_ry7v@f;BJZz7tT?GKNpI28vhIJ{Ws!cRbOI29Yln=3@0#}_wG(3dM38kt1XA-h z@FKgw%ZRt_L*X4pjrX@u235Zr0tkczyh`I0Fq+nU=UJyn_Sx6YEgKKCEXe)SMM=4{ z;LZ>XBKt~FvD)#v*}cSN8y^OC5PSa zv+rbV&9~qzf|)^G(aJg56WZEz4qoEY_eoP=O=??>W0nT-glfW;3PzSq9D)&fwIkJi zI+{PdudKJ>!gg*+=$E$%e5b~7YMI)I8?6boS498 zV+0&9Xg8jXoTwaw%;LIvFpB&w^TS@8B3H$1d!(6H_G(#g2pko%N*!uT2YvU-nHHB- z)aQU3q^@E@)w1q{VJ@u9Q2gf)-Ri7R6!1oWoFV9paK)G}9+4hW3}d8AH@hV}t|;U3 zzAP!Nl5gX;+3~Ms?&F;~C(YmAQ>Zl!SNXH!Y(jrg-!g*-rvZRvd9+3pSBFJ3Tn1lx z?D6rL6zcnho?X~YsM=~>PX2v@%LLQ%b(lS8)h}CE=N8htDznP1Gip`Jb-!8Exk~3P z67Nkqn?Nfo05EAxeIOPcH@C&BcUOyT(dtHR!u)|;ZriXM&%($V2JV^MKhUU!?~|!R z<+Jq96&tcpeF00OsSztHd!``mXL$gW*pjLHpH#W-YpMGL6K3&E+c`Qs#3R1rj;h5k|csP8KDCkoFF z;Rx8b>=>tz2G8Z=`XYj7S7yxexN>WtIfGfb!za4=Yb<>=Z4pkd-H0jXI0gomgq52S z!}^D^73ldql$%}tCz8!_KKh*N;V-McTs@gC*}%_1onHlN_3%8$OB9zIec6U;zUy*n zpsH7vdK(rJ^762feyywoY?)BIh2S_;hL@tKy@7^eNK)^o++kNhrYE5*1DSep>85{V z?sOc>A0Uo~7-dhiC80q>2>RkAVK3Vruf+N)^t^hkYr2bU=B`&*wTmntz5*RPirRwgYy;<~kCcvRt@ z1cZi=-;lpfhRt~0y&`;}UiOveu8YljEYjYp_VyKeDPKd`x%UpA!z)m$V;+H&EDu4p zzC10CdX##iWU931h;C!mo2CBj66i zw+X9LWzLchl{~k~7lDkSF8%&`tFfvD(o)|KWlkd zTRBun5ePoA2Q+Q0#qmWaRn;J(-B5D*N1+JLt3L-IL~8opZr}W)F`Ef zl?c$BYs}2Js5Yi-6+a>-Ez(BZYJZ6qR^gUv;&Utk=^mVL#-!2N8D&|e9!S3C(L6`T zrsCo`{dxYtVnO@&kSGqT(a}Da6rBspA1HsMw=0l&`8@@Ksfjzp(Xn0Z-0EX)#iy0Q zt1~ouq086RO01UY+Kj57ivK+B<60;1@kQaFg%U^!`9Ze zx6tk)T5A6WsDjp9eYk}G8D&EPF~>AhL%Uv*7#D;Ll;c`$GOv&@BP3 z(b^pqjP%GhyTN?rn!+>7m0#TcM8OzU0IgBuHK4GxITDHc*>K7Q>^rbVuAB?;0Eu|@ z>Xpvn-!X|b`EYtIGqW$=Y#z5C$8@J_UxH_EZf%Lwx^+xvWGz_M|N6ygt;8;=yV&3G(Hv7Hq?e(|m>*#nz16=mLgsE4BqS$ zf=U9R1rvlpg7^M0MP|F%cilMPWHc}!pnc~N0Kfp|{lpl)4nO;4!|8SehF;GKoukYh zR8NlXD&T|&1m9#Y8>xtRP=+tm0ztf*LyMwUDW-a5ZlaL_%b*^<^&*A4hplqmgKpPf zLk0wq8g4_xtkwu#2Qoc+p!#=L;hP9ahMQ^TI3muxSiyR@$f}a4u{>bDJ76K2O78!; zHXqa*o4CF5atSps{=URuJD%I5#IwSVrC2FoUW@M3eGJZ1OZqu?Zg`XuSU=f+0 z4#-PU*>*z%oN`4o?`D5KI8Ad~YASrwuyL5THa;Q2g=fPyWj6EFd#cqpI56<_Ckz0J zbL4!Jix7NmYJ&zR%x9r-lf7libC&!C6eD>m?|^+1ow+Xubl=y3o8Xj%sdQdRW*3tV z`o+xaYDt(?JU8{>t$+;r#>Q4P)cNt$!725#8Rg@cVSNQqhGB7JKagi) zHd}#q+4{veE2_#)i*2o-AfvB{k2fFqbU&hr9Xv_xvBdq+S}y)n(59rZ{p(`$Q@|^*9?S`! z<1^t#a&a+m8*3__Rv)9#B|ah7hzzy}Cyi{ETaBeKEcMnz<{4LH07;oPfWUDv+tgw7 zoC?aIO+W!0sD@dz8|M6h_WJ6uq|sP6IVS0RonOb+ILBKhs*@C^*%n*&Y_@riDiNBa zJLCa0Mm7KXaBw&@|D$DnEUo{+Yxi1r-zEfwuDRBmv10zU3Ur)0wyvG?Kq_dfhlEg- zwPI*euiQDh%zw@9p9xjpHm~}23y(@+pH_4OA2+0QeJB;c#yv-MV!5W#iKcOeavkwp zQ0NWPO80T{0VE$7&aFAoF{W{e+YeG*IiQLtA9`&};%i3F_Ovwl;p>u~ONvxenoB(? zyf`A_RL5CfF)^a_^8D0P&U?iW-o24CR6Xdea=m}^Y9>1bJQe3szT+JSc(u#(;yM1V zJed>AnNFmzaZBC322$6JaV5^hAL%Vc#dtlxQa+&({^Fto@(K;uUu0&lqblOZ_+;(e4lq#vh%U`u?ybT5CMB$}B4hm@Tk%Br&}O z8Y%TrF^~C9F@;xn8NA{d^U^I!@TR`-#PRn*K`l+d)p>pMb$i;cGPBo&-KmFsh~i0; zfdGHKx>F|B2DMSKvRdOK_Pw1*yxFWIi=>mW?~(K4wKdNjv*}Ner|sWsWJDdhoPdp* zFO2Nq1|_cs<#y9_TX<7HSuQq{=FYi);akOpXyBDxI*_PgbAA025SnJy5X)#aDW(F{ zG)h;=|3nP_`$&AFlMOMi2LPVAaB450Fb)vG1&n#^iVJ!(I;~JXSZP~lCBVn^Ds7(! z;#)#$PJD`d;)U9V%&At*za2mQ)q7PQUkhi_j{X+l{e5lMp?r*4n7HBE&CA8A2%@Z~ zfdUk>8%qI+pAZc2^z*KAsl%$$T)5$-Dc%A5Of?CSz{?+tkBKo!qW|P^Ep1-f6{sij zn8#)^(NlNR>k^GeJP3PH6ObX=0AJ#OsH~q{qMJ}$RoZ?8NTds<6p+h$%f{8Z7r#Gd;MLbn3fX@+DBCm4pA10hrOa%( z<<^+u=IKO5J|mI-VFyAU$hP1bmYuu=JzUoVL1~le75MfCU+=QKOCA@u~kd_q4+fKOj$kwFPtHT6+MDk#H zy|h5>RDGUmBVyMGX+ti3!x%?ZIM1o)mYyzIp|3qKEK4 z+I`r)%*uTAMA_7ei_yG0ztw|vc@xv(KZ{kk-g>v)oD5s-Uu*m-1t=;CN zCC}K6TYKIk>}WZ+pj)?Agz@d!--}^IuM*nNCPfekgy!f?oqX1WnJ6hJ##IL=p6q;s z-+FGOzS4U(wt8z`C+@nMUYS1rnO(Q!_!Z*U!NOBCVLE?TKCoS_qz(8Sq+6V!rb|GH zM)K%s18i@nLyn?LIPhhI5p&1CO?HG*(c;9lK{$X`7X!4Q(fH?>Ltv~(&hvV(m;-k&2Ut(lY2)**3m`zgXJnV-##Q;HNO|-M14|kSuOzZ@KqPmg+JDP;7vS$<$fq2lzwOWowJCG7z9+yAOd?y~dT= zpXg8>*vY437i4|4isuEuJ-@(2yzW8}T3TAMvdCn~GKbu|A1^HJ`Rg2*6HkHM9U#2Z z$P?+AXq2^5$AB=*NTGpMfVzczVzaXr?gul8Jq8*OLsj9VxH6j;wTVUHBIx#%XB5d? zL0zn-I>59fJr8o4BRBP2T!Per(F|;}ckOUZ|5vgXYF&+<)ZN%oEenAxH7^{1X|hUW zlRJ`B?CR=5y;SlA#5l`IjNXCyoHt=}YvWo+Pp_Fv!Y~L}{YbO2KCDG8QB-e$j4+$_ zALa+7vNPbE6ZTc=rZIGm&H_qvZrco~5hoW%O%j%&$2BMDCNGGZ3LR@8UxFqWVeEK& zw1Y*aD=zB5r`wDVUV2w+0sIw;Nn5XBK_;HTYNb}1crQjiJ4!EuKh?wO63JJ&vMhp` zc(l_B*cT^~<%cRs{|;&M)y*mjVq`Z zCu(aTrv*3+#vBmOk&#y4=b`@oT>t^<#d&e*WqSzxd7N)z2d{8~^Y+^-lit4oc!O@5 z;}b}?PHwE#&`t$l`UM0B_r#KnNK+ecc??ss*qekACe(Rr3cxp=4Fz71OdmD|tB<`6 z*=j}@QQbg`qbRfYYOqz)SFd_VIiy?%@Q|v z6C|DK<&`ASvB=~(nR~lV>3##6J4_?|sif1&2jy$qUE!vGIJvv)fK`WBw=5h0m{BKp z5J->?`n62pW>l0vQo+PZYazxDH;Pp`b&BS#U_zDZ9(#6Rn7Egtu(?61jnGKs+~;io z3+$7jff*{X#q3BA7Ci66>3e65IW-uq)^XPh8l4>_l!W=X6^EeP(0lAbMlB|wT>z>qIxFj91_nUp1733XD*B_HtBJtbzLTz-!&5a&9=gmJCT3_Q!g>`btHk z9x;Y;>9H)gR{l!|Gp7!70p*qbWHk0*2Dh$T_|$NJKT6a5WNWKANnmg{yD#qHUYd`3 z#)&tGB9MU`w(P@-1_TqxFL6$NF#oYCADL%TZY#<{!x0;&mE*bh={FgzxFBraj}&w= zk5ZZ=d9(Fe=9WeZ-+!X>eFAEGGO}m~XkU0pPqfBxx9w&VqD?l3A>HnhL_8$5Pvzd( zCcYT2Nn4#PN*#TI75XnV4N9+dW8=R>lL^3t*2aQ6^NVj#OVr?53>2Uruu6{_g_?&?8F;>^Kqms|s-4|g1JjP_dm2w88Av7dQKo%JeE7qNxvM7C}XzF660<>T3FmoHoS z$W?5M@G-)10f{;6kV$f_ zq&yj!%4U%Rh&0WBE*1tNgH|B!=;Y+o3q|;Fii?YHdvR$bYDa)X7`IgvdUvtG$<3*I z(?-XMZ&FHR}h%UF}L%P_f1qALe6EKyqTXtB)s3K$;cyK9=O#B-RA)~6I2Fbv84A67Sy zLiV9$>{PkRsixC)_hW=KiC=<|QNB<47*=Xc!0P9{s4*@p^7Z6H5T1zQpke|lO+WM4 z1Q4?HgTupA)JHGh%@t0#p2A>rO!@iD>0h$Ev*IF?+$NVy4XKUZ6rEqmi<}*X{v3TNR9Q^sdfqbEM10#2rv!@Hwbrs*Q`{6S0~SkKI^( zMkVFc_|(Ko&Yq*aDe^2l{N#uvL0G+VVDZC%Kx(H96?^5k$4lVK#yr$aWsi(+@EfbT zUYc(3@jQ{uJuS)l_cyJ3Nzs9Uf!6(b*=M#bmX`}b0wPvDVF-1Eht8}g?H%9X;^IO} zy^NRLU%3e4nb|H@asaE)8?NF!-`YD+c(vrkF;gOXO3ifu zDBQI~GIEh&*R`*32HAGj*5etT0n0mUT@dH%4|?!nnw~cr^WUPqV%e0#Vs;m^|E17l z7`>{2w(iR{HER1>tOSA+-L^^Lg1Wesd=QGlYJYT^GmkuM8NH~Ty@FK9WfO?T;S^|@ zzZq^vS+;%R19PcgR`l|C=NCj7sBFS`J@YUbj0Aemlx>ip)M{Z zc$L#L6BD4&jg#av!jVa^Y71@2(V(FJDD)9%XgZ9>PF^NTnA! z58v{KP+MQ0UU+yoYPqdn#BAfXO*Akk!t5?r7B#+o?ln&O~jQIoqY4q+s^k6@Fair>F zLqK40@mYG-EGWWr@Lxw<1U#0oitX!`z*YQ{U)qg|+=D-1<)2k(!GM0LMhgNnGY{PR zzVu-fAnE6Dg2XsjjZ1R#7jC;%ZE%;IfKKx_C|ah)k&12o;hN0M%%@ME=9Hpun*g3# zi7Dm!Kg9VLdf-kkBYY1b$;sk5rAJGBSnD5q`PAc*m;2>+dU})oL3ZBgfhhJ$Pe+Z& z3gqMSfNR8!m+~c!b+=e#suA<=HEdS;5$x8cNC$y)UgzXX>CJkn1g)k_L|Q5bm7{GA z_Jk8=bGkMXc;O(5^kB#Vguf3g4h=*d#vU|z0dR{QLiJPuwJ5ToO$`(kg+25w1vTGx zMkXeKom*fj^H>42vay~@YeM<#Y5tSB@Pc6k5ccs)BAuY#0^d+34u{j{N5oJ4{0ng7 zvJAJ0TRS_tG2K2q(7c>V_vMsO*<)Q`1rC*+ym`J13DxH_x-TT84RT0Zw(N|4PK%AT z-q%k1?6!U|`VR%x;EXW*x)aDZ9Ia-w*z~DAoQhz7%PTEy3>G+ZZL}&2@K&$}T?jvV zwywOezw3Yf#+nDt4Uy*8L@2Us-Y~EtS}{(M4`AD$FUz}9h^x1*KJ6aTkg%&(0F^|$ zs5K(8H1GWLBw@4VnJrI=Iq*zSJs@y*aUJo5MXE%j$oto}fOWG*kBIx)DPX9M2Soq^ z7CZO-`%28>cBPgqjD2}%B*{A?bbtP81O1}+hE<^bJt@-ugh%)-=3GQ=*U)pY6%43) zYX|M0W2`DvSJiqFa3?qS{ z6JYm0rxHxPP7WIWJt^Q?fLdv_Da$O5x;r>~<|0Z3bNB8&(vC3NW%9>!y{v=;aG}H&ueX)bS2asn`Zz$}mHQStxcp9Uhgz2sJ6kZ*udCnEW)*ZCiGqVc6-Q>a1 zG+gzDGw1|HIUdXXuG3Jm9hysJy$%j#94@=b?v?DW4JOxh(DoMIqma4-?+HsM?vx0# zO_%24!Ml?n>8ZOtf0Xg#<3*c+&bpy03Vp&OAEh4O1nj%9vFx?tpbLNfRbUDFl+lD< z0O=H<(hRJ+W6zQFjmka+`Mun}J{q(hrM@X{H8ts=vMUSTdQe(tc&9lDArOpu!mFRB zy-~4^+G@&R+TH}L!RLX|Kqdlr=K9>Os0~pQkW|4&vxirE2ts@jKBDc1A`JqyOqt++ zq)$Eo6=6k|H9Q9to8x!SV-0ls%umq2hg5a3i|ny6j30h{m6lOnX*kyTNp+hSTorut$7caO{J zkSLYs7wrA=S-@~~nz!e6wr{O$tn9S->d|ukrC_dm(*T!4q$&`;G4Mi{dz*BqDm;oW zCSN^4(sD8-UD8WTsV!El3#7S!wI(pSCJ3wm966Lb(Zuo&2fD@ZaO(%y*fB_i5D$3q zW{+?gLvwZKp8e`r6WK#t1r`wQTUpuhP?ZjqLQ<&h3h92gUksjx1#da1uNcbGU$tJH zedql-s~z5ao3X=>O}or;bV;vj{7X-Ua}a$C{wLXr9b=V_lO`{=xna+oksZBBRpcz2 zvdo?lar#{e_gz&0kszoRG*|*AryE=SY2FhXQ$@&9uU{M>9EynWT=9~qely^i__Pa0jp|4t4`*919*q(xOfhNoxlO< z!=|%7)roMdHLh}#Y4U+s0v<3(^25QUO09=_o0x<=zMWE!R~2;R7*Y7~Ju-aL%xnY* zL8_!-hHqY<0`=BFm3*U;j&a}d z#D(qxYF;Jck<@R} zRlYfH4Nx>z6myh)w4SsyhCUm-!4fP$4@@n_bWEY!W2D9p>m+~+39ph%V0VOcPySTw zB_Q*kMT=8^n<6Q7gS(czJW_}hfa?GJL>tb&J!{MD&-Okc0iH4o{I@TF7xv?XwjbMP zgSRHZRtG830SvquUk7^GYLm2+&e4r53s1_}0oNjm9Vk&b9kj&jHId_+TneK|+BRC_L1cZR!OimgREkxQ?Cg zlFK)cWSi#cjI>%Gt0mP(lM{3H`UW$$|F5a4f3icv9)&PXwyLW!v9NQ68j;54?qBhto^?^96X$48wgAx!|<1%;J z6(mf1etnH(kVA~SlmHXC(UbZ#OrqG9y1KflBamot4p5}OQ0rBv2hMX*bZa?-nXT%# z>aiw-SgMkvmpk}1<;q^-y1YK;^)`wRkv%ZbD{#hpaTbaPN>2~FkS~i)3

}`{H`- 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 SAZ?0(ASNU&So~4v>;C{w_81oc diff --git a/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-zero-padding-irc-layout-linux.png b/playwright/snapshots/timeline/timeline.spec.ts/hidden-event-line-zero-padding-irc-layout-linux.png deleted file mode 100644 index 5fba124a92979f83b90395b32f99be34f372dea2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 50908 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

8rFCAbxrgIhxk5nr2R@q9vg#c+jsr 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 diff --git a/playwright/snapshots/user-view/user-view.spec.ts/UserView-should-render-the-user-view-as-expected-1-linux.png b/playwright/snapshots/user-view/user-view.spec.ts/UserView-should-render-the-user-view-as-expected-1-linux.png deleted file mode 100644 index 75b64546d63f0fee745a35e411b2e7fa4fe522de..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17497 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 diff --git a/playwright/stale-screenshot-reporter.ts b/playwright/stale-screenshot-reporter.ts new file mode 100644 index 0000000000..3a3d18e28c --- /dev/null +++ b/playwright/stale-screenshot-reporter.ts @@ -0,0 +1,74 @@ +/* +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. +*/ + +/** + * Test reporter which compares the reported screenshots vs those on disk to find stale screenshots + * Only intended to run from within GitHub Actions + */ + +import path from "node:path"; +import { glob } from "glob"; + +import type { Reporter, TestCase } from "@playwright/test/reporter"; + +const snapshotRoot = path.join(__dirname, "snapshots"); + +class StaleScreenshotReporter implements Reporter { + private screenshots = new Set(); + private success = true; + + public onTestEnd(test: TestCase): void { + for (const annotation of test.annotations) { + if (annotation.type === "_screenshot") { + this.screenshots.add(annotation.description); + } + } + } + + private error(msg: string, file: string) { + if (process.env.GITHUB_ACTIONS) { + console.log(`::error file=${file}::${msg}`); + } + console.error(msg, file); + this.success = false; + } + + public async onExit(): Promise { + const screenshotFiles = new Set(await glob(`**/*.png`, { cwd: snapshotRoot })); + for (const screenshot of screenshotFiles) { + if (screenshot.split("-").at(-1) !== "linux.png") { + this.error( + "Found screenshot belonging to different platform, this should not be checked in", + screenshot, + ); + } + } + for (const screenshot of this.screenshots) { + screenshotFiles.delete(screenshot); + } + if (screenshotFiles.size > 0) { + for (const screenshot of screenshotFiles) { + this.error("Stale screenshot file", screenshot); + } + } + + if (!this.success) { + process.exit(1); + } + } +} + +export default StaleScreenshotReporter; diff --git a/yarn.lock b/yarn.lock index b6585e26ac..7aff84f1a0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7418,7 +7418,7 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.45.1: +playwright-core@1.45.1, playwright-core@^1.45.1: version "1.45.1" resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.45.1.tgz#549a2701556b58245cc75263f9fc2795c1158dc1" integrity sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg== From 13e10654b016755ee4b90d62637644a810862eec Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Tue, 16 Jul 2024 07:20:51 +0100 Subject: [PATCH 34/59] [create-pull-request] automated change (#12779) 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 8f04358ade..c46676f0d5 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:f7f460134dcaa841d5cab38d43b3016124e9c341925709db7ffcc018e93b368b"; +const DOCKER_TAG = "develop@sha256:76683a0a17507dd6a724bc6eaab5763fdd7ecdb70d810c5bd94006ce84487edc"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From 5f10ccb5e4e7c6629d21f589afbc5e6885a888f5 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 06:51:03 +0000 Subject: [PATCH 35/59] Update dependency @types/lodash to v4.17.7 (#12747) 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 7aff84f1a0..1d528bf013 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2621,9 +2621,9 @@ integrity sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ== "@types/lodash@^4.14.168": - version "4.17.6" - resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.6.tgz#193ced6a40c8006cfc1ca3f4553444fb38f0e543" - integrity sha512-OpXEVoCKSS3lQqjx9GGGOapBeuW5eUboYHRlHP9urXPX25IKZ6AnP5ZRxtVf63iieUbsHxLn8NQ5Nlftc6yzAA== + version "4.17.7" + resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.7.tgz#2f776bcb53adc9e13b2c0dfd493dfcbd7de43612" + integrity sha512-8wTvZawATi/lsmNu10/j2hk1KEP0IvjubqPE3cu1Xz7xfXXt5oCq3SNUz4fMIP4XGF9Ky+Ue2tBA3hcS7LSBlA== "@types/mapbox__point-geometry@*", "@types/mapbox__point-geometry@^0.1.2": version "0.1.4" From f7a078d250b388b85c76748f02fd4cfdac6c0b6f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 16 Jul 2024 10:03:35 +0100 Subject: [PATCH 36/59] Update right panel base card styling to match Compound (#12768) * Update base card styling to match Compound Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update screenshot Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- package.json | 2 +- playwright/e2e/crypto/crypto.spec.ts | 2 +- playwright/e2e/crypto/event-shields.spec.ts | 2 +- playwright/e2e/read-receipts/index.ts | 2 +- .../e2e/right-panel/right-panel.spec.ts | 6 +- playwright/e2e/threads/threads.spec.ts | 6 +- ...iew-with-a-poll-on-bubble-layout-linux.png | Bin 24660 -> 22386 bytes ...View-with-a-poll-on-group-layout-linux.png | Bin 24607 -> 22315 bytes .../file-panel.spec.ts/empty-linux.png | Bin 10600 -> 9580 bytes .../empty-linux.png | Bin 10153 -> 9062 bytes ...ly-to-the-location-on-ThreadView-linux.png | Bin 18752 -> 18839 bytes .../user-view.spec.ts/user-info-linux.png | Bin 17830 -> 16728 bytes res/css/views/right_panel/_BaseCard.pcss | 59 ++--------------- res/themes/dark/css/_dark.pcss | 2 +- res/themes/legacy-dark/css/_legacy-dark.pcss | 2 +- .../legacy-light/css/_legacy-light.pcss | 2 +- res/themes/light/css/_light.pcss | 2 +- src/components/structures/ThreadPanel.tsx | 2 +- src/components/views/right_panel/BaseCard.tsx | 62 +++++++++++------- src/components/views/right_panel/UserInfo.tsx | 2 +- .../__snapshots__/AppTile-test.tsx.snap | 43 ++++++------ .../__snapshots__/UserInfo-test.tsx.snap | 46 +++++++++---- .../ThirdPartyMemberInfo-test.tsx.snap | 4 +- yarn.lock | 2 +- 24 files changed, 118 insertions(+), 130 deletions(-) diff --git a/package.json b/package.json index e483fb3948..a54fa74797 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "@sentry/browser": "^8.0.0", "@testing-library/react-hooks": "^8.0.1", "@vector-im/compound-design-tokens": "^1.2.0", - "@vector-im/compound-web": "^5.2.3", + "@vector-im/compound-web": "^5.4.0", "@zxcvbn-ts/core": "^3.0.4", "@zxcvbn-ts/language-common": "^3.0.4", "@zxcvbn-ts/language-en": "^3.0.2", diff --git a/playwright/e2e/crypto/crypto.spec.ts b/playwright/e2e/crypto/crypto.spec.ts index 30301270ac..1e1015cd53 100644 --- a/playwright/e2e/crypto/crypto.spec.ts +++ b/playwright/e2e/crypto/crypto.spec.ts @@ -227,7 +227,7 @@ test.describe("Cryptography", function () { await verify(page, bob); // Assert that verified icon is rendered - await page.getByRole("button", { name: "Room members" }).click(); + await page.getByTestId("base-card-back-button").click(); await page.locator(".mx_RightPanelTabs").getByText("Info").click(); await expect(page.locator('.mx_RoomSummaryCard_badges [data-kind="success"]')).toContainText("Encrypted"); diff --git a/playwright/e2e/crypto/event-shields.spec.ts b/playwright/e2e/crypto/event-shields.spec.ts index 0de678c17c..d73002263f 100644 --- a/playwright/e2e/crypto/event-shields.spec.ts +++ b/playwright/e2e/crypto/event-shields.spec.ts @@ -132,7 +132,7 @@ test.describe("Cryptography", function () { // wait for the logout to propagate. Workaround for https://github.com/vector-im/element-web/issues/26263 by repeatedly closing and reopening Bob's user info. async function awaitOneDevice(iterations = 1) { const rightPanel = page.locator(".mx_RightPanel"); - await rightPanel.getByRole("button", { name: "Room members" }).click(); + await rightPanel.getByTestId("base-card-back-button").click(); await rightPanel.getByText("Bob").click(); const sessionCountText = await rightPanel .locator(".mx_UserInfo_devices") diff --git a/playwright/e2e/read-receipts/index.ts b/playwright/e2e/read-receipts/index.ts index 484df2251d..a3b45c4190 100644 --- a/playwright/e2e/read-receipts/index.ts +++ b/playwright/e2e/read-receipts/index.ts @@ -538,7 +538,7 @@ class Helpers { const threadPanel = this.page.locator(".mx_ThreadPanel"); await expect(threadPanel).toBeVisible(); await threadPanel.evaluate(($panel) => { - const $button = $panel.querySelector('.mx_BaseCard_back[aria-label="Threads"]'); + const $button = $panel.querySelector('[data-testid="base-card-back-button"]'); // If the Threads back button is present then click it - the // threads button can open either threads list or thread panel if ($button) { diff --git a/playwright/e2e/right-panel/right-panel.spec.ts b/playwright/e2e/right-panel/right-panel.spec.ts index e323a4b24f..a5b6e9ec20 100644 --- a/playwright/e2e/right-panel/right-panel.spec.ts +++ b/playwright/e2e/right-panel/right-panel.spec.ts @@ -106,7 +106,7 @@ test.describe("RightPanel", () => { await expect(page.locator(".mx_FilePanel")).toBeVisible(); await expect(page.locator(".mx_FilePanel_empty")).toBeVisible(); - await page.getByRole("button", { name: "Room information" }).click(); + await page.getByTestId("base-card-back-button").click(); await checkRoomSummaryCard(page, ROOM_NAME); }); @@ -120,7 +120,7 @@ test.describe("RightPanel", () => { await expect(page.locator(".mx_UserInfo")).toBeVisible(); await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible(); - await page.getByRole("button", { name: "Room members" }).click(); + await page.getByTestId("base-card-back-button").click(); await expect(page.locator(".mx_MemberList")).toBeVisible(); await page.locator(".mx_RightPanelTabs").getByText("Info").click(); @@ -145,7 +145,7 @@ test.describe("RightPanel", () => { await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible(); await expect(page.locator(".mx_SpaceScopeHeader").getByText(SPACE_NAME)).toBeVisible(); - await page.getByRole("button", { name: "Back" }).click(); + await page.getByTestId("base-card-back-button").click(); await expect(page.locator(".mx_MemberList")).toBeVisible(); }); }); diff --git a/playwright/e2e/threads/threads.spec.ts b/playwright/e2e/threads/threads.spec.ts index 9b5ea46511..d53604aa4c 100644 --- a/playwright/e2e/threads/threads.spec.ts +++ b/playwright/e2e/threads/threads.spec.ts @@ -433,7 +433,7 @@ test.describe("Threads", () => { await textbox.press("Enter"); await expect(locator.locator(".mx_EventTile_last").getByText("Hello Mr. User")).toBeAttached(); // Close thread - await locator.getByRole("button", { name: "Close" }).click(); + await locator.getByTestId("base-card-close-button").click(); // Open existing thread locator = page @@ -486,7 +486,7 @@ test.describe("Threads", () => { await textbox.press("Enter"); await expect(threadPanel.locator(".mx_EventTile_last").getByText(threadMessage)).toBeVisible(); // Close thread - await threadPanel.getByRole("button", { name: "Close" }).click(); + await threadPanel.getByTestId("base-card-close-button").click(); }; await sendMessage("Hello Mr. Bot"); @@ -502,7 +502,7 @@ test.describe("Threads", () => { ).toBeVisible(); // Open threads list - await page.locator(".mx_BaseCard_back").click(); + await page.getByTestId("base-card-back-button").click(); const rightPanel = page.locator(".mx_RightPanel"); // Check that the threads are listed await expect(rightPanel.locator(".mx_EventTile").getByText("Hello Mr. User in a thread")).toBeVisible(); diff --git a/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-bubble-layout-linux.png b/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-bubble-layout-linux.png index c85c583a19a96d6cfc864745d33b21c6da83b9ca..9992923226d12e9e03fd3ba13a2fc420acf72659 100644 GIT binary patch literal 22386 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 R{}Ww-yJj}G$fl2D{|B&zsJQ?D literal 24660 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 diff --git a/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-group-layout-linux.png b/playwright/snapshots/polls/polls.spec.ts/ThreadView-with-a-poll-on-group-layout-linux.png index b6990e727ea14ec1488b1cc9c1c22ee894899350..050a82a8af811fb870518b1eb7ba645d3f836ad8 100644 GIT binary patch literal 22315 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 literal 10600 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𝔔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 G`9A>1>oq+9 diff --git a/playwright/snapshots/threads/threads.spec.ts/Reply-to-the-location-on-ThreadView-linux.png b/playwright/snapshots/threads/threads.spec.ts/Reply-to-the-location-on-ThreadView-linux.png index 281f1cebe5b09c7d336f3b74c0e5ec45491f8596..d30d8e98a8dd8a94c6251f060baab344d135c42c 100644 GIT binary patch literal 18839 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 diff --git a/playwright/snapshots/user-view/user-view.spec.ts/user-info-linux.png b/playwright/snapshots/user-view/user-view.spec.ts/user-info-linux.png index 61ab66015777917db2a47cdbb25fc8fa78d12077..0d4e64813c193d94be6f1092e51b5a160278b432 100644 GIT binary patch literal 16728 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 literal 17830 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 SH9WvhLFAt+Lo1|A0{=f<)4K8i diff --git a/res/css/views/right_panel/_BaseCard.pcss b/res/css/views/right_panel/_BaseCard.pcss index 67eb9b7e49..692f7d23b3 100644 --- a/res/css/views/right_panel/_BaseCard.pcss +++ b/res/css/views/right_panel/_BaseCard.pcss @@ -27,7 +27,7 @@ limitations under the License. .mx_BaseCard_header { height: 64px; - padding: var(--cpd-space-3x); + padding: var(--cpd-space-4x); box-sizing: border-box; /* changing the color from $separator to transparent as it is the best visual output during the transition period. This will be @@ -36,8 +36,13 @@ limitations under the License. display: flex; align-items: center; justify-content: space-between; - gap: var(--cpd-space-2x); + gap: var(--cpd-space-3x); flex-shrink: 0; + border-block-end: var(--cpd-border-width-1) solid $separator; + + .mx_BaseCard_header_spacer { + flex: 1; + } > h2 { margin: 0 44px; @@ -155,52 +160,6 @@ limitations under the License. } } -.mx_BaseCard_back, -.mx_BaseCard_close { - flex-shrink: 0; - position: relative; - /* @TODO(kerrya) background colours here are not semantic - these buttons to be replaced with IconButton after secondary variant is added - https://github.com/vector-im/compound/issues/279 */ - background-color: var(--cpd-color-bg-subtle-secondary); - width: var(--BaseCard_header-button-size); - height: var(--BaseCard_header-button-size); - border-radius: 50%; - - &:hover { - background-color: var(--cpd-color-bg-subtle-primary); - } - - &::before { - content: ""; - position: absolute; - height: inherit; - width: inherit; - top: 0; - left: 0; - mask-repeat: no-repeat; - mask-position: center; - mask-size: 20px; - background-color: var(--cpd-color-icon-secondary); - } -} - -.mx_BaseCard_back { - order: 0; /* always first! */ - &::before { - transform: rotate(90deg); - mask-size: 22px; - mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); - } -} - -.mx_BaseCard_close { - order: 999; /* always last */ - &::before { - mask-image: url("@vector-im/compound-design-tokens/icons/close.svg"); - } -} - .mx_ContextualMenu_wrapper.mx_BaseCard_header_title { .mx_ContextualMenu { position: initial; @@ -235,7 +194,3 @@ limitations under the License. } } } - -.mx_BaseCard_headerProp { - flex: 1 1 100%; -} diff --git a/res/themes/dark/css/_dark.pcss b/res/themes/dark/css/_dark.pcss index 326debc062..d398fb5967 100644 --- a/res/themes/dark/css/_dark.pcss +++ b/res/themes/dark/css/_dark.pcss @@ -14,7 +14,7 @@ $overlay-background: var(--cpd-color-alpha-gray-1300); $panels: var(--cpd-color-bg-subtle-secondary); $panel-actions: var(--cpd-color-alpha-gray-300); -$separator: var(--cpd-color-alpha-gray-400); +$separator: var(--cpd-color-gray-400); /* ******************** */ diff --git a/res/themes/legacy-dark/css/_legacy-dark.pcss b/res/themes/legacy-dark/css/_legacy-dark.pcss index 7e14e85f10..c6840f5b90 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.pcss +++ b/res/themes/legacy-dark/css/_legacy-dark.pcss @@ -105,7 +105,7 @@ $overlay-background: rgba($background, 0.85); $panels: rgba($system, 0.9); $panel-actions: $roomtile-selected-bg-color; -$separator: var(--cpd-color-alpha-gray-400); +$separator: var(--cpd-color-gray-400); /** * Creating a `semantic` color scale. This will not be needed with the new diff --git a/res/themes/legacy-light/css/_legacy-light.pcss b/res/themes/legacy-light/css/_legacy-light.pcss index 5f9b8fd452..e40fbde72b 100644 --- a/res/themes/legacy-light/css/_legacy-light.pcss +++ b/res/themes/legacy-light/css/_legacy-light.pcss @@ -163,7 +163,7 @@ $overlay-background: rgba($background, 0.85); $panels: rgba($system, 0.9); $panel-actions: $roomtile-selected-bg-color; -$separator: var(--cpd-color-alpha-gray-400); +$separator: var(--cpd-color-gray-400); /* Legacy theme backports */ diff --git a/res/themes/light/css/_light.pcss b/res/themes/light/css/_light.pcss index 730c115514..1a237427f2 100644 --- a/res/themes/light/css/_light.pcss +++ b/res/themes/light/css/_light.pcss @@ -32,7 +32,7 @@ $overlay-background: var(--cpd-color-alpha-gray-1300); $panels: var(--cpd-color-bg-subtle-secondary); $panel-actions: var(--cpd-color-alpha-gray-300); -$separator: var(--cpd-color-alpha-gray-400); +$separator: var(--cpd-color-gray-400); $accent: var(--cpd-color-text-action-accent); $alert: var(--cpd-color-text-critical-primary); diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index 1fca77c27e..d9e1cf2aa8 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -229,7 +229,7 @@ const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => const roomContext = useContext(RoomContext); const timelinePanel = useRef(null); const card = useRef(null); - const closeButonRef = useRef(null); + const closeButonRef = useRef(null); const [filterOption, setFilterOption] = useState(ThreadFilterType.All); const [room, setRoom] = useState(null); diff --git a/src/components/views/right_panel/BaseCard.tsx b/src/components/views/right_panel/BaseCard.tsx index bb07426a11..d8b0c1b71b 100644 --- a/src/components/views/right_panel/BaseCard.tsx +++ b/src/components/views/right_panel/BaseCard.tsx @@ -14,12 +14,14 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { forwardRef, ReactNode, KeyboardEvent, Ref } from "react"; +import React, { forwardRef, ReactNode, KeyboardEvent, Ref, MouseEvent } from "react"; import classNames from "classnames"; +import { IconButton, Text } from "@vector-im/compound-web"; +import { Icon as CloseIcon } from "@vector-im/compound-design-tokens/icons/close.svg"; +import { Icon as ChevronLeftIcon } from "@vector-im/compound-design-tokens/icons/chevron-left.svg"; import AutoHideScrollbar from "../../structures/AutoHideScrollbar"; import { _t } from "../../../languageHandler"; -import AccessibleButton, { ButtonEvent } from "../elements/AccessibleButton"; import RightPanelStore from "../../../stores/right-panel/RightPanelStore"; import { backLabelForPhase } from "../../../stores/right-panel/RightPanelStorePhases"; import { CardContext } from "./context"; @@ -34,13 +36,13 @@ interface IProps { ariaLabelledBy?: string; withoutScrollContainer?: boolean; closeLabel?: string; - onClose?(ev: ButtonEvent): void; - onBack?(ev: ButtonEvent): void; + onClose?(ev: MouseEvent): void; + onBack?(ev: MouseEvent): void; onKeyDown?(ev: KeyboardEvent): void; cardState?: any; ref?: Ref; // Ref for the 'close' button the the card - closeButtonRef?: Ref; + closeButtonRef?: Ref; children: ReactNode; } @@ -81,26 +83,39 @@ const BaseCard: React.FC = forwardRef( ) => { let backButton; const cardHistory = RightPanelStore.instance.roomPhaseHistory; - if (cardHistory.length > 1) { + if (cardHistory.length > 1 && !hideHeaderButtons) { const prevCard = cardHistory[cardHistory.length - 2]; - const onBackClick = (ev: ButtonEvent): void => { + const onBackClick = (ev: MouseEvent): void => { onBack?.(ev); RightPanelStore.instance.popCard(); }; const label = backLabelForPhase(prevCard.phase) ?? _t("action|back"); - backButton = ; + backButton = ( + + + + ); } let closeButton; - if (onClose) { + if (onClose && !hideHeaderButtons) { closeButton = ( - + tooltip={closeLabel ?? _t("action|close")} + subtleBackground + > + + ); } @@ -108,16 +123,6 @@ const BaseCard: React.FC = forwardRef( children = {children}; } - let headerButtons: React.ReactElement | undefined; - if (!hideHeaderButtons) { - headerButtons = ( - <> - {backButton} - {closeButton} - - ); - } - const shouldRenderHeader = header || !hideHeaderButtons; return ( @@ -132,8 +137,15 @@ const BaseCard: React.FC = forwardRef( > {shouldRenderHeader && (

- {headerButtons} -
{header}
+ {backButton} + {typeof header === "string" ? ( + + {header} + + ) : ( + header ??
+ )} + {closeButton}
)} {children} diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 5f9830f5d6..165f0707e0 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -1778,7 +1778,7 @@ const UserInfo: React.FC = ({ user, room, onClose, phase = RightPanelPha return (
+

+ Example 1 +

+ +
with crypto enabled renders 1`] = `
-
+ Profile +

+
with crypto enabled should render a deactivate button for
-
+ Profile +

+
should render invite 1`] = ` class="mx_BaseCard_header" >
should render invite when room in not availabl class="mx_BaseCard_header" >
Date: Tue, 16 Jul 2024 21:46:17 +0900 Subject: [PATCH 37/59] Let Element Call widget set session memberships (#12713) * Let Element Call widget set session memberships Grant Element Call widgets permission to set device-specific session membership state events. * Lint * Test that call widgets can set session membership * Add comments for each membership type --- src/stores/widgets/StopGapWidgetDriver.ts | 28 +++++++++++++++---- .../widgets/StopGapWidgetDriver-test.ts | 2 ++ 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index 248c520ddd..f6bffca3d2 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -144,13 +144,31 @@ export class StopGapWidgetDriver extends WidgetDriver { this.allowedCapabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomEncryption).raw, ); + const clientUserId = MatrixClientPeg.safeGet().getSafeUserId(); + // For the legacy membership type this.allowedCapabilities.add( - WidgetEventCapability.forStateEvent( - EventDirection.Send, - "org.matrix.msc3401.call.member", - MatrixClientPeg.safeGet().getSafeUserId(), - ).raw, + WidgetEventCapability.forStateEvent(EventDirection.Send, "org.matrix.msc3401.call.member", clientUserId) + .raw, ); + const clientDeviceId = MatrixClientPeg.safeGet().getDeviceId(); + if (clientDeviceId !== null) { + // For the session membership type compliant with MSC4143 + this.allowedCapabilities.add( + WidgetEventCapability.forStateEvent( + EventDirection.Send, + "org.matrix.msc3401.call.member", + `_${clientUserId}_${clientDeviceId}`, + ).raw, + ); + // MSC3779 version, with no leading underscore + this.allowedCapabilities.add( + WidgetEventCapability.forStateEvent( + EventDirection.Send, + "org.matrix.msc3401.call.member", + `${clientUserId}_${clientDeviceId}`, + ).raw, + ); + } this.allowedCapabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, "org.matrix.msc3401.call.member").raw, ); diff --git a/test/stores/widgets/StopGapWidgetDriver-test.ts b/test/stores/widgets/StopGapWidgetDriver-test.ts index 6e51d4ae98..5ba95d901d 100644 --- a/test/stores/widgets/StopGapWidgetDriver-test.ts +++ b/test/stores/widgets/StopGapWidgetDriver-test.ts @@ -99,6 +99,8 @@ describe("StopGapWidgetDriver", () => { "org.matrix.msc2762.receive.state_event:org.matrix.msc3401.call", "org.matrix.msc2762.send.state_event:org.matrix.msc3401.call.member#@alice:example.org", "org.matrix.msc2762.receive.state_event:org.matrix.msc3401.call.member", + `org.matrix.msc2762.send.state_event:org.matrix.msc3401.call.member#_@alice:example.org_${client.deviceId}`, + `org.matrix.msc2762.send.state_event:org.matrix.msc3401.call.member#@alice:example.org_${client.deviceId}`, "org.matrix.msc3819.send.to_device:m.call.invite", "org.matrix.msc3819.receive.to_device:m.call.invite", "org.matrix.msc3819.send.to_device:m.call.candidates", From 59d08d84b0912bf5c947a95d0db718f33a56bd89 Mon Sep 17 00:00:00 2001 From: Andrew Ferrazzutti Date: Tue, 16 Jul 2024 23:07:40 +0900 Subject: [PATCH 38/59] Let Element Call widget receive m.room.create (#12710) * Let Element Call widget receive m.room.create This allows the widget to check the room version without prompting the user to grant that capability, so the widget can know about version-specific auth rules (namely MSC3779). * Test that call widgets get RoomCreate events --- src/stores/widgets/StopGapWidgetDriver.ts | 4 ++++ test/stores/widgets/StopGapWidgetDriver-test.ts | 1 + 2 files changed, 5 insertions(+) diff --git a/src/stores/widgets/StopGapWidgetDriver.ts b/src/stores/widgets/StopGapWidgetDriver.ts index f6bffca3d2..cce1ca18a6 100644 --- a/src/stores/widgets/StopGapWidgetDriver.ts +++ b/src/stores/widgets/StopGapWidgetDriver.ts @@ -172,6 +172,10 @@ export class StopGapWidgetDriver extends WidgetDriver { this.allowedCapabilities.add( WidgetEventCapability.forStateEvent(EventDirection.Receive, "org.matrix.msc3401.call.member").raw, ); + // for determining auth rules specific to the room version + this.allowedCapabilities.add( + WidgetEventCapability.forStateEvent(EventDirection.Receive, EventType.RoomCreate).raw, + ); const sendRecvRoomEvents = ["io.element.call.encryption_keys"]; for (const eventType of sendRecvRoomEvents) { diff --git a/test/stores/widgets/StopGapWidgetDriver-test.ts b/test/stores/widgets/StopGapWidgetDriver-test.ts index 5ba95d901d..b0ec31044a 100644 --- a/test/stores/widgets/StopGapWidgetDriver-test.ts +++ b/test/stores/widgets/StopGapWidgetDriver-test.ts @@ -95,6 +95,7 @@ describe("StopGapWidgetDriver", () => { "org.matrix.msc2762.timeline:!1:example.org", "org.matrix.msc2762.send.event:org.matrix.rageshake_request", "org.matrix.msc2762.receive.event:org.matrix.rageshake_request", + "org.matrix.msc2762.receive.state_event:m.room.create", "org.matrix.msc2762.receive.state_event:m.room.member", "org.matrix.msc2762.receive.state_event:org.matrix.msc3401.call", "org.matrix.msc2762.send.state_event:org.matrix.msc3401.call.member#@alice:example.org", From e097cc00d069634149a5ed87dc202b52884859a0 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 16 Jul 2024 17:27:46 +0100 Subject: [PATCH 39/59] Update playwright monorepo to v1.45.2 (#12783) 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 c1f55013d3..d8c01c2c34 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1881,11 +1881,11 @@ integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== "@playwright/test@^1.40.1": - version "1.45.1" - resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.45.1.tgz#819b90fa43d17000fce5ebd127043fd661938b7a" - integrity sha512-Wo1bWTzQvGA7LyKGIZc8nFSTFf2TkthGIFBR+QVNilvwouGzFd4PYukZe3rvf5PSqjHi1+1NyKSDZKcQWETzaA== + version "1.45.2" + resolved "https://registry.yarnpkg.com/@playwright/test/-/test-1.45.2.tgz#e1b8512e20916720de1c5f5e89a362a252ea78ca" + integrity sha512-JxG9eq92ET75EbVi3s+4sYbcG7q72ECeZNbdBlaMkGcNbiDQ4cAi8U2QP5oKkOx+1gpaiL1LDStmzCaEM1Z6fQ== dependencies: - playwright "1.45.1" + playwright "1.45.2" "@radix-ui/primitive@1.0.1": version "1.0.1" @@ -7418,17 +7418,17 @@ pkg-dir@^4.2.0: dependencies: find-up "^4.0.0" -playwright-core@1.45.1, playwright-core@^1.45.1: - version "1.45.1" - resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.45.1.tgz#549a2701556b58245cc75263f9fc2795c1158dc1" - integrity sha512-LF4CUUtrUu2TCpDw4mcrAIuYrEjVDfT1cHbJMfwnE2+1b8PZcFzPNgvZCvq2JfQ4aTjRCCHw5EJ2tmr2NSzdPg== +playwright-core@1.45.2, playwright-core@^1.45.1: + version "1.45.2" + resolved "https://registry.yarnpkg.com/playwright-core/-/playwright-core-1.45.2.tgz#c8b8b7f66eda47fb2bd24e5435c92d1163022df8" + integrity sha512-ha175tAWb0dTK0X4orvBIqi3jGEt701SMxMhyujxNrgd8K0Uy5wMSwwcQHtyB4om7INUkfndx02XnQ2p6dvLDw== -playwright@1.45.1: - version "1.45.1" - resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.45.1.tgz#aaa6b0d6db14796b599d80c6679e63444e942534" - integrity sha512-Hjrgae4kpSQBr98nhCj3IScxVeVUixqj+5oyif8TdIn2opTCPEzqAqNMeK42i3cWDCVu9MI+ZsGWw+gVR4ISBg== +playwright@1.45.2: + version "1.45.2" + resolved "https://registry.yarnpkg.com/playwright/-/playwright-1.45.2.tgz#21082072120a2c8a7e3bbb2792e81e8aa367b7a7" + integrity sha512-ReywF2t/0teRvNBpfIgh5e4wnrI/8Su8ssdo5XsQKpjxJj+jspm00jSoz9BTg91TT0c9HRjXO7LBNVrgYj9X0g== dependencies: - playwright-core "1.45.1" + playwright-core "1.45.2" optionalDependencies: fsevents "2.3.2" From cf96a6d82c280cb7d3809c2dbdbfa316bf81aad2 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Wed, 17 Jul 2024 07:19:56 +0100 Subject: [PATCH 40/59] [create-pull-request] automated change (#12784) 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 c46676f0d5..c0354f45de 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:76683a0a17507dd6a724bc6eaab5763fdd7ecdb70d810c5bd94006ce84487edc"; +const DOCKER_TAG = "develop@sha256:c53712bee6a429cecaa5d0885c95b2c9ea926e73aa4982ff234ce2f2ee371da0"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From c57d8463b9d394a22cd39d2ada0501d457034ab8 Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 17 Jul 2024 10:58:07 +0100 Subject: [PATCH 41/59] Clear settings store cache on logout (#12786) And clear it in the widget layout store test, also fixing the tests which didn't actually individually as they actually relied on the state bleeding between tests. --- src/Lifecycle.ts | 1 + src/settings/SettingsStore.ts | 6 +++++ src/settings/handlers/LocalEchoWrapper.ts | 5 +++++ src/settings/handlers/SettingsHandler.ts | 5 +++++ test/stores/WidgetLayoutStore-test.ts | 27 ++++++++++++----------- 5 files changed, 31 insertions(+), 13 deletions(-) diff --git a/src/Lifecycle.ts b/src/Lifecycle.ts index f851ddddf6..e2141cd94d 100644 --- a/src/Lifecycle.ts +++ b/src/Lifecycle.ts @@ -1056,6 +1056,7 @@ export async function onLoggedOut(): Promise { await clearStorage({ deleteEverything: true }); LifecycleCustomisations.onLoggedOutAndStorageCleared?.(); await PlatformPeg.get()?.clearStorage(); + SettingsStore.reset(); // Do this last, so we can make sure all storage has been cleared and all // customisations got the memo. diff --git a/src/settings/SettingsStore.ts b/src/settings/SettingsStore.ts index a746485368..6e3e9e3e1f 100644 --- a/src/settings/SettingsStore.ts +++ b/src/settings/SettingsStore.ts @@ -134,6 +134,12 @@ export default class SettingsStore { // Counter used for generation of watcher IDs private static watcherCount = 1; + public static reset(): void { + for (const handler of Object.values(LEVEL_HANDLERS)) { + handler.reset(); + } + } + /** * Gets all the feature-style setting names. * @returns {string[]} The names of the feature settings. diff --git a/src/settings/handlers/LocalEchoWrapper.ts b/src/settings/handlers/LocalEchoWrapper.ts index ea216710e7..39724e5bc2 100644 --- a/src/settings/handlers/LocalEchoWrapper.ts +++ b/src/settings/handlers/LocalEchoWrapper.ts @@ -83,4 +83,9 @@ export default class LocalEchoWrapper extends SettingsHandler { public isSupported(): boolean { return this.handler.isSupported(); } + + public reset(): void { + this.cache = {}; + this.handler.reset(); + } } diff --git a/src/settings/handlers/SettingsHandler.ts b/src/settings/handlers/SettingsHandler.ts index d9cfdaca1d..db0ec7d730 100644 --- a/src/settings/handlers/SettingsHandler.ts +++ b/src/settings/handlers/SettingsHandler.ts @@ -61,4 +61,9 @@ export default abstract class SettingsHandler { * @returns {boolean} True if this level is supported on the current device. */ public abstract isSupported(): boolean; + + /** + * Resets the handler, clearing any caches or other stored data. Called on user logout. + */ + public reset(): void {} } diff --git a/test/stores/WidgetLayoutStore-test.ts b/test/stores/WidgetLayoutStore-test.ts index ddffe66ae9..17fbf9f2fa 100644 --- a/test/stores/WidgetLayoutStore-test.ts +++ b/test/stores/WidgetLayoutStore-test.ts @@ -57,6 +57,8 @@ describe("WidgetLayoutStore", () => { off: jest.fn(), getApps: () => mockApps, } as unknown as WidgetStore); + + SettingsStore.reset(); }); beforeAll(() => { @@ -156,9 +158,14 @@ describe("WidgetLayoutStore", () => { await store.start(); expect(roomUpdateListener).toHaveBeenCalled(); - expect(store.getContainerWidgets(mockRoom, Container.Top)).toEqual([mockApps[0]]); + expect(store.getContainerWidgets(mockRoom, Container.Top)).toEqual([]); expect(store.getContainerWidgets(mockRoom, Container.Center)).toEqual([]); - expect(store.getContainerWidgets(mockRoom, Container.Right)).toEqual([mockApps[1], mockApps[2], mockApps[3]]); + expect(store.getContainerWidgets(mockRoom, Container.Right)).toEqual([ + mockApps[0], + mockApps[1], + mockApps[2], + mockApps[3], + ]); }); it("should clear the layout and emit an update if there are no longer apps in the room", () => { @@ -238,21 +245,15 @@ describe("WidgetLayoutStore", () => { "widgets": { "1": { "container": "top", - "height": 23, - "index": 2, - "width": 64, + "height": undefined, + "index": 0, + "width": 100, }, "2": { - "container": "top", - "height": 23, - "index": 0, - "width": 10, + "container": "right", }, "3": { - "container": "top", - "height": 23, - "index": 1, - "width": 26, + "container": "right", }, "4": { "container": "right", From 4edf4e42cde989c565cdb0995d65b26484f5038b Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Wed, 17 Jul 2024 13:54:35 +0100 Subject: [PATCH 42/59] Remove SpaceScopeHeader (#12785) * Remove SpaceScopeHeader It is no longer necessary as we no longer offer the ability to open the member list for a space from any random room. Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Remove stale test Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../e2e/right-panel/right-panel.spec.ts | 2 - res/css/_components.pcss | 1 - res/css/views/rooms/_SpaceScopeHeader.pcss | 29 ---------- src/components/views/right_panel/UserInfo.tsx | 3 +- src/components/views/rooms/MemberList.tsx | 2 - .../views/rooms/SpaceScopeHeader.tsx | 54 ------------------- .../views/rooms/ThirdPartyMemberInfo.tsx | 3 +- .../views/right_panel/UserInfo-test.tsx | 9 ---- 8 files changed, 2 insertions(+), 101 deletions(-) delete mode 100644 res/css/views/rooms/_SpaceScopeHeader.pcss delete mode 100644 src/components/views/rooms/SpaceScopeHeader.tsx diff --git a/playwright/e2e/right-panel/right-panel.spec.ts b/playwright/e2e/right-panel/right-panel.spec.ts index a5b6e9ec20..51ebb3df92 100644 --- a/playwright/e2e/right-panel/right-panel.spec.ts +++ b/playwright/e2e/right-panel/right-panel.spec.ts @@ -138,12 +138,10 @@ test.describe("RightPanel", () => { .getByRole("button", { name: /\d member/ }) .click(); await expect(page.locator(".mx_MemberList")).toBeVisible(); - await expect(page.locator(".mx_SpaceScopeHeader").getByText(SPACE_NAME)).toBeVisible(); await getMemberTileByName(page, NAME).click(); await expect(page.locator(".mx_UserInfo")).toBeVisible(); await expect(page.locator(".mx_UserInfo_profile").getByText(NAME)).toBeVisible(); - await expect(page.locator(".mx_SpaceScopeHeader").getByText(SPACE_NAME)).toBeVisible(); await page.getByTestId("base-card-back-button").click(); await expect(page.locator(".mx_MemberList")).toBeVisible(); diff --git a/res/css/_components.pcss b/res/css/_components.pcss index 327b86da08..fc929f3d97 100644 --- a/res/css/_components.pcss +++ b/res/css/_components.pcss @@ -312,7 +312,6 @@ @import "./views/rooms/_RoomTile.pcss"; @import "./views/rooms/_RoomUpgradeWarningBar.pcss"; @import "./views/rooms/_SendMessageComposer.pcss"; -@import "./views/rooms/_SpaceScopeHeader.pcss"; @import "./views/rooms/_Stickers.pcss"; @import "./views/rooms/_ThirdPartyMemberInfo.pcss"; @import "./views/rooms/_ThreadSummary.pcss"; diff --git a/res/css/views/rooms/_SpaceScopeHeader.pcss b/res/css/views/rooms/_SpaceScopeHeader.pcss deleted file mode 100644 index 4a94793ba7..0000000000 --- a/res/css/views/rooms/_SpaceScopeHeader.pcss +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright 2023 The Matrix.org Foundation C.I.C. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -.mx_SpaceScopeHeader { - text-align: center; - - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 1; - overflow: hidden; - - .mx_BaseAvatar { - margin-right: var(--cpd-space-2x); - vertical-align: middle; - } -} diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 165f0707e0..493cb06bcf 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -80,7 +80,6 @@ import { DirectoryMember, startDmOnFirstMessage } from "../../../utils/direct-me import { SdkContextClass } from "../../../contexts/SDKContext"; import { asyncSome } from "../../../utils/arrays"; import UIStore from "../../../stores/UIStore"; -import { createSpaceScopeHeader } from "../rooms/SpaceScopeHeader"; export interface IDevice extends Device { ambiguous?: boolean; @@ -1778,7 +1777,7 @@ const UserInfo: React.FC = ({ user, room, onClose, phase = RightPanelPha return ( { className="mx_MemberList" ariaLabelledBy="memberlist-panel-tab" role="tabpanel" - header={createSpaceScopeHeader(room)} hideHeaderButtons={this.props.hideHeaderButtons} footer={footer} onClose={this.props.onClose} diff --git a/src/components/views/rooms/SpaceScopeHeader.tsx b/src/components/views/rooms/SpaceScopeHeader.tsx deleted file mode 100644 index b9f53b7b8a..0000000000 --- a/src/components/views/rooms/SpaceScopeHeader.tsx +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2023 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 { Room } from "matrix-js-sdk/src/matrix"; -import { Text } from "@vector-im/compound-web"; - -import RoomAvatar from "../avatars/RoomAvatar"; -import { useRoomName } from "../../../hooks/useRoomName"; - -/** - * Returns a space scope header if needed - * @param room The room object - * @returns rendered component if the room is a space room, otherwise returns null - */ -export function createSpaceScopeHeader(room?: Room | null): React.JSX.Element | null { - if (room?.isSpaceRoom()) return ; - else return null; -} - -/** - * Scope header used to decorate right panels that are scoped to a space. - * It renders room avatar and name. - */ -export const SpaceScopeHeader: React.FC<{ room: Room }> = ({ room }) => { - const roomName = useRoomName(room); - - return ( - - - {roomName} - - ); -}; diff --git a/src/components/views/rooms/ThirdPartyMemberInfo.tsx b/src/components/views/rooms/ThirdPartyMemberInfo.tsx index c2b772e78f..b510d5e002 100644 --- a/src/components/views/rooms/ThirdPartyMemberInfo.tsx +++ b/src/components/views/rooms/ThirdPartyMemberInfo.tsx @@ -28,7 +28,6 @@ import { Action } from "../../../dispatcher/actions"; import ErrorDialog from "../dialogs/ErrorDialog"; import BaseCard from "../right_panel/BaseCard"; import { Flex } from "../../utils/Flex"; -import { createSpaceScopeHeader } from "./SpaceScopeHeader"; interface IProps { event: MatrixEvent; @@ -134,7 +133,7 @@ export default class ThirdPartyMemberInfo extends React.Component + {/* same as userinfo name style */} diff --git a/test/components/views/right_panel/UserInfo-test.tsx b/test/components/views/right_panel/UserInfo-test.tsx index bc314e9e32..6875bf227d 100644 --- a/test/components/views/right_panel/UserInfo-test.tsx +++ b/test/components/views/right_panel/UserInfo-test.tsx @@ -302,15 +302,6 @@ describe("", () => { expect(screen.queryByTestId("space-header")).not.toBeInTheDocument(); }); - it("renders space header when room is a space room", () => { - const spaceRoom = { - ...mockRoom, - isSpaceRoom: jest.fn().mockReturnValue(true), - }; - renderComponent({ room: spaceRoom }); - expect(screen.getByTestId("space-header")).toBeInTheDocument(); - }); - it("renders encryption info panel without pending verification", () => { renderComponent({ phase: RightPanelPhases.EncryptionPanel, room: mockRoom }); expect(screen.getByRole("heading", { name: /encryption/i })).toBeInTheDocument(); From 3c9bd69d488854b447b0bcb7b57fa1c88e3a139e Mon Sep 17 00:00:00 2001 From: Alex Kirk Date: Wed, 17 Jul 2024 15:46:45 +0200 Subject: [PATCH 43/59] Accessibility: Add Landmark navigation (#12190) Co-authored-by: R Midhun Suresh --- .../accessibility/keyboard-navigation.spec.ts | 166 ++++++++++++++++++ src/@types/global.d.ts | 8 + src/Keyboard.ts | 2 + src/accessibility/KeyboardShortcuts.ts | 23 ++- src/accessibility/LandmarkNavigation.ts | 105 +++++++++++ src/components/structures/LeftPanel.tsx | 11 ++ src/components/structures/LoggedInView.tsx | 9 + .../views/rooms/BasicMessageComposer.tsx | 11 ++ src/components/views/rooms/RoomList.tsx | 20 ++- src/components/views/spaces/SpacePanel.tsx | 20 ++- src/i18n/strings/en_EN.json | 2 + .../accessibility/LandmarkNavigation-test.tsx | 130 ++++++++++++++ .../KeyboardUserSettingsTab-test.tsx.snap | 46 +++++ 13 files changed, 550 insertions(+), 3 deletions(-) create mode 100644 playwright/e2e/accessibility/keyboard-navigation.spec.ts create mode 100644 src/accessibility/LandmarkNavigation.ts create mode 100644 test/accessibility/LandmarkNavigation-test.tsx diff --git a/playwright/e2e/accessibility/keyboard-navigation.spec.ts b/playwright/e2e/accessibility/keyboard-navigation.spec.ts new file mode 100644 index 0000000000..b4b74f5187 --- /dev/null +++ b/playwright/e2e/accessibility/keyboard-navigation.spec.ts @@ -0,0 +1,166 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { test, expect } from "../../element-web-test"; +import { Bot } from "../../pages/bot"; + +test.describe("Landmark navigation tests", () => { + test.use({ + displayName: "Alice", + }); + + test("without any rooms", async ({ page, homeserver, app, user }) => { + /** + * Without any rooms, there is no tile in the roomlist to be focused. + * So the next landmark in the list should be focused instead. + */ + + // Pressing Control+F6 will first focus the space button + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + + // Pressing Control+F6 again will focus room search + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_RoomSearch")).toBeFocused(); + + // Pressing Control+F6 again will focus the message composer + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_HomePage")).toBeFocused(); + + // Pressing Control+F6 again will bring focus back to the space button + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + + // Now go back in the same order + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_HomePage")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_RoomSearch")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + }); + + test("with an open room", async ({ page, homeserver, app, user }) => { + const bob = new Bot(page, homeserver, { displayName: "Bob" }); + await bob.prepareClient(); + + // create dm with bob + await app.client.evaluate( + async (cli, { bob }) => { + const bobRoom = await cli.createRoom({ is_direct: true }); + await cli.invite(bobRoom.room_id, bob); + }, + { + bob: bob.credentials.userId, + }, + ); + + await app.viewRoomByName("Bob"); + // confirm the room was loaded + await expect(page.getByText("Bob joined the room")).toBeVisible(); + + // Pressing Control+F6 will first focus the space button + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + + // Pressing Control+F6 again will focus room search + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_RoomSearch")).toBeFocused(); + + // Pressing Control+F6 again will focus the room tile in the room list + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_RoomTile_selected")).toBeFocused(); + + // Pressing Control+F6 again will focus the message composer + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_BasicMessageComposer_input")).toBeFocused(); + + // Pressing Control+F6 again will bring focus back to the space button + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + + // Now go back in the same order + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_BasicMessageComposer_input")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_RoomTile_selected")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_RoomSearch")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + }); + + test("without an open room", async ({ page, homeserver, app, user }) => { + const bob = new Bot(page, homeserver, { displayName: "Bob" }); + await bob.prepareClient(); + + // create a dm with bob + await app.client.evaluate( + async (cli, { bob }) => { + const bobRoom = await cli.createRoom({ is_direct: true }); + await cli.invite(bobRoom.room_id, bob); + }, + { + bob: bob.credentials.userId, + }, + ); + + await app.viewRoomByName("Bob"); + // confirm the room was loaded + await expect(page.getByText("Bob joined the room")).toBeVisible(); + + // Close the room + page.goto("/#/home"); + + // Pressing Control+F6 will first focus the space button + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + + // Pressing Control+F6 again will focus room search + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_RoomSearch")).toBeFocused(); + + // Pressing Control+F6 again will focus the room tile in the room list + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_RoomTile")).toBeFocused(); + + // Pressing Control+F6 again will focus the home section + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_HomePage")).toBeFocused(); + + // Pressing Control+F6 will bring focus back to the space button + await page.keyboard.press("ControlOrMeta+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + + // Now go back in same order + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_HomePage")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_RoomTile")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_RoomSearch")).toBeFocused(); + + await page.keyboard.press("ControlOrMeta+Shift+F6"); + await expect(page.locator(".mx_SpaceButton_active")).toBeFocused(); + }); +}); diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index c62733c0f0..e42e83d58d 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -224,6 +224,14 @@ declare global { readonly port: MessagePort; } + /** + * In future, browsers will support focusVisible option. + * See https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#focusvisible + */ + interface FocusOptions { + focusVisible: boolean; + } + // https://github.com/microsoft/TypeScript/issues/28308#issuecomment-650802278 function registerProcessor( name: string, diff --git a/src/Keyboard.ts b/src/Keyboard.ts index 7b1ea4031b..33ce4e4e72 100644 --- a/src/Keyboard.ts +++ b/src/Keyboard.ts @@ -29,6 +29,7 @@ export const Key = { ARROW_DOWN: "ArrowDown", ARROW_LEFT: "ArrowLeft", ARROW_RIGHT: "ArrowRight", + F6: "F6", TAB: "Tab", ESCAPE: "Escape", ENTER: "Enter", @@ -77,6 +78,7 @@ export const Key = { }; export const IS_MAC = navigator.platform.toUpperCase().includes("MAC"); +export const IS_ELECTRON = window.electron; export function isOnlyCtrlOrCmdKeyEvent(ev: React.KeyboardEvent | KeyboardEvent): boolean { if (IS_MAC) { diff --git a/src/accessibility/KeyboardShortcuts.ts b/src/accessibility/KeyboardShortcuts.ts index 9a78f07df4..f5e18d205d 100644 --- a/src/accessibility/KeyboardShortcuts.ts +++ b/src/accessibility/KeyboardShortcuts.ts @@ -17,7 +17,7 @@ limitations under the License. */ import { _td, TranslationKey } from "../languageHandler"; -import { IS_MAC, Key } from "../Keyboard"; +import { IS_MAC, IS_ELECTRON, Key } from "../Keyboard"; import { IBaseSetting } from "../settings/Settings"; import { KeyCombo } from "../KeyBindingsManager"; @@ -129,6 +129,10 @@ export enum KeyBindingAction { PreviousVisitedRoomOrSpace = "KeyBinding.PreviousVisitedRoomOrSpace", /** Navigates forward */ NextVisitedRoomOrSpace = "KeyBinding.NextVisitedRoomOrSpace", + /** Navigates to the next Landmark */ + NextLandmark = "KeyBinding.nextLandmark", + /** Navigates to the next Landmark */ + PreviousLandmark = "KeyBinding.previousLandmark", /** Toggles microphone while on a call */ ToggleMicInCall = "KeyBinding.toggleMicInCall", @@ -291,6 +295,8 @@ export const CATEGORIES: Record = { KeyBindingAction.SwitchToSpaceByNumber, KeyBindingAction.PreviousVisitedRoomOrSpace, KeyBindingAction.NextVisitedRoomOrSpace, + KeyBindingAction.NextLandmark, + KeyBindingAction.PreviousLandmark, ], }, [CategoryName.AUTOCOMPLETE]: { @@ -714,4 +720,19 @@ export const KEYBOARD_SHORTCUTS: IKeyboardShortcuts = { key: Key.COMMA, }, }, + [KeyBindingAction.NextLandmark]: { + default: { + ctrlOrCmdKey: !IS_ELECTRON, + key: Key.F6, + }, + displayName: _td("keyboard|next_landmark"), + }, + [KeyBindingAction.PreviousLandmark]: { + default: { + ctrlOrCmdKey: !IS_ELECTRON, + key: Key.F6, + shiftKey: true, + }, + displayName: _td("keyboard|prev_landmark"), + }, }; diff --git a/src/accessibility/LandmarkNavigation.ts b/src/accessibility/LandmarkNavigation.ts new file mode 100644 index 0000000000..50ec478d2a --- /dev/null +++ b/src/accessibility/LandmarkNavigation.ts @@ -0,0 +1,105 @@ +/* + * 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 { TimelineRenderingType } from "../contexts/RoomContext"; +import { Action } from "../dispatcher/actions"; +import defaultDispatcher from "../dispatcher/dispatcher"; + +export const enum Landmark { + // This is the space/home button in the left panel. + ACTIVE_SPACE_BUTTON, + // This is the room filter in the left panel. + ROOM_SEARCH, + // This is the currently opened room/first room in the room list in the left panel. + ROOM_LIST, + // This is the message composer within the room if available or it is the welcome screen shown when no room is selected + MESSAGE_COMPOSER_OR_HOME, +} + +const ORDERED_LANDMARKS = [ + Landmark.ACTIVE_SPACE_BUTTON, + Landmark.ROOM_SEARCH, + Landmark.ROOM_LIST, + Landmark.MESSAGE_COMPOSER_OR_HOME, +]; + +/** + * The landmarks are cycled through in the following order: + * ACTIVE_SPACE_BUTTON <-> ROOM_SEARCH <-> ROOM_LIST <-> MESSAGE_COMPOSER/HOME <-> ACTIVE_SPACE_BUTTON + */ +export class LandmarkNavigation { + /** + * Get the next/previous landmark that must be focused from a given landmark + * @param currentLandmark The current landmark + * @param backwards If true, the landmark before currentLandmark in ORDERED_LANDMARKS is returned + * @returns The next landmark to focus + */ + private static getLandmark(currentLandmark: Landmark, backwards = false): Landmark { + const currentIndex = ORDERED_LANDMARKS.findIndex((l) => l === currentLandmark); + const offset = backwards ? -1 : 1; + const newLandmark = ORDERED_LANDMARKS.at((currentIndex + offset) % ORDERED_LANDMARKS.length)!; + return newLandmark; + } + + /** + * Focus the next landmark from a given landmark. + * This method will skip over any missing landmarks. + * @param currentLandmark The current landmark + * @param backwards If true, search the next landmark to the left in ORDERED_LANDMARKS + */ + public static findAndFocusNextLandmark(currentLandmark: Landmark, backwards = false): void { + let landmark = currentLandmark; + let element: HTMLElement | null | undefined = null; + while (element === null) { + landmark = LandmarkNavigation.getLandmark(landmark, backwards); + element = landmarkToDomElementMap[landmark](); + } + element?.focus({ focusVisible: true }); + } +} + +/** + * The functions return: + * - The DOM element of the landmark if it exists + * - undefined if the DOM element exists but focus is given through an action + * - null if the landmark does not exist + */ +const landmarkToDomElementMap: Record HTMLElement | null | undefined> = { + [Landmark.ACTIVE_SPACE_BUTTON]: () => document.querySelector(".mx_SpaceButton_active"), + + [Landmark.ROOM_SEARCH]: () => document.querySelector(".mx_RoomSearch"), + [Landmark.ROOM_LIST]: () => + document.querySelector(".mx_RoomTile_selected") || + document.querySelector(".mx_RoomTile"), + + [Landmark.MESSAGE_COMPOSER_OR_HOME]: () => { + const isComposerOpen = !!document.querySelector(".mx_MessageComposer"); + if (isComposerOpen) { + const inThread = !!document.activeElement?.closest(".mx_ThreadView"); + defaultDispatcher.dispatch( + { + action: Action.FocusSendMessageComposer, + context: inThread ? TimelineRenderingType.Thread : TimelineRenderingType.Room, + }, + true, + ); + // Special case where the element does exist but we focus it through an action. + return undefined; + } else { + return document.querySelector(".mx_HomePage"); + } + }, +}; diff --git a/src/components/structures/LeftPanel.tsx b/src/components/structures/LeftPanel.tsx index 084afdaf8b..7ef3bc4ba3 100644 --- a/src/components/structures/LeftPanel.tsx +++ b/src/components/structures/LeftPanel.tsx @@ -44,6 +44,7 @@ import AccessibleButton, { ButtonEvent } from "../views/elements/AccessibleButto import PosthogTrackers from "../../PosthogTrackers"; import PageType from "../../PageTypes"; import { UserOnboardingButton } from "../views/user-onboarding/UserOnboardingButton"; +import { Landmark, LandmarkNavigation } from "../../accessibility/LandmarkNavigation"; interface IProps { isMinimized: boolean; @@ -308,6 +309,16 @@ export default class LeftPanel extends React.Component { } break; } + + const navAction = getKeyBindingsManager().getNavigationAction(ev); + if (navAction === KeyBindingAction.PreviousLandmark || navAction === KeyBindingAction.NextLandmark) { + ev.stopPropagation(); + ev.preventDefault(); + LandmarkNavigation.findAndFocusNextLandmark( + Landmark.ROOM_SEARCH, + navAction === KeyBindingAction.PreviousLandmark, + ); + } }; private renderBreadcrumbs(): React.ReactNode { diff --git a/src/components/structures/LoggedInView.tsx b/src/components/structures/LoggedInView.tsx index 7687d0f3ea..755d2c1156 100644 --- a/src/components/structures/LoggedInView.tsx +++ b/src/components/structures/LoggedInView.tsx @@ -75,6 +75,7 @@ import { PipContainer } from "./PipContainer"; import { monitorSyncedPushRules } from "../../utils/pushRules/monitorSyncedPushRules"; import { ConfigOptions } from "../../SdkConfig"; import { MatrixClientContextProvider } from "./MatrixClientContextProvider"; +import { Landmark, LandmarkNavigation } from "../../accessibility/LandmarkNavigation"; // We need to fetch each pinned message individually (if we don't already have it) // so each pinned message may trigger a request. Limit the number per room for sanity. @@ -470,6 +471,14 @@ class LoggedInView extends React.Component { const navAction = getKeyBindingsManager().getNavigationAction(ev); switch (navAction) { + case KeyBindingAction.NextLandmark: + case KeyBindingAction.PreviousLandmark: + LandmarkNavigation.findAndFocusNextLandmark( + Landmark.MESSAGE_COMPOSER_OR_HOME, + navAction === KeyBindingAction.PreviousLandmark, + ); + handled = true; + break; case KeyBindingAction.FilterRooms: dis.dispatch({ action: "focus_room_filter", diff --git a/src/components/views/rooms/BasicMessageComposer.tsx b/src/components/views/rooms/BasicMessageComposer.tsx index 061dfe2703..38576dc255 100644 --- a/src/components/views/rooms/BasicMessageComposer.tsx +++ b/src/components/views/rooms/BasicMessageComposer.tsx @@ -51,6 +51,7 @@ import { _t } from "../../../languageHandler"; import { linkify } from "../../../linkify-matrix"; import { SdkContextClass } from "../../../contexts/SDKContext"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; +import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation"; // matches emoticons which follow the start of a line or whitespace const REGEX_EMOTICON_WHITESPACE = new RegExp("(?:^|\\s)(" + EMOTICON_REGEX.source + ")\\s|:^$"); @@ -536,6 +537,16 @@ export default class BasicMessageEditor extends React.Component } } + const navAction = getKeyBindingsManager().getNavigationAction(event); + + if (navAction === KeyBindingAction.NextLandmark || navAction === KeyBindingAction.PreviousLandmark) { + LandmarkNavigation.findAndFocusNextLandmark( + Landmark.MESSAGE_COMPOSER_OR_HOME, + navAction === KeyBindingAction.PreviousLandmark, + ); + handled = true; + } + const autocompleteAction = getKeyBindingsManager().getAutocompleteAction(event); const accessibilityAction = getKeyBindingsManager().getAccessibilityAction(event); if (model.autoComplete?.hasCompletions()) { diff --git a/src/components/views/rooms/RoomList.tsx b/src/components/views/rooms/RoomList.tsx index c277bd5aca..d088fbc927 100644 --- a/src/components/views/rooms/RoomList.tsx +++ b/src/components/views/rooms/RoomList.tsx @@ -60,7 +60,10 @@ import IconizedContextMenu, { import ExtraTile from "./ExtraTile"; import RoomSublist, { IAuxButtonProps } from "./RoomSublist"; import { SdkContextClass } from "../../../contexts/SDKContext"; +import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; +import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import AccessibleButton from "../elements/AccessibleButton"; +import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation"; interface IProps { onKeyDown: (ev: React.KeyboardEvent, state: IRovingTabIndexState) => void; @@ -652,7 +655,22 @@ export default class RoomList extends React.PureComponent {
{ + const navAction = getKeyBindingsManager().getNavigationAction(ev); + if ( + navAction === KeyBindingAction.NextLandmark || + navAction === KeyBindingAction.PreviousLandmark + ) { + LandmarkNavigation.findAndFocusNextLandmark( + Landmark.ROOM_LIST, + navAction === KeyBindingAction.PreviousLandmark, + ); + ev.stopPropagation(); + ev.preventDefault(); + return; + } + onKeyDownHandler(ev); + }} className="mx_RoomList" role="tree" aria-label={_t("common|rooms")} diff --git a/src/components/views/spaces/SpacePanel.tsx b/src/components/views/spaces/SpacePanel.tsx index 942be74bb9..5bd9a90850 100644 --- a/src/components/views/spaces/SpacePanel.tsx +++ b/src/components/views/spaces/SpacePanel.tsx @@ -67,10 +67,13 @@ import defaultDispatcher from "../../../dispatcher/dispatcher"; import { ActionPayload } from "../../../dispatcher/payloads"; import { Action } from "../../../dispatcher/actions"; import { NotificationState } from "../../../stores/notifications/NotificationState"; +import { KeyBindingAction } from "../../../accessibility/KeyboardShortcuts"; +import { getKeyBindingsManager } from "../../../KeyBindingsManager"; import { shouldShowComponent } from "../../../customisations/helpers/UIComponents"; import { UIComponent } from "../../../settings/UIFeature"; import { ThreadsActivityCentre } from "./threads-activity-centre/"; import AccessibleButton from "../elements/AccessibleButton"; +import { Landmark, LandmarkNavigation } from "../../../accessibility/LandmarkNavigation"; import { KeyboardShortcut } from "../settings/KeyboardShortcut"; const useSpaces = (): [Room[], MetaSpace[], Room[], SpaceKey] => { @@ -383,7 +386,22 @@ const SpacePanel: React.FC = () => { >
+
  • + Go to next landmark +
    + + + Ctrl + + + + + + + F6 + + +
    +
  • +
  • + Go to previous landmark +
    + + + Ctrl + + + + + + + Shift + + + + + + + F6 + + +
    +
  • From 39d453a5a3e19e2254e7fcb050b9b5969d36c9aa Mon Sep 17 00:00:00 2001 From: David Baker Date: Wed, 17 Jul 2024 14:51:42 +0100 Subject: [PATCH 44/59] Stop using the js-sdk's compare function (#12782) * Stop using the js-sdk's compare function The file is supposed to be a js-sdk internal module so we shouldn't have been using it, and now it uses the native collator, it's completely trivial. It was also causing Intl.Collator to be accessed at the module scope which risked it beating the modernizr check. * add test * Fix tests Move the restoreAllMocks to prevent mock leakage and also add some custom themes to test the ordering of those. * Move spy to the right place * Add ANOTHER test * Add test for integration manager ordering --- .../views/rooms/WhoIsTypingTile.tsx | 4 +- .../views/settings/PowerLevelSelector.tsx | 16 +++-- src/integrations/IntegrationManagers.ts | 4 +- .../tag-sorting/AlphabeticAlgorithm.ts | 4 +- src/stores/widgets/WidgetLayoutStore.ts | 6 +- src/theme.ts | 6 +- .../views/rooms/MemberList-test.tsx | 4 +- test/integrations/IntegrationManagers-test.ts | 70 +++++++++++++++++++ test/stores/WidgetLayoutStore-test.ts | 42 ++++++++--- test/theme-test.ts | 19 ++++- 10 files changed, 146 insertions(+), 29 deletions(-) create mode 100644 test/integrations/IntegrationManagers-test.ts diff --git a/src/components/views/rooms/WhoIsTypingTile.tsx b/src/components/views/rooms/WhoIsTypingTile.tsx index 1b5636cd15..2bc6337945 100644 --- a/src/components/views/rooms/WhoIsTypingTile.tsx +++ b/src/components/views/rooms/WhoIsTypingTile.tsx @@ -17,7 +17,6 @@ limitations under the License. import React from "react"; import { Room, RoomEvent, RoomMember, RoomMemberEvent, MatrixEvent } from "matrix-js-sdk/src/matrix"; -import { compare } from "matrix-js-sdk/src/utils"; import * as WhoIsTyping from "../../../WhoIsTyping"; import Timer from "../../../utils/Timer"; @@ -208,7 +207,8 @@ export default class WhoIsTypingTile extends React.Component { // sort them so the typing members don't change order when // moved to delayedStopTypingTimers - usersTyping.sort((a, b) => compare(a.name, b.name)); + const collator = new Intl.Collator(); + usersTyping.sort((a, b) => collator.compare(a.name, b.name)); const typingString = WhoIsTyping.whoIsTypingString(usersTyping, this.props.whoIsTypingLimit); if (!typingString) { diff --git a/src/components/views/settings/PowerLevelSelector.tsx b/src/components/views/settings/PowerLevelSelector.tsx index 5d823c885d..dcb1590c07 100644 --- a/src/components/views/settings/PowerLevelSelector.tsx +++ b/src/components/views/settings/PowerLevelSelector.tsx @@ -18,7 +18,6 @@ import React, { useState, JSX, PropsWithChildren } from "react"; import { Button } from "@vector-im/compound-web"; -import { compare } from "matrix-js-sdk/src/utils"; import { useMatrixClientContext } from "../../../contexts/MatrixClientContext"; import PowerSelector from "../elements/PowerSelector"; @@ -78,9 +77,11 @@ export function PowerLevelSelector({ currentPowerLevel && currentPowerLevel.value !== userLevels[currentPowerLevel?.userId], ); + const collator = new Intl.Collator(); + // We sort the users by power level, then we filter them const users = Object.keys(userLevels) - .sort((userA, userB) => sortUser(userA, userB, userLevels)) + .sort((userA, userB) => sortUser(collator, userA, userB, userLevels)) .filter(filter); // No user to display, we return the children into fragment to convert it to JSX.Element type @@ -136,7 +137,14 @@ export function PowerLevelSelector({ * @param userB * @param userLevels */ -function sortUser(userA: string, userB: string, userLevels: PowerLevelSelectorProps["userLevels"]): number { +function sortUser( + collator: Intl.Collator, + userA: string, + userB: string, + userLevels: PowerLevelSelectorProps["userLevels"], +): number { const powerLevelDiff = userLevels[userA] - userLevels[userB]; - return powerLevelDiff !== 0 ? powerLevelDiff : compare(userA.toLocaleLowerCase(), userB.toLocaleLowerCase()); + return powerLevelDiff !== 0 + ? powerLevelDiff + : collator.compare(userA.toLocaleLowerCase(), userB.toLocaleLowerCase()); } diff --git a/src/integrations/IntegrationManagers.ts b/src/integrations/IntegrationManagers.ts index 0ec7d99185..5ccf6a6e0c 100644 --- a/src/integrations/IntegrationManagers.ts +++ b/src/integrations/IntegrationManagers.ts @@ -16,7 +16,6 @@ limitations under the License. import { logger } from "matrix-js-sdk/src/logger"; import { ClientEvent, IClientWellKnown, MatrixClient } from "matrix-js-sdk/src/matrix"; -import { compare } from "matrix-js-sdk/src/utils"; import type { MatrixEvent } from "matrix-js-sdk/src/matrix"; import SdkConfig from "../SdkConfig"; @@ -145,6 +144,7 @@ export class IntegrationManagers { } public getOrderedManagers(): IntegrationManagerInstance[] { + const collator = new Intl.Collator(); const ordered: IntegrationManagerInstance[] = []; for (const kind of KIND_PREFERENCE) { const managers = this.managers.filter((m) => m.kind === kind); @@ -152,7 +152,7 @@ export class IntegrationManagers { if (kind === Kind.Account) { // Order by state_keys (IDs) - managers.sort((a, b) => compare(a.id ?? "", b.id ?? "")); + managers.sort((a, b) => collator.compare(a.id ?? "", b.id ?? "")); } ordered.push(...managers); diff --git a/src/stores/room-list/algorithms/tag-sorting/AlphabeticAlgorithm.ts b/src/stores/room-list/algorithms/tag-sorting/AlphabeticAlgorithm.ts index 9b2363214a..4421c23c60 100644 --- a/src/stores/room-list/algorithms/tag-sorting/AlphabeticAlgorithm.ts +++ b/src/stores/room-list/algorithms/tag-sorting/AlphabeticAlgorithm.ts @@ -15,7 +15,6 @@ limitations under the License. */ import { Room } from "matrix-js-sdk/src/matrix"; -import { compare } from "matrix-js-sdk/src/utils"; import { TagID } from "../../models"; import { IAlgorithm } from "./IAlgorithm"; @@ -25,8 +24,9 @@ import { IAlgorithm } from "./IAlgorithm"; */ export class AlphabeticAlgorithm implements IAlgorithm { public sortRooms(rooms: Room[], tagId: TagID): Room[] { + const collator = new Intl.Collator(); return rooms.sort((a, b) => { - return compare(a.name, b.name); + return collator.compare(a.name, b.name); }); } } diff --git a/src/stores/widgets/WidgetLayoutStore.ts b/src/stores/widgets/WidgetLayoutStore.ts index eef5d84d0d..6b5766ebc9 100644 --- a/src/stores/widgets/WidgetLayoutStore.ts +++ b/src/stores/widgets/WidgetLayoutStore.ts @@ -16,7 +16,7 @@ import { Room, RoomStateEvent, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { Optional } from "matrix-events-sdk"; -import { compare, MapWithDefault, recursiveMapToObject } from "matrix-js-sdk/src/utils"; +import { MapWithDefault, recursiveMapToObject } from "matrix-js-sdk/src/utils"; import { IWidget } from "matrix-widget-api"; import SettingsStore from "../../settings/SettingsStore"; @@ -200,6 +200,8 @@ export class WidgetLayoutStore extends ReadyWatchingStore { const runoff = topWidgets.slice(MAX_PINNED); rightWidgets.push(...runoff); + const collator = new Intl.Collator(); + // Order the widgets in the top container, putting autopinned Jitsi widgets first // unless they have a specific order in mind topWidgets.sort((a, b) => { @@ -219,7 +221,7 @@ export class WidgetLayoutStore extends ReadyWatchingStore { if (orderA === orderB) { // We just need a tiebreak - return compare(a.id, b.id); + return collator.compare(a.id, b.id); } return orderA - orderB; diff --git a/src/theme.ts b/src/theme.ts index 3245d72b76..9cff3f95be 100644 --- a/src/theme.ts +++ b/src/theme.ts @@ -15,7 +15,6 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { compare } from "matrix-js-sdk/src/utils"; import { logger } from "matrix-js-sdk/src/logger"; import { _t } from "./languageHandler"; @@ -113,7 +112,10 @@ export function getOrderedThemes(): ITheme[] { .map((p) => ({ id: p[0], name: p[1] })) // convert pairs to objects for code readability .filter((p) => !isHighContrastTheme(p.id)); const builtInThemes = themes.filter((p) => !p.id.startsWith("custom-")); - const customThemes = themes.filter((p) => !builtInThemes.includes(p)).sort((a, b) => compare(a.name, b.name)); + const collator = new Intl.Collator(); + const customThemes = themes + .filter((p) => !builtInThemes.includes(p)) + .sort((a, b) => collator.compare(a.name, b.name)); return [...builtInThemes, ...customThemes]; } diff --git a/test/components/views/rooms/MemberList-test.tsx b/test/components/views/rooms/MemberList-test.tsx index 648fa71230..87806e5a85 100644 --- a/test/components/views/rooms/MemberList-test.tsx +++ b/test/components/views/rooms/MemberList-test.tsx @@ -19,7 +19,6 @@ import React from "react"; import { act, fireEvent, render, RenderResult, screen } from "@testing-library/react"; import { Room, MatrixClient, RoomState, RoomMember, User, MatrixEvent } from "matrix-js-sdk/src/matrix"; import { KnownMembership } from "matrix-js-sdk/src/types"; -import { compare } from "matrix-js-sdk/src/utils"; import { mocked, MockedObject } from "jest-mock"; import { MatrixClientPeg } from "../../../../src/MatrixClientPeg"; @@ -145,7 +144,8 @@ describe("MemberList", () => { if (!groupChange) { const nameA = memberA.name[0] === "@" ? memberA.name.slice(1) : memberA.name; const nameB = memberB.name[0] === "@" ? memberB.name.slice(1) : memberB.name; - const nameCompare = compare(nameB, nameA); + const collator = new Intl.Collator(); + const nameCompare = collator.compare(nameB, nameA); console.log("Comparing name"); expect(nameCompare).toBeGreaterThanOrEqual(0); } else { diff --git a/test/integrations/IntegrationManagers-test.ts b/test/integrations/IntegrationManagers-test.ts new file mode 100644 index 0000000000..db95ab435b --- /dev/null +++ b/test/integrations/IntegrationManagers-test.ts @@ -0,0 +1,70 @@ +/* +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 { MatrixClient, MatrixEvent } from "matrix-js-sdk/src/matrix"; +import { mocked } from "jest-mock"; + +import { IntegrationManagers } from "../../src/integrations/IntegrationManagers"; +import { stubClient } from "../test-utils"; + +describe("IntegrationManagers", () => { + let client: MatrixClient; + let intMgrs: IntegrationManagers; + + beforeEach(() => { + client = stubClient(); + mocked(client).getAccountData.mockReturnValue({ + getContent: jest.fn().mockReturnValue({ + foo: { + id: "foo", + content: { + type: "m.integration_manager", + url: "http://foo/ui", + data: { + api_url: "http://foo/api", + }, + }, + }, + bar: { + id: "bar", + content: { + type: "m.integration_manager", + url: "http://bar/ui", + data: { + api_url: "http://bar/api", + }, + }, + }, + }), + } as unknown as MatrixEvent); + + intMgrs = new IntegrationManagers(); + intMgrs.startWatching(); + }); + + afterEach(() => { + intMgrs.stopWatching(); + }); + + describe("getOrderedManagers", () => { + it("should return integration managers in alphabetical order", () => { + const orderedManagers = intMgrs.getOrderedManagers(); + + expect(orderedManagers[0].id).toBe("bar"); + expect(orderedManagers[1].id).toBe("foo"); + }); + }); +}); diff --git a/test/stores/WidgetLayoutStore-test.ts b/test/stores/WidgetLayoutStore-test.ts index 17fbf9f2fa..ee4ebcc6d0 100644 --- a/test/stores/WidgetLayoutStore-test.ts +++ b/test/stores/WidgetLayoutStore-test.ts @@ -25,25 +25,29 @@ import SettingsStore from "../../src/settings/SettingsStore"; // setup test env values const roomId = "!room:server"; -const mockRoom = { - roomId: roomId, - currentState: { - getStateEvents: (_l, _x) => { - return { - getId: () => "$layoutEventId", - getContent: () => null, - }; - }, - }, -}; describe("WidgetLayoutStore", () => { let client: MatrixClient; let store: WidgetLayoutStore; let roomUpdateListener: (event: string) => void; let mockApps: IApp[]; + let mockRoom: Room; + let layoutEventContent: Record | null; beforeEach(() => { + layoutEventContent = null; + mockRoom = { + roomId: roomId, + currentState: { + getStateEvents: (_l, _x) => { + return { + getId: () => "$layoutEventId", + getContent: () => layoutEventContent, + }; + }, + }, + }; + mockApps = [ { roomId: roomId, id: "1" }, { roomId: roomId, id: "2" }, @@ -87,6 +91,22 @@ describe("WidgetLayoutStore", () => { expect(store.getContainerHeight(mockRoom, Container.Top)).toBeNull(); }); + it("ordering of top container widgets should be consistent even if no index specified", async () => { + layoutEventContent = { + widgets: { + "1": { + container: "top", + }, + "2": { + container: "top", + }, + }, + }; + + store.recalculateRoom(mockRoom); + expect(store.getContainerWidgets(mockRoom, Container.Top)).toStrictEqual([mockApps[0], mockApps[1]]); + }); + it("add three widgets to top container", async () => { store.recalculateRoom(mockRoom); store.moveToContainer(mockRoom, mockApps[0], Container.Top); diff --git a/test/theme-test.ts b/test/theme-test.ts index fdba6d0d18..b375a75301 100644 --- a/test/theme-test.ts +++ b/test/theme-test.ts @@ -15,9 +15,13 @@ limitations under the License. */ import SettingsStore from "../src/settings/SettingsStore"; -import { enumerateThemes, setTheme } from "../src/theme"; +import { enumerateThemes, getOrderedThemes, setTheme } from "../src/theme"; describe("theme", () => { + afterEach(() => { + jest.restoreAllMocks(); + }); + describe("setTheme", () => { let lightTheme: HTMLStyleElement; let darkTheme: HTMLStyleElement; @@ -48,7 +52,6 @@ describe("theme", () => { }); afterEach(() => { - jest.restoreAllMocks(); jest.useRealTimers(); }); @@ -162,4 +165,16 @@ describe("theme", () => { }); }); }); + + describe("getOrderedThemes", () => { + it("should return a list of themes in the correct order", () => { + jest.spyOn(SettingsStore, "getValue").mockReturnValue([{ name: "Zebra Striped" }, { name: "Apple Green" }]); + expect(getOrderedThemes()).toEqual([ + { id: "light", name: "Light" }, + { id: "dark", name: "Dark" }, + { id: "custom-Apple Green", name: "Apple Green" }, + { id: "custom-Zebra Striped", name: "Zebra Striped" }, + ]); + }); + }); }); From 72d32bd681478c96b48c4247978d92679cd1c8a4 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Thu, 18 Jul 2024 07:21:00 +0100 Subject: [PATCH 45/59] [create-pull-request] automated change (#12789) 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 c0354f45de..3b63306ecb 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:c53712bee6a429cecaa5d0885c95b2c9ea926e73aa4982ff234ce2f2ee371da0"; +const DOCKER_TAG = "develop@sha256:1e71b0a038807a93d586f0624c6db2b49eeff371765d2f2abb240cdad1c246cb"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From 924f5a079f9c11641c5d76913762dfd2b2ae77e3 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 18 Jul 2024 08:41:44 +0100 Subject: [PATCH 46/59] Add test for the unsupported browser screen (#12787) * Add test for the unsupported browser screen Test a handful of APIs that are easy to disable with an init script and assert that the app display the "Unsupported Browser" screen. * Oops, test wasn't actually testing anything * Remove other feature tests They didn't work because there are two separate screens, one of which has an iframe and one of which doesn't. * Add screenshot test * Rename to ts * Fix screenshot * Fix snapshot filename * Rename file * rename screenshot again * rename screenshot again * 16th time's a charm * remove file * please just be in the right place --- .../e2e/app-loading/feature-detection.spec.ts | 27 ++++++++++++++++++ .../unsupported-browser-linux.png | Bin 0 -> 59582 bytes 2 files changed, 27 insertions(+) create mode 100644 playwright/e2e/app-loading/feature-detection.spec.ts create mode 100644 playwright/snapshots/app-loading/feature-detection.spec.ts/unsupported-browser-linux.png diff --git a/playwright/e2e/app-loading/feature-detection.spec.ts b/playwright/e2e/app-loading/feature-detection.spec.ts new file mode 100644 index 0000000000..d0a72fd27f --- /dev/null +++ b/playwright/e2e/app-loading/feature-detection.spec.ts @@ -0,0 +1,27 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import { test, expect } from "../../element-web-test"; + +test(`shows error page if browser lacks Intl support`, async ({ page }) => { + await page.addInitScript({ content: `delete window.Intl;` }); + await page.goto("/"); + + const header = await page.frameLocator("iframe").getByText("Unsupported browser"); + await expect(header).toBeVisible(); + + await expect(page).toMatchScreenshot("unsupported-browser.png"); +}); diff --git a/playwright/snapshots/app-loading/feature-detection.spec.ts/unsupported-browser-linux.png b/playwright/snapshots/app-loading/feature-detection.spec.ts/unsupported-browser-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..96ad96e3e119ecc46b2d7a2f2b198aeacf1178de GIT binary patch literal 59582 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 VMm}bcx)GJlRjF%|SrU5p{tqXm!j1p{ literal 0 HcmV?d00001 From 564ea53b8395595706ea8c9d6cca62e32145c108 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 18 Jul 2024 14:04:40 +0100 Subject: [PATCH 47/59] Fix stray 'account' heading (#12791) * Fix stray 'account' heading There's nothing in the 'account' section other than the password change control now, so remove the whole section if you can't change your password. Fixes https://github.com/element-hq/element-web/issues/27756 * Unused import --- .../tabs/user/GeneralUserSettingsTab.tsx | 29 +++++++------------ 1 file changed, 11 insertions(+), 18 deletions(-) diff --git a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx index 57d1983238..8405dd83ba 100644 --- a/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx +++ b/src/components/views/settings/tabs/user/GeneralUserSettingsTab.tsx @@ -16,7 +16,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -import React, { ReactNode } from "react"; +import React from "react"; import { HTTPError } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; @@ -146,22 +146,8 @@ export default class GeneralUserSettingsTab extends React.Component - {_t("settings|general|password_change_section")} - - - ); - } + private renderAccountSection(): JSX.Element | undefined { + if (!this.state.canChangePassword) return undefined; return ( <> @@ -170,7 +156,14 @@ export default class GeneralUserSettingsTab extends React.Component - {passwordChangeSection} + {_t("settings|general|password_change_section")} + ); From 2920e76b64730fc435932b2709a99d73a94c3b96 Mon Sep 17 00:00:00 2001 From: David Baker Date: Thu, 18 Jul 2024 14:25:02 +0100 Subject: [PATCH 48/59] Test for lack of WebAssembly support (#12792) * Test for lack of WebAssembly support * Good news: the 'only' detection works --- .../e2e/app-loading/feature-detection.spec.ts | 15 +++++++++++++++ ...upported-browser-CompatibilityView-linux.png | Bin 0 -> 70539 bytes 2 files changed, 15 insertions(+) create mode 100644 playwright/snapshots/app-loading/feature-detection.spec.ts/unsupported-browser-CompatibilityView-linux.png diff --git a/playwright/e2e/app-loading/feature-detection.spec.ts b/playwright/e2e/app-loading/feature-detection.spec.ts index d0a72fd27f..2acde32c37 100644 --- a/playwright/e2e/app-loading/feature-detection.spec.ts +++ b/playwright/e2e/app-loading/feature-detection.spec.ts @@ -20,8 +20,23 @@ test(`shows error page if browser lacks Intl support`, async ({ page }) => { await page.addInitScript({ content: `delete window.Intl;` }); await page.goto("/"); + // Lack of Intl support causes the app bundle to fail to load, so we get the iframed + // static error page and need to explicitly look in the iframe becuse Playwright doesn't + // recurse into iframes when looking for elements const header = await page.frameLocator("iframe").getByText("Unsupported browser"); await expect(header).toBeVisible(); await expect(page).toMatchScreenshot("unsupported-browser.png"); }); + +test(`shows error page if browser lacks WebAssembly support`, async ({ page }) => { + await page.addInitScript({ content: `delete window.WebAssembly;` }); + await page.goto("/"); + + // Lack of WebAssembly support doesn't cause the bundle to fail loading, so we get + // CompatibilityView, ie. no iframes. + const header = await page.getByText("Unsupported browser"); + await expect(header).toBeVisible(); + + await expect(page).toMatchScreenshot("unsupported-browser-CompatibilityView.png"); +}); diff --git a/playwright/snapshots/app-loading/feature-detection.spec.ts/unsupported-browser-CompatibilityView-linux.png b/playwright/snapshots/app-loading/feature-detection.spec.ts/unsupported-browser-CompatibilityView-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..df1a44f523cab9eefc55931f421e7e9c02c08d4d GIT binary patch literal 70539 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 H*{%Nv>STUi literal 0 HcmV?d00001 From f706ac4fa19980bfb09526271e6ed6758bbe1d5f Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Thu, 18 Jul 2024 15:24:44 +0100 Subject: [PATCH 49/59] Update styling of UserInfo right panel card (#12788) * Add colour to PresenceLabel in UserInfo Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update button positions & styles in UserInfo Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update UserInfo styles Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Revert Ignore->Block copy change Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- .../user-view.spec.ts/user-info-linux.png | Bin 16728 -> 17208 bytes res/css/views/right_panel/_UserInfo.pcss | 79 ++-- res/css/views/rooms/_PresenceLabel.pcss | 4 + src/components/views/right_panel/UserInfo.tsx | 433 ++++++++++-------- src/components/views/rooms/PresenceLabel.tsx | 10 +- src/i18n/strings/en_EN.json | 8 +- .../views/right_panel/UserInfo-test.tsx | 187 +++++--- .../__snapshots__/UserInfo-test.tsx.snap | 368 +++++++++++---- 8 files changed, 670 insertions(+), 419 deletions(-) diff --git a/playwright/snapshots/user-view/user-view.spec.ts/user-info-linux.png b/playwright/snapshots/user-view/user-view.spec.ts/user-info-linux.png index 0d4e64813c193d94be6f1092e51b5a160278b432..b6d6d2a210856bdaeae1a9500ce9b2822271075f 100644 GIT binary patch literal 17208 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 MOjfi)`0Mxo1@+W9uK)l5 literal 16728 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 diff --git a/res/css/views/right_panel/_UserInfo.pcss b/res/css/views/right_panel/_UserInfo.pcss index 1dfd39dd25..a2e156e0e5 100644 --- a/res/css/views/right_panel/_UserInfo.pcss +++ b/res/css/views/right_panel/_UserInfo.pcss @@ -41,35 +41,17 @@ limitations under the License. } } - h2 { - font-size: $font-18px; - font-weight: var(--cpd-font-weight-semibold); - margin: 18px 0 0 0; - } - .mx_UserInfo_container { - padding: $spacing-8 $spacing-16; - - &:not(.mx_UserInfo_separator) { - padding-top: $spacing-16; - padding-bottom: 0; - - > :not(h3) { - margin-inline-start: $spacing-8; - display: flex; - flex-flow: column; - align-items: flex-start; - row-gap: $spacing-8; - } - } + padding: var(--cpd-space-4x) 0; + margin: 0 var(--cpd-space-4x); .mx_UserInfo_container_verifyButton { margin-top: $spacing-8; } - } - .mx_UserInfo_separator { - border-bottom: 1px solid $separator; + & + .mx_UserInfo_container { + border-top: 1px solid $separator; + } } .mx_UserInfo_memberDetailsContainer { @@ -94,7 +76,7 @@ limitations under the License. margin: $spacing-24 $spacing-32 0 $spacing-32; .mx_UserInfo_avatar_transition { - max-width: 30vh; + max-width: 120px; aspect-ratio: 1 / 1; margin: 0 auto; transition: 0.5s; @@ -112,7 +94,7 @@ limitations under the License. } } - h3 { + h2 { text-transform: uppercase; color: $tertiary-content; font: var(--cpd-font-heading-sm-semibold); @@ -125,41 +107,36 @@ limitations under the License. } .mx_UserInfo_profile { - text-align: center; - - h2 { - display: flex; - font-size: $font-17px; + h1 { + font-size: $font-20px; line-height: $font-25px; - flex: 1; - justify-content: center; - /* We reverse things here so for accessible technologies the name comes before the e2e shield */ - flex-direction: row-reverse; - span { - /* limit to 2 lines, show an ellipsis if it overflows */ - /* this looks webkit specific but is supported by Firefox 68+ */ - display: -webkit-box; - -webkit-box-orient: vertical; - -webkit-line-clamp: 2; + /* limit to 2 lines, show an ellipsis if it overflows */ + /* this looks webkit specific but is supported by Firefox 68+ */ + display: -webkit-box; + -webkit-box-orient: vertical; + -webkit-line-clamp: 2; - overflow: hidden; - word-break: break-all; - text-overflow: ellipsis; - } + overflow: hidden; + word-break: break-all; + text-overflow: ellipsis; - .mx_E2EIcon { - margin-top: 3px; /* visual vertical centering to the top line of text. */ - margin-inline-end: $spacing-4; /* margin from displayName */ - min-width: 18px; /* convince flexbox to not collapse it */ + /* E2E icon wrapper */ + .mx_Flex > span { + display: inline-block; } } .mx_UserInfo_profileStatus { - margin-top: $spacing-12; + margin: var(--cpd-space-1x) 0; } } + .mx_PresenceLabel { + font: var(--cpd-font-body-sm-regular); + opacity: 1; + } + .mx_UserInfo_memberDetails { .mx_UserInfo_profileField { display: flex; @@ -184,10 +161,6 @@ limitations under the License. .mx_UserInfo_field { line-height: $font-16px; - - &.mx_UserInfo_destructive { - color: $alert; - } } .mx_UserInfo_statusMessage { diff --git a/res/css/views/rooms/_PresenceLabel.pcss b/res/css/views/rooms/_PresenceLabel.pcss index 5be83c77d7..e775fb08ea 100644 --- a/res/css/views/rooms/_PresenceLabel.pcss +++ b/res/css/views/rooms/_PresenceLabel.pcss @@ -18,3 +18,7 @@ limitations under the License. font-size: $font-11px; opacity: 0.5; } + +.mx_PresenceLabel_online { + color: var(--cpd-color-text-success-primary); +} diff --git a/src/components/views/right_panel/UserInfo.tsx b/src/components/views/right_panel/UserInfo.tsx index 493cb06bcf..1f9843d708 100644 --- a/src/components/views/right_panel/UserInfo.tsx +++ b/src/components/views/right_panel/UserInfo.tsx @@ -34,6 +34,18 @@ import { KnownMembership } from "matrix-js-sdk/src/types"; import { UserVerificationStatus, VerificationRequest } from "matrix-js-sdk/src/crypto-api"; import { logger } from "matrix-js-sdk/src/logger"; import { CryptoEvent } from "matrix-js-sdk/src/crypto"; +import { Heading, MenuItem, Text } from "@vector-im/compound-web"; +import { Icon as ChatIcon } from "@vector-im/compound-design-tokens/icons/chat.svg"; +import { Icon as CheckIcon } from "@vector-im/compound-design-tokens/icons/check.svg"; +import { Icon as ShareIcon } from "@vector-im/compound-design-tokens/icons/share.svg"; +import { Icon as MentionIcon } from "@vector-im/compound-design-tokens/icons/mention.svg"; +import { Icon as InviteIcon } from "@vector-im/compound-design-tokens/icons/user-add.svg"; +import { Icon as BlockIcon } from "@vector-im/compound-design-tokens/icons/block.svg"; +import { Icon as DeleteIcon } from "@vector-im/compound-design-tokens/icons/delete.svg"; +import { Icon as CloseIcon } from "@vector-im/compound-design-tokens/icons/close.svg"; +import { Icon as ChatProblemIcon } from "@vector-im/compound-design-tokens/icons/chat-problem.svg"; +import { Icon as VisibilityOffIcon } from "@vector-im/compound-design-tokens/icons/visibility-off.svg"; +import { Icon as LeaveIcon } from "@vector-im/compound-design-tokens/icons/leave.svg"; import dis from "../../../dispatcher/dispatcher"; import Modal from "../../../Modal"; @@ -79,7 +91,8 @@ import { ViewRoomPayload } from "../../../dispatcher/payloads/ViewRoomPayload"; import { DirectoryMember, startDmOnFirstMessage } from "../../../utils/direct-messages"; import { SdkContextClass } from "../../../contexts/SDKContext"; import { asyncSome } from "../../../utils/arrays"; -import UIStore from "../../../stores/UIStore"; +import { Flex } from "../../utils/Flex"; +import CopyableText from "../elements/CopyableText"; export interface IDevice extends Device { ambiguous?: boolean; @@ -391,31 +404,29 @@ const MessageButton = ({ member }: { member: Member }): JSX.Element => { const [busy, setBusy] = useState(false); return ( - { + { + ev.preventDefault(); if (busy) return; setBusy(true); await openDmForUser(cli, member); setBusy(false); }} - className="mx_UserInfo_field" disabled={busy} - > - {_t("common|message")} - + label={_t("user_info|send_message")} + Icon={ChatIcon} + /> ); }; export const UserOptionsSection: React.FC<{ member: Member; - isIgnored: boolean; canInvite: boolean; isSpace?: boolean; -}> = ({ member, isIgnored, canInvite, isSpace }) => { +}> = ({ member, canInvite, isSpace, children }) => { const cli = useContext(MatrixClientContext); - let ignoreButton: JSX.Element | undefined; let insertPillButton: JSX.Element | undefined; let inviteUserButton: JSX.Element | undefined; let readReceiptButton: JSX.Element | undefined; @@ -427,42 +438,9 @@ export const UserOptionsSection: React.FC<{ }); }; - const unignore = useCallback(() => { - const ignoredUsers = cli.getIgnoredUsers(); - const index = ignoredUsers.indexOf(member.userId); - if (index !== -1) ignoredUsers.splice(index, 1); - cli.setIgnoredUsers(ignoredUsers); - }, [cli, member]); - - const ignore = useCallback(async () => { - const name = (member instanceof User ? member.displayName : member.name) || member.userId; - const { finished } = Modal.createDialog(QuestionDialog, { - title: _t("user_info|ignore_confirm_title", { user: name }), - description:
    {_t("user_info|ignore_confirm_description")}
    , - button: _t("action|ignore"), - }); - const [confirmed] = await finished; - - if (confirmed) { - const ignoredUsers = cli.getIgnoredUsers(); - ignoredUsers.push(member.userId); - cli.setIgnoredUsers(ignoredUsers); - } - }, [cli, member]); - // Only allow the user to ignore the user if its not ourselves // same goes for jumping to read receipt if (!isMe) { - ignoreButton = ( - - {isIgnored ? _t("action|unignore") : _t("action|ignore")} - - ); - if (member instanceof RoomMember && member.roomId && !isSpace) { const onReadReceiptButton = function (): void { const room = cli.getRoom(member.roomId); @@ -487,16 +465,28 @@ export const UserOptionsSection: React.FC<{ const room = member instanceof RoomMember ? cli.getRoom(member.roomId) : undefined; if (room?.getEventReadUpTo(member.userId)) { readReceiptButton = ( - - {_t("user_info|jump_to_rr_button")} - + { + ev.preventDefault(); + onReadReceiptButton(); + }} + label={_t("user_info|jump_to_rr_button")} + Icon={CheckIcon} + /> ); } insertPillButton = ( - - {_t("action|mention")} - + { + ev.preventDefault(); + onInsertPillButton(); + }} + label={_t("action|mention")} + Icon={MentionIcon} + /> ); } @@ -507,7 +497,7 @@ export const UserOptionsSection: React.FC<{ shouldShowComponent(UIComponent.InviteUsers) ) { const roomId = member && member.roomId ? member.roomId : SdkContextClass.instance.roomViewStore.getRoomId(); - const onInviteUserButton = async (ev: ButtonEvent): Promise => { + const onInviteUserButton = async (ev: Event): Promise => { try { // We use a MultiInviter to re-use the invite logic, even though we're only inviting one user. const inviter = new MultiInviter(cli, roomId || ""); @@ -538,34 +528,43 @@ export const UserOptionsSection: React.FC<{ }; inviteUserButton = ( - - {_t("action|invite")} - + { + ev.preventDefault(); + onInviteUserButton(ev); + }} + label={_t("action|invite")} + Icon={InviteIcon} + /> ); } } const shareUserButton = ( - - {_t("user_info|share_button")} - + { + ev.preventDefault(); + onShareUserClick(); + }} + label={_t("user_info|share_button")} + Icon={ShareIcon} + /> ); const directMessageButton = isMe || !shouldShowComponent(UIComponent.CreateRooms) ? null : ; return ( -
    -

    {_t("common|options")}

    -
    - {directMessageButton} - {readReceiptButton} - {shareUserButton} - {insertPillButton} - {inviteUserButton} - {ignoreButton} -
    -
    + + {children} + {directMessageButton} + {inviteUserButton} + {readReceiptButton} + {shareUserButton} + {insertPillButton} + ); }; @@ -586,15 +585,10 @@ export const warnSelfDemote = async (isSpace: boolean): Promise => { return !!confirmed; }; -const GenericAdminToolsContainer: React.FC<{ +const Container: React.FC<{ children: ReactNode; }> = ({ children }) => { - return ( -
    -

    {_t("user_info|admin_tools_section")}

    -
    {children}
    -
    - ); + return
    {children}
    ; }; interface IPowerLevelsContent { @@ -756,14 +750,17 @@ export const RoomKickButton = ({ : _t("user_info|kick_button_room"); return ( - { + ev.preventDefault(); + onKick(); + }} disabled={isUpdating} - > - {kickLabel} - + label={kickLabel} + kind="critical" + Icon={LeaveIcon} + /> ); }; @@ -782,13 +779,16 @@ const RedactMessagesButton: React.FC = ({ member }) => { }; return ( - - {_t("user_info|redact_button")} - + { + ev.preventDefault(); + onRedactAllMessages(); + }} + label={_t("user_info|redact_button")} + kind="critical" + Icon={CloseIcon} + /> ); }; @@ -904,14 +904,18 @@ export const BanToggleButton = ({ label = room.isSpaceRoom() ? _t("user_info|unban_button_space") : _t("user_info|unban_button_room"); } - const classes = classNames("mx_UserInfo_field", { - mx_UserInfo_destructive: !isBanned, - }); - return ( - - {label} - + { + ev.preventDefault(); + onBanOrUnban(); + }} + disabled={isUpdating} + label={label} + kind="critical" + Icon={ChatProblemIcon} + /> ); }; @@ -981,15 +985,81 @@ const MuteToggleButton: React.FC = ({ }); }; - const classes = classNames("mx_UserInfo_field", { - mx_UserInfo_destructive: !muted, - }); - const muteLabel = muted ? _t("common|unmute") : _t("common|mute"); return ( - - {muteLabel} - + { + ev.preventDefault(); + onMuteToggle(); + }} + disabled={isUpdating} + label={muteLabel} + kind="critical" + Icon={VisibilityOffIcon} + /> + ); +}; + +const IgnoreToggleButton: React.FC<{ + member: User | RoomMember; +}> = ({ member }) => { + const cli = useContext(MatrixClientContext); + const unignore = useCallback(() => { + const ignoredUsers = cli.getIgnoredUsers(); + const index = ignoredUsers.indexOf(member.userId); + if (index !== -1) ignoredUsers.splice(index, 1); + cli.setIgnoredUsers(ignoredUsers); + }, [cli, member]); + + const ignore = useCallback(async () => { + const name = (member instanceof User ? member.displayName : member.name) || member.userId; + const { finished } = Modal.createDialog(QuestionDialog, { + title: _t("user_info|ignore_confirm_title", { user: name }), + description:
    {_t("user_info|ignore_confirm_description")}
    , + button: _t("action|ignore"), + }); + const [confirmed] = await finished; + + if (confirmed) { + const ignoredUsers = cli.getIgnoredUsers(); + ignoredUsers.push(member.userId); + cli.setIgnoredUsers(ignoredUsers); + } + }, [cli, member]); + + // Check whether the user is ignored + const [isIgnored, setIsIgnored] = useState(cli.isUserIgnored(member.userId)); + // Recheck if the user or client changes + useEffect(() => { + setIsIgnored(cli.isUserIgnored(member.userId)); + }, [cli, member.userId]); + // Recheck also if we receive new accountData m.ignored_user_list + const accountDataHandler = useCallback( + (ev) => { + if (ev.getType() === "m.ignored_user_list") { + setIsIgnored(cli.isUserIgnored(member.userId)); + } + }, + [cli, member.userId], + ); + useTypedEventEmitter(cli, ClientEvent.AccountData, accountDataHandler); + + return ( + { + ev.preventDefault(); + if (isIgnored) { + unignore(); + } else { + ignore(); + } + }} + label={isIgnored ? _t("user_info|unignore_button") : _t("user_info|ignore_button")} + kind="critical" + Icon={BlockIcon} + /> ); }; @@ -1070,13 +1140,13 @@ export const RoomAdminToolsContainer: React.FC = ({ if (kickButton || banButton || muteButton || redactButton || children) { return ( - + {muteButton} + {redactButton} {kickButton} {banButton} - {redactButton} {children} - + ); } @@ -1352,23 +1422,6 @@ const BasicUserInfo: React.FC<{ // Load whether or not we are a Synapse Admin const isSynapseAdmin = useIsSynapseAdmin(cli); - // Check whether the user is ignored - const [isIgnored, setIsIgnored] = useState(cli.isUserIgnored(member.userId)); - // Recheck if the user or client changes - useEffect(() => { - setIsIgnored(cli.isUserIgnored(member.userId)); - }, [cli, member.userId]); - // Recheck also if we receive new accountData m.ignored_user_list - const accountDataHandler = useCallback( - (ev) => { - if (ev.getType() === "m.ignored_user_list") { - setIsIgnored(cli.isUserIgnored(member.userId)); - } - }, - [cli, member.userId], - ); - useTypedEventEmitter(cli, ClientEvent.AccountData, accountDataHandler); - // Count of how many operations are currently in progress, if > 0 then show a Spinner const [pendingUpdateCount, setPendingUpdateCount] = useState(0); const startUpdating = useCallback(() => { @@ -1412,13 +1465,16 @@ const BasicUserInfo: React.FC<{ // someone does figure out how to bypass this check the worst that happens is an error. if (isSynapseAdmin && member.userId.endsWith(`:${cli.getDomain()}`)) { synapseDeactivateButton = ( - - {_t("user_info|deactivate_confirm_action")} - + { + ev.preventDefault(); + onSynapseDeactivate(); + }} + label={_t("user_info|deactivate_confirm_action")} + kind="critical" + Icon={DeleteIcon} + /> ); } @@ -1428,23 +1484,12 @@ const BasicUserInfo: React.FC<{ // hide the Roles section for DMs as it doesn't make sense there if (!DMRoomMap.shared().getUserIdForRoomId((member as RoomMember).roomId)) { memberDetails = ( -
    -

    - {_t( - "user_info|role_label", - {}, - { - RoomName: () => {room.name}, - }, - )} -

    - -
    + ); } @@ -1461,7 +1506,7 @@ const BasicUserInfo: React.FC<{ ); } else if (synapseDeactivateButton) { - adminToolsContainer = {synapseDeactivateButton}; + adminToolsContainer = {synapseDeactivateButton}; } if (pendingUpdateCount > 0) { @@ -1559,8 +1604,8 @@ const BasicUserInfo: React.FC<{ } const securitySection = ( -
    -

    {_t("common|security")}

    + +

    {_t("common|security")}

    {text}

    {verifyButton} {cryptoEnabled && ( @@ -1572,23 +1617,29 @@ const BasicUserInfo: React.FC<{ /> )} {editDevices} -
    + ); return ( - {memberDetails} - {securitySection} + + > + {memberDetails} + {adminToolsContainer} + {!isMe && ( + + + + )} + {spinner} ); @@ -1621,24 +1672,6 @@ export const UserInfoHeader: React.FC<{ const avatarUrl = (member as User).avatarUrl; - const avatarElement = ( -
    -
    -
    - -
    -
    -
    - ); - let presenceState: string | undefined; let presenceLastActiveAgo: number | undefined; let presenceCurrentlyActive: boolean | undefined; @@ -1661,36 +1694,52 @@ export const UserInfoHeader: React.FC<{ activeAgo={presenceLastActiveAgo} currentlyActive={presenceCurrentlyActive} presenceState={presenceState} + className="mx_UserInfo_profileStatus" + coloured /> ); } const e2eIcon = e2eStatus ? : null; - + const userIdentifier = UserIdentifierCustomisations.getDisplayUserIdentifier?.(member.userId, { + roomId, + withDisplayName: true, + }); const displayName = (member as RoomMember).rawDisplayName; return ( - {avatarElement} - -
    -
    -
    -

    - - {displayName} - - {e2eIcon} -

    +
    +
    +
    +
    -
    - {UserIdentifierCustomisations.getDisplayUserIdentifier?.(member.userId, { - roomId, - withDisplayName: true, - })} -
    -
    {presenceLabel}
    + + + + + + {displayName} + {e2eIcon} + + + {presenceLabel} + + userIdentifier} border={false}> + {userIdentifier} + + + + ); }; diff --git a/src/components/views/rooms/PresenceLabel.tsx b/src/components/views/rooms/PresenceLabel.tsx index 24e144c8ef..bdbc7e23e2 100644 --- a/src/components/views/rooms/PresenceLabel.tsx +++ b/src/components/views/rooms/PresenceLabel.tsx @@ -16,6 +16,7 @@ limitations under the License. import React from "react"; import { UnstableValue } from "matrix-js-sdk/src/NamespacedValue"; +import classNames from "classnames"; import { _t } from "../../../languageHandler"; import { formatDuration } from "../../../DateUtils"; @@ -31,6 +32,9 @@ interface IProps { currentlyActive?: boolean; // offline, online, etc presenceState?: string; + // whether to apply colouring to the label + coloured?: boolean; + className?: string; } export default class PresenceLabel extends React.Component { @@ -62,7 +66,11 @@ export default class PresenceLabel extends React.Component { public render(): React.ReactNode { return ( -
    +
    {this.getPrettyPresence(this.props.presenceState, this.props.activeAgo, this.props.currentlyActive)}
    ); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 3f71d4319b..03da4e7811 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -3770,6 +3770,7 @@ "error_revoke_3pid_invite_title": "Failed to revoke invite", "hide_sessions": "Hide sessions", "hide_verified_sessions": "Hide verified sessions", + "ignore_button": "Ignore", "ignore_confirm_description": "All messages and invites from this user will be hidden. Are you sure you want to ignore them?", "ignore_confirm_title": "Ignore %(user)s", "invited_by": "Invited by %(sender)s", @@ -3797,20 +3798,21 @@ "no_recent_messages_description": "Try scrolling up in the timeline to see if there are any earlier ones.", "no_recent_messages_title": "No recent messages by %(user)s found" }, - "redact_button": "Remove recent messages", + "redact_button": "Remove messages", "revoke_invite": "Revoke invite", - "role_label": "Role in ", "room_encrypted": "Messages in this room are end-to-end encrypted.", "room_encrypted_detail": "Your messages are secured and only you and the recipient have the unique keys to unlock them.", "room_unencrypted": "Messages in this room are not end-to-end encrypted.", "room_unencrypted_detail": "In encrypted rooms, your messages are secured and only you and the recipient have the unique keys to unlock them.", - "share_button": "Share Link to User", + "send_message": "Send message", + "share_button": "Share profile", "unban_button_room": "Unban from room", "unban_button_space": "Unban from space", "unban_room_confirm_title": "Unban from %(roomName)s", "unban_space_everything": "Unban them from everything I'm able to", "unban_space_specific": "Unban them from specific things I'm able to", "unban_space_warning": "They won't be able to access whatever you're not an admin of.", + "unignore_button": "Unignore", "verify_button": "Verify User", "verify_explainer": "For extra security, verify this user by checking a one-time code on both of your devices." }, diff --git a/test/components/views/right_panel/UserInfo-test.tsx b/test/components/views/right_panel/UserInfo-test.tsx index 6875bf227d..3b36468786 100644 --- a/test/components/views/right_panel/UserInfo-test.tsx +++ b/test/components/views/right_panel/UserInfo-test.tsx @@ -56,6 +56,9 @@ import { clearAllModals, flushPromises } from "../../../test-utils"; import ErrorDialog from "../../../../src/components/views/dialogs/ErrorDialog"; import { shouldShowComponent } from "../../../../src/customisations/helpers/UIComponents"; import { UIComponent } from "../../../../src/settings/UIFeature"; +import { Action } from "../../../../src/dispatcher/actions"; +import ShareDialog from "../../../../src/components/views/dialogs/ShareDialog"; +import BulkRedactDialog from "../../../../src/components/views/dialogs/BulkRedactDialog"; jest.mock("../../../../src/utils/direct-messages", () => ({ ...jest.requireActual("../../../../src/utils/direct-messages"), @@ -323,7 +326,7 @@ describe("", () => { , ); - screen.getByRole("button", { name: "Message" }); + screen.getByRole("button", { name: "Send message" }); }); it("hides the message button if the visibility customisation hides all create room features", () => { @@ -342,6 +345,64 @@ describe("", () => { }, ); }); + + describe("Ignore", () => { + const member = new RoomMember(defaultRoomId, defaultUserId); + + it("shows block button when member userId does not match client userId", () => { + // call to client.getUserId returns undefined, which will not match member.userId + renderComponent(); + + expect(screen.getByRole("button", { name: "Ignore" })).toBeInTheDocument(); + }); + + it("shows a modal before ignoring the user", async () => { + const originalCreateDialog = Modal.createDialog; + const modalSpy = (Modal.createDialog = jest.fn().mockReturnValue({ + finished: Promise.resolve([true]), + close: () => {}, + })); + + try { + mockClient.getIgnoredUsers.mockReturnValue([]); + renderComponent(); + + await userEvent.click(screen.getByRole("button", { name: "Ignore" })); + expect(modalSpy).toHaveBeenCalled(); + expect(mockClient.setIgnoredUsers).toHaveBeenLastCalledWith([member.userId]); + } finally { + Modal.createDialog = originalCreateDialog; + } + }); + + it("cancels ignoring the user", async () => { + const originalCreateDialog = Modal.createDialog; + const modalSpy = (Modal.createDialog = jest.fn().mockReturnValue({ + finished: Promise.resolve([false]), + close: () => {}, + })); + + try { + mockClient.getIgnoredUsers.mockReturnValue([]); + renderComponent(); + + await userEvent.click(screen.getByRole("button", { name: "Ignore" })); + expect(modalSpy).toHaveBeenCalled(); + expect(mockClient.setIgnoredUsers).not.toHaveBeenCalled(); + } finally { + Modal.createDialog = originalCreateDialog; + } + }); + + it("unignores the user", async () => { + mockClient.isUserIgnored.mockReturnValue(true); + mockClient.getIgnoredUsers.mockReturnValue([member.userId]); + renderComponent(); + + await userEvent.click(screen.getByRole("button", { name: "Unignore" })); + expect(mockClient.setIgnoredUsers).toHaveBeenCalledWith([]); + }); + }); }); describe("with crypto enabled", () => { @@ -801,7 +862,7 @@ describe("", () => { describe("", () => { const member = new RoomMember(defaultRoomId, defaultUserId); - const defaultProps = { member, isIgnored: false, canInvite: false, isSpace: false }; + const defaultProps = { member, canInvite: false, isSpace: false }; const renderComponent = (props = {}) => { const Wrapper = (wrapperProps = {}) => { @@ -828,9 +889,13 @@ describe("", () => { inviteSpy.mockRestore(); }); - it("always shows share user button", () => { + it("always shows share user button and clicking it should produce a ShareDialog", async () => { + const spy = jest.spyOn(Modal, "createDialog"); + renderComponent(); - expect(screen.getByRole("button", { name: /share link to user/i })).toBeInTheDocument(); + await userEvent.click(screen.getByRole("button", { name: "Share profile" })); + + expect(spy).toHaveBeenCalledWith(ShareDialog, { target: defaultProps.member }); }); it("does not show ignore or direct message buttons when member userId matches client userId", () => { @@ -842,20 +907,31 @@ describe("", () => { expect(screen.queryByRole("button", { name: /message/i })).not.toBeInTheDocument(); }); - it("shows ignore, direct message and mention buttons when member userId does not match client userId", () => { + it("shows direct message and mention buttons when member userId does not match client userId", () => { // call to client.getUserId returns undefined, which will not match member.userId renderComponent(); - expect(screen.getByRole("button", { name: /ignore/i })).toBeInTheDocument(); - expect(screen.getByRole("button", { name: /message/i })).toBeInTheDocument(); - expect(screen.getByRole("button", { name: /mention/i })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Send message" })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Mention" })).toBeInTheDocument(); + }); + + it("mention button fires ComposerInsert Action", async () => { + renderComponent(); + + const button = screen.getByRole("button", { name: "Mention" }); + await userEvent.click(button); + expect(dis.dispatch).toHaveBeenCalledWith({ + action: Action.ComposerInsert, + timelineRenderingType: "Room", + userId: "@user:example.com", + }); }); it("when call to client.getRoom is null, does not show read receipt button", () => { mockClient.getRoom.mockReturnValueOnce(null); renderComponent(); - expect(screen.queryByRole("button", { name: /jump to read receipt/i })).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Jump to read receipt" })).not.toBeInTheDocument(); }); it("when call to client.getRoom is non-null and room.getEventReadUpTo is null, does not show read receipt button", () => { @@ -863,7 +939,7 @@ describe("", () => { mockClient.getRoom.mockReturnValueOnce(mockRoom); renderComponent(); - expect(screen.queryByRole("button", { name: /jump to read receipt/i })).not.toBeInTheDocument(); + expect(screen.queryByRole("button", { name: "Jump to read receipt" })).not.toBeInTheDocument(); }); it("when calls to client.getRoom and room.getEventReadUpTo are non-null, shows read receipt button", () => { @@ -871,7 +947,7 @@ describe("", () => { mockClient.getRoom.mockReturnValueOnce(mockRoom); renderComponent(); - expect(screen.getByRole("button", { name: /jump to read receipt/i })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Jump to read receipt" })).toBeInTheDocument(); }); it("clicking the read receipt button calls dispatch with correct event_id", async () => { @@ -880,7 +956,7 @@ describe("", () => { mockClient.getRoom.mockReturnValue(mockRoom); renderComponent(); - const readReceiptButton = screen.getByRole("button", { name: /jump to read receipt/i }); + const readReceiptButton = screen.getByRole("button", { name: "Jump to read receipt" }); expect(readReceiptButton).toBeInTheDocument(); await userEvent.click(readReceiptButton); @@ -904,7 +980,7 @@ describe("", () => { mockClient.getRoom.mockReturnValue(mockRoom); renderComponent(); - const readReceiptButton = screen.getByRole("button", { name: /jump to read receipt/i }); + const readReceiptButton = screen.getByRole("button", { name: "Jump to read receipt" }); expect(readReceiptButton).toBeInTheDocument(); await userEvent.click(readReceiptButton); @@ -964,52 +1040,6 @@ describe("", () => { }); }); - it("shows a modal before ignoring the user", async () => { - const originalCreateDialog = Modal.createDialog; - const modalSpy = (Modal.createDialog = jest.fn().mockReturnValue({ - finished: Promise.resolve([true]), - close: () => {}, - })); - - try { - mockClient.getIgnoredUsers.mockReturnValue([]); - renderComponent({ isIgnored: false }); - - await userEvent.click(screen.getByRole("button", { name: "Ignore" })); - expect(modalSpy).toHaveBeenCalled(); - expect(mockClient.setIgnoredUsers).toHaveBeenLastCalledWith([member.userId]); - } finally { - Modal.createDialog = originalCreateDialog; - } - }); - - it("cancels ignoring the user", async () => { - const originalCreateDialog = Modal.createDialog; - const modalSpy = (Modal.createDialog = jest.fn().mockReturnValue({ - finished: Promise.resolve([false]), - close: () => {}, - })); - - try { - mockClient.getIgnoredUsers.mockReturnValue([]); - renderComponent({ isIgnored: false }); - - await userEvent.click(screen.getByRole("button", { name: "Ignore" })); - expect(modalSpy).toHaveBeenCalled(); - expect(mockClient.setIgnoredUsers).not.toHaveBeenCalled(); - } finally { - Modal.createDialog = originalCreateDialog; - } - }); - - it("unignores the user", async () => { - mockClient.getIgnoredUsers.mockReturnValue([member.userId]); - renderComponent({ isIgnored: true }); - - await userEvent.click(screen.getByRole("button", { name: "Unignore" })); - expect(mockClient.setIgnoredUsers).toHaveBeenCalledWith([]); - }); - it.each([ ["for a RoomMember", member, member.getMxcAvatarUrl()], ["for a User", defaultUser, defaultUser.avatarUrl], @@ -1020,10 +1050,10 @@ describe("", () => { mocked(startDmOnFirstMessage).mockReturnValue(deferred.promise); renderComponent({ member }); - await userEvent.click(screen.getByText("Message")); + await userEvent.click(screen.getByRole("button", { name: "Send message" })); // Checking the attribute, because the button is a DIV and toBeDisabled() does not work. - expect(screen.getByText("Message")).toHaveAttribute("disabled"); + expect(screen.getByRole("button", { name: "Send message" })).toBeDisabled(); expect(startDmOnFirstMessage).toHaveBeenCalledWith(mockClient, [ new DirectoryMember({ @@ -1039,7 +1069,7 @@ describe("", () => { }); // Checking the attribute, because the button is a DIV and toBeDisabled() does not work. - expect(screen.getByText("Message")).not.toHaveAttribute("disabled"); + expect(screen.getByRole("button", { name: "Send message" })).not.toBeDisabled(); }, ); }); @@ -1396,10 +1426,30 @@ describe("", () => { renderComponent({ member: defaultMemberWithPowerLevel }); - expect(screen.getByRole("heading", { name: /admin tools/i })).toBeInTheDocument(); - expect(screen.getByText(/disinvite from room/i)).toBeInTheDocument(); - expect(screen.getByText(/ban from room/i)).toBeInTheDocument(); - expect(screen.getByText(/remove recent messages/i)).toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Disinvite from room" })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Ban from room" })).toBeInTheDocument(); + expect(screen.getByRole("button", { name: "Remove messages" })).toBeInTheDocument(); + }); + + it("should show BulkRedactDialog upon clicking the Remove messages button", async () => { + const spy = jest.spyOn(Modal, "createDialog"); + + mockClient.getRoom.mockReturnValue(mockRoom); + mockClient.getUserId.mockReturnValue("@arbitraryId:server"); + const mockMeMember = new RoomMember(mockRoom.roomId, mockClient.getUserId()!); + mockMeMember.powerLevel = 51; // defaults to 50 + const defaultMemberWithPowerLevel = { ...defaultMember, powerLevel: 0 } as RoomMember; + mockRoom.getMember.mockImplementation((userId) => + userId === mockClient.getUserId() ? mockMeMember : defaultMemberWithPowerLevel, + ); + + renderComponent({ member: defaultMemberWithPowerLevel }); + await userEvent.click(screen.getByRole("button", { name: "Remove messages" })); + + expect(spy).toHaveBeenCalledWith( + BulkRedactDialog, + expect.objectContaining({ member: defaultMemberWithPowerLevel }), + ); }); it("returns mute toggle button if conditions met", () => { @@ -1441,10 +1491,9 @@ describe("", () => { isUpdating: true, }); - const button = screen.getByText(/mute/i); + const button = screen.getByRole("button", { name: "Mute" }); expect(button).toBeInTheDocument(); - expect(button).toHaveAttribute("disabled"); - expect(button).toHaveAttribute("aria-disabled", "true"); + expect(button).toBeDisabled(); }); it("should not show mute button for one's own member", () => { diff --git a/test/components/views/right_panel/__snapshots__/UserInfo-test.tsx.snap b/test/components/views/right_panel/__snapshots__/UserInfo-test.tsx.snap index c29ab8cee6..c82d72f917 100644 --- a/test/components/views/right_panel/__snapshots__/UserInfo-test.tsx.snap +++ b/test/components/views/right_panel/__snapshots__/UserInfo-test.tsx.snap @@ -118,7 +118,7 @@ exports[` with crypto enabled renders 1`] = ` data-testid="avatar-img" data-type="round" role="button" - style="--cpd-avatar-size: 230.39999999999998px;" + style="--cpd-avatar-size: 120px;" > u @@ -126,44 +126,51 @@ exports[` with crypto enabled renders 1`] = `
    -
    -

    - - @user:example.com - -

    -
    -
    - customUserIdentifier -
    -
    - Unknown + @user:example.com
    +

    +
    + Unknown
    +

    +

    + customUserIdentifier +
    +
    +

    -

    +

    Security -

    +

    Messages in this room are not end-to-end encrypted.

    @@ -201,32 +208,100 @@ exports[` with crypto enabled renders 1`] = `
    -

    - Options -

    -
    + + +
    +
    +
    + + +
    @@ -282,7 +357,7 @@ exports[` with crypto enabled should render a deactivate button for data-testid="avatar-img" data-type="round" role="button" - style="--cpd-avatar-size: 230.39999999999998px;" + style="--cpd-avatar-size: 120px;" > u @@ -290,44 +365,51 @@ exports[` with crypto enabled should render a deactivate button for
    -
    -

    - - @user:example.com - -

    -
    -
    - customUserIdentifier -
    -
    - Unknown + @user:example.com
    + +
    + Unknown
    +

    +

    + customUserIdentifier +
    +
    +

    -

    +

    Security -

    +

    Messages in this room are not end-to-end encrypted.

    @@ -365,50 +447,134 @@ exports[` with crypto enabled should render a deactivate button for
    -

    - Options -

    -
    + +
    + + +
    -

    - Admin Tools -

    -
    -
    + + + +
    +
    +
    From db4112122a74b427b1d0b25fba16b34823283445 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 19 Jul 2024 07:15:42 +0100 Subject: [PATCH 50/59] [create-pull-request] automated change (#12794) Co-authored-by: github-merge-queue --- src/i18n/strings/cs.json | 1 - src/i18n/strings/de_DE.json | 1 - src/i18n/strings/el.json | 1 - src/i18n/strings/eo.json | 1 - src/i18n/strings/es.json | 1 - src/i18n/strings/et.json | 1 - src/i18n/strings/fi.json | 1 - src/i18n/strings/fr.json | 1 - src/i18n/strings/gl.json | 1 - src/i18n/strings/he.json | 1 - src/i18n/strings/hu.json | 1 - src/i18n/strings/id.json | 1 - src/i18n/strings/is.json | 1 - src/i18n/strings/it.json | 1 - src/i18n/strings/ja.json | 1 - src/i18n/strings/lo.json | 1 - src/i18n/strings/lt.json | 1 - src/i18n/strings/nl.json | 1 - src/i18n/strings/pl.json | 27 ++++++++++++++------------- src/i18n/strings/pt_BR.json | 1 - src/i18n/strings/ru.json | 1 - src/i18n/strings/sk.json | 1 - src/i18n/strings/sq.json | 1 - src/i18n/strings/sv.json | 1 - 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 - 28 files changed, 14 insertions(+), 40 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index 7da68c59d3..b98bcc01ed 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3683,7 +3683,6 @@ }, "redact_button": "Odstranit nedávné zprávy", "revoke_invite": "Zrušit pozvání", - "role_label": "Role v ", "room_encrypted": "Zprávy jsou v této místnosti koncově šifrované.", "room_encrypted_detail": "Vaše zprávy jsou zabezpečené - pouze vy a jejich příjemci máte klíče potřebné k jejich přečtení.", "room_unencrypted": "Zprávy nejsou koncově šifrované.", diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 26ebeb05d6..4ac9291038 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3656,7 +3656,6 @@ }, "redact_button": "Kürzlich gesendete Nachrichten entfernen", "revoke_invite": "Einladung zurückziehen", - "role_label": "Rolle in ", "room_encrypted": "Nachrichten in diesem Raum sind Ende-zu-Ende verschlüsselt.", "room_encrypted_detail": "Diese Nachricht ist verschlüsselt. Nur Sie und der Empfänger haben den Schlüssel, um die Nachricht zu entschlüsseln.", "room_unencrypted": "Nachrichten in diesem Raum sind nicht Ende-zu-Ende verschlüsselt.", diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index 2cc7aeafee..d7ea9063ac 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -2967,7 +2967,6 @@ }, "redact_button": "Κατάργηση πρόσφατων μηνυμάτων", "revoke_invite": "Ανάκληση πρόσκλησης", - "role_label": "Ρόλος στο ", "room_encrypted": "Τα μηνύματα σε αυτό το δωμάτιο είναι κρυπτογραφημένα από άκρο σε άκρο.", "room_encrypted_detail": "Τα μηνύματά σας είναι ασφαλή και μόνο εσείς και ο παραλήπτης έχετε τα μοναδικά κλειδιά για να τα ξεκλειδώσετε.", "room_unencrypted": "Τα μηνύματα σε αυτό το δωμάτιο δεν είναι κρυπτογραφημένα από άκρο σε άκρο.", diff --git a/src/i18n/strings/eo.json b/src/i18n/strings/eo.json index acf1dcebb0..a7609450cf 100644 --- a/src/i18n/strings/eo.json +++ b/src/i18n/strings/eo.json @@ -2642,7 +2642,6 @@ }, "redact_button": "Forigi freŝajn mesaĝojn", "revoke_invite": "Nuligi inviton", - "role_label": "Rolo en ", "room_encrypted": "Mesaĝoj en ĉi tiu ĉambro estas tutvoje ĉifrataj.", "room_encrypted_detail": "Viaj mesaĝoj estas sekurigitaj, kaj nur vi kaj la ricevanto posedas la unikan ŝlosilojn, kiuj ilin povas malĉifri.", "room_unencrypted": "Mesaĝoj en ĉi tiu ĉambro ne estas tutvoje ĉifrataj.", diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index c3ff20c5a6..794ac603ba 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -3376,7 +3376,6 @@ }, "redact_button": "Eliminar mensajes recientes", "revoke_invite": "Revocar invitación", - "role_label": "Rol en ", "room_encrypted": "Los mensajes de esta sala están cifrados de extremo a extremo.", "room_encrypted_detail": "Los mensajes son seguros y sólo tú y el destinatario tienen las claves únicas para desbloquearlos.", "room_unencrypted": "Los mensajes en esta sala no están cifrados de extremo a extremo.", diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index f2cc8b6922..4c714a9949 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3621,7 +3621,6 @@ }, "redact_button": "Eemalda hiljutised sõnumid", "revoke_invite": "Tühista kutse", - "role_label": "Roll jututoas ", "room_encrypted": "See jututuba on läbivalt krüptitud.", "room_encrypted_detail": "Sinu sõnumid on turvatud ning ainult sinul ja saaja(te)l on unikaalsed võtmed selliste sõnumite lugemiseks.", "room_unencrypted": "See jututuba ei ole läbivalt krüptitud.", diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index e1976e1bff..177029d11b 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -3232,7 +3232,6 @@ }, "redact_button": "Poista viimeaikaiset viestit", "revoke_invite": "Kumoa kutsu", - "role_label": "Rooli huoneessa ", "room_encrypted": "Tämän huoneen viestit ovat päästä päähän -salattuja.", "room_encrypted_detail": "Viestisi ovat turvattu, ja vain sinulla ja vastaanottajalla on avaimet viestien lukemiseen.", "room_unencrypted": "Tämän huoneen viestit eivät ole päästä päähän -salattuja.", diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index 9a35bd7f85..a8df8fc902 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3717,7 +3717,6 @@ }, "redact_button": "Supprimer les messages récents", "revoke_invite": "Révoquer l’invitation", - "role_label": "Rôle dans ", "room_encrypted": "Les messages dans ce salon sont chiffrés de bout en bout.", "room_encrypted_detail": "Vos messages sont sécurisés et seuls vous et le destinataire avez les clés uniques pour les déchiffrer.", "room_unencrypted": "Les messages dans ce salon ne sont pas chiffrés de bout en bout.", diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 1c799134b9..99b4388671 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -3134,7 +3134,6 @@ }, "redact_button": "Eliminar mensaxes recentes", "revoke_invite": "Revogar convite", - "role_label": "Rol en ", "room_encrypted": "As mensaxes desta sala están cifradas de extremo-a-extremo.", "room_encrypted_detail": "As túas mensaxes están seguras e só ti e o correspondente tedes as únicas chaves que as desbloquean.", "room_unencrypted": "As mensaxes desta sala non están cifradas de extremo-a-extremo.", diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index 4cb91bc93e..4f8991ff6e 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -2508,7 +2508,6 @@ }, "redact_button": "הסר הודעות אחרונות", "revoke_invite": "שלול הזמנה", - "role_label": "תפקיד בחדר ", "room_encrypted": "ההודעות בחדר זה מוצפנות מקצה לקצה.", "room_encrypted_detail": "ההודעות שלך מאובטחות ורק לך ולמקבל יש את המפתחות הייחודיים לפתיחתן.", "room_unencrypted": "הודעות בחדר זה אינן מוצפנות מקצה לקצה.", diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 8c0b1fcbd2..526bd81639 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3592,7 +3592,6 @@ }, "redact_button": "Friss üzenetek törlése", "revoke_invite": "Meghívó visszavonása", - "role_label": "Szerep itt: ", "room_encrypted": "Az üzenetek a szobában végponttól végpontig titkosítottak.", "room_encrypted_detail": "Az üzenete biztonságban van, és csak Ön és a címzettek rendelkeznek a visszafejtéshez szükséges egyedi kulcsokkal.", "room_unencrypted": "Az üzenetek a szobában nincsenek végponttól végpontig titkosítva.", diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index 746f175216..79697d7dad 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -3626,7 +3626,6 @@ }, "redact_button": "Hapus pesan terkini", "revoke_invite": "Hapus undangan", - "role_label": "Peran di ", "room_encrypted": "Pesan di ruangan ini terenkripsi secara ujung ke ujung.", "room_encrypted_detail": "Pesan Anda diamankan dan hanya Anda dan penerimanya mempunyai kunci yang unik untuk mengaksesnya.", "room_unencrypted": "Pesan di ruangan ini tidak dienkripsi secara ujung ke ujung.", diff --git a/src/i18n/strings/is.json b/src/i18n/strings/is.json index af7c28014e..10c477173a 100644 --- a/src/i18n/strings/is.json +++ b/src/i18n/strings/is.json @@ -3020,7 +3020,6 @@ }, "redact_button": "Fjarlægja nýleg skilaboð", "revoke_invite": "Afturkalla boð", - "role_label": "Hlutverk í ", "room_encrypted": "Skilaboð í þessari spjallrás eru enda-í-enda dulrituð.", "room_encrypted_detail": "Öryggi skilaboðanna þinna er tryggt og einungis þú og viðtakendurnir hafa dulritunarlyklana til að opna skilaboðin.", "room_unencrypted": "Skilaboð í þessari spjallrás eru ekki enda-í-enda dulrituð.", diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index a5960e2d3a..c8a700b6e6 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -3676,7 +3676,6 @@ }, "redact_button": "Rimuovi i messaggi recenti", "revoke_invite": "Revoca invito", - "role_label": "Ruolo in ", "room_encrypted": "I messaggi in questa stanza sono cifrati end-to-end.", "room_encrypted_detail": "I tuoi messaggi sono protetti e solo tu ed il destinatario avete le chiavi univoche per sbloccarli.", "room_unencrypted": "I messaggi in questa stanza non sono cifrati end-to-end.", diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index 788e305fbb..e07756ffd1 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -3388,7 +3388,6 @@ }, "redact_button": "最近のメッセージを削除", "revoke_invite": "招待を取り消す", - "role_label": "での役割", "room_encrypted": "このルームのメッセージはエンドツーエンドで暗号化されています。", "room_encrypted_detail": "あなたのメッセージは保護されています。メッセージのロックを解除するための固有の鍵は、あなたと受信者だけが持っています。", "room_unencrypted": "このルームのメッセージはエンドツーエンドで暗号化されていません。", diff --git a/src/i18n/strings/lo.json b/src/i18n/strings/lo.json index 5cecf688f5..8cfe241876 100644 --- a/src/i18n/strings/lo.json +++ b/src/i18n/strings/lo.json @@ -2986,7 +2986,6 @@ }, "redact_button": "ລຶບຂໍ້ຄວາມຫຼ້າສຸດອອກ", "revoke_invite": "ຍົກເລີກຄຳເຊີນ", - "role_label": "ບົດບາດໃນ ", "room_encrypted": "ຂໍ້ຄວາມຢູ່ໃນຫ້ອງນີ້ຖືກເຂົ້າລະຫັດແບບຕົ້ນທາງຮອດປາຍທາງ.", "room_encrypted_detail": "ຂໍ້ຄວາມຂອງທ່ານປອດໄພ ແລະມີແຕ່ທ່ານ ແລະຜູ້ຮັບເທົ່ານັ້ນທີ່ມີກະແຈສະເພາະເພື່ອປົດລັອກພວກມັນ.", "room_unencrypted": "ຂໍ້ຄວາມຢູ່ໃນຫ້ອງນີ້ບໍ່ໄດ້ຖືກເຂົ້າລະຫັດແບບຕົ້ນທາງ-ປາຍທາງ.", diff --git a/src/i18n/strings/lt.json b/src/i18n/strings/lt.json index cd092b5cbf..e8cc6bc7eb 100644 --- a/src/i18n/strings/lt.json +++ b/src/i18n/strings/lt.json @@ -2398,7 +2398,6 @@ }, "redact_button": "Pašalinti paskutines žinutes", "revoke_invite": "Atšaukti kvietimą", - "role_label": "Rolė ", "room_encrypted": "Žinutės šiame kambaryje yra visapusiškai užšifruotos.", "room_encrypted_detail": "Jūsų žinutės yra apsaugotos ir tik jūs ir gavėjas turite unikalius raktus joms atrakinti.", "room_unencrypted": "Žinutės šiame kambaryje nėra visapusiškai užšifruotos.", diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index e09544f451..dbd0b4ddd3 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -3156,7 +3156,6 @@ }, "redact_button": "Recente berichten verwijderen", "revoke_invite": "Uitnodiging intrekken", - "role_label": "Rol in ", "room_encrypted": "De berichten in deze kamer worden eind-tot-eind-versleuteld.", "room_encrypted_detail": "Jouw berichten zijn beveiligd, en enkel de ontvanger en jij hebben de unieke sleutels om ze te ontsleutelen.", "room_unencrypted": "De berichten in deze kamer worden niet eind-tot-eind-versleuteld.", diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 82e2a50f7f..671ec8c738 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -221,7 +221,7 @@ "logout_dialog": { "description": "Czy na pewno chcesz się wylogować?", "megolm_export": "Ręcznie eksportuj klucze", - "setup_key_backup_title": "Utracisz dostęp do zaszyfrowanych wiadomości", + "setup_key_backup_title": "Utracisz dostęp do swoich wiadomości szyfrowanych", "setup_secure_backup_description_1": "Zaszyfrowane wiadomości są zabezpieczone przy użyciu szyfrowania end-to-end. Tylko Ty oraz ich adresaci posiadają klucze do ich rozszyfrowania.", "setup_secure_backup_description_2": "Po wylogowaniu, te klucze zostaną usunięte z urządzenia, co oznacza, że nie będziesz w stanie czytać wiadomości szyfrowanych, chyba że posiadasz je na swoich innych urządzeniach lub zapisałeś je na serwerze.", "skip_key_backup": "Nie chcę moich zaszyfrowanych wiadomości", @@ -568,7 +568,7 @@ "timeline": "Oś czasu", "trusted": "Zaufane", "unavailable": "niedostępne", - "unencrypted": "Nieszyfrowane", + "unencrypted": "Nieszyfrowany", "unmute": "Wyłącz wyciszenie", "unnamed_room": "Pokój bez nazwy", "unnamed_space": "Przestrzeń bez nazwy", @@ -632,7 +632,7 @@ "placeholder_thread": "Odpowiedz do wątku…", "placeholder_thread_encrypted": "Odpowiedz do wątku szyfrowanego…", "poll_button": "Ankieta", - "poll_button_no_perms_description": "Nie posiadasz uprawnień, aby rozpocząć ankiety w tym pokoju.", + "poll_button_no_perms_description": "Nie masz uprawnień do rozpoczęcia ankiety w tym pokoju", "poll_button_no_perms_title": "Wymagane Uprawnienia", "replying_title": "Odpowiadanie", "room_upgraded_link": "Konwersacja jest kontynuowana tutaj.", @@ -995,7 +995,7 @@ "prompt_unencrypted": "W pokojach szyfrowanych, zweryfikuj wszystkich użytkowników, aby upewnić się, że są bezpieczne.", "prompt_user": "Rozpocznij weryfikację ponownie z ich profilu.", "qr_or_sas": "%(qrCode)s lub %(emojiCompare)s", - "qr_or_sas_header": "Zweryfikuj to urządzenie wykonują jedno z następujących:", + "qr_or_sas_header": "Zweryfikuj to urządzenie wykonując jedno z następujących:", "qr_prompt": "Zeskanuj ten unikatowy kod", "qr_reciprocate_same_shield_device": "Prawie gotowe! Czy drugie urządzenie pokazuje tę samą tarczę?", "qr_reciprocate_same_shield_user": "Prawie gotowe! Czy %(displayName)s pokazuje tę samą tarczę?", @@ -1006,7 +1006,7 @@ "reset_proceed_prompt": "Zresetuj", "sas_caption_self": "Zweryfikuj to urządzenie, upewniając się że poniższy numer wyświetlony jest na jego ekranie.", "sas_caption_user": "Sprawdź tego użytkownika potwierdzając, że następujące liczby pojawiają się na ekranie rozmówcy.", - "sas_description": "Porównaj unikatowy zestaw emoji, jeżeli nie masz aparatu na jednym z urządzeń", + "sas_description": "Porównaj unikatowy zestaw emoji, jeżeli nie masz aparatu na którymś z urządzeń", "sas_emoji_caption_self": "Potwierdź że poniższe emotikony są wyświetlane na obu urządzeniach, w tej samej kolejności:", "sas_emoji_caption_user": "Sprawdź tego użytkownika potwierdzając, że następujące emotikony pojawiają się na ekranie rozmówcy.", "sas_match": "Pasują do siebie", @@ -1372,12 +1372,14 @@ "navigate_next_message_edit": "Przejdź do następnej wiadomości do edycji", "navigate_prev_history": "Poprzedni ostatnio odwiedzony pokój lub przestrzeń", "navigate_prev_message_edit": "Przejdź do poprzedniej wiadomości, aby ją edytować", + "next_landmark": "Przejdź do następnego punktu", "next_room": "Następny pokój lub wiadomość prywatna", "next_unread_room": "Następny nieodczytany pokój lub wiadomość prywatna", "number": "[liczba]", "open_user_settings": "Otwórz ustawienia użytkownika", "page_down": "Page Down", "page_up": "Page Up", + "prev_landmark": "Przejdź do poprzedniego punktu", "prev_room": "Poprzedni pokój lub wiadomość prywatna", "prev_unread_room": "Poprzedni nieodczytany pokój lub wiadomość prywatna", "room_list_collapse_section": "Zwiń sekcję listy pokojów", @@ -2108,7 +2110,7 @@ "one": "Pokaż %(count)s więcej", "other": "Pokaż %(count)s więcej" }, - "show_previews": "Pokazuj podglądy wiadomości", + "show_previews": "Pokazuj podgląd wiadomości", "sort_by": "Sortuj według", "sort_by_activity": "Aktywności", "sort_by_alphabet": "A-Z", @@ -2176,8 +2178,8 @@ "aliases_section": "Adresy pokoju", "avatar_field_label": "Awatar pokoju", "canonical_alias_field_label": "Główny adres", - "default_url_previews_off": "Podglądy linków są domyślnie wyłączone dla uczestników tego pokoju.", - "default_url_previews_on": "Podglądy linków są domyślnie włączone dla uczestników tego pokoju.", + "default_url_previews_off": "Podgląd linków są domyślnie wyłączone dla uczestników tego pokoju.", + "default_url_previews_on": "Podgląd linków są domyślnie włączone dla uczestników tego pokoju.", "description_space": "Edytuj ustawienia powiązane z twoją przestrzenią.", "error_creating_alias_description": "Wystąpił błąd podczas aktualizowania tego adresu. Serwer mógł odrzucić żądanie lub wystąpił błąd tymczasowy.", "error_creating_alias_title": "Wystąpił błąd podczas tworzenia adresu", @@ -2205,11 +2207,11 @@ "published_aliases_section": "Opublikowane adresy", "save": "Zapisz zmiany", "topic_field_label": "Temat pokoju", - "url_preview_encryption_warning": "W zaszyfrowanych pokojach, takich jak ten, podgląd adresów URL jest domyślnie wyłączony, aby upewnić się, że serwer (w którym generowane są podglądy) nie może zbierać informacji o linkach widocznych w tym pokoju.", + "url_preview_encryption_warning": "W pokojach szyfrowanych, takich jak ten, podgląd adresów URL jest domyślnie wyłączony, aby upewnić się, że serwer (na którym generowane są podglądy) nie może zbierać informacji o linkach, które widzisz w pokoju.", "url_preview_explainer": "Gdy ktoś umieści URL w wiadomości, można wyświetlić podgląd adresu URL, aby podać więcej informacji o tym łączu, takich jak tytuł, opis i obraz ze strony internetowej.", - "url_previews_section": "Podglądy linków", - "user_url_previews_default_off": "Masz domyślnie
    wyłączone podglądy linków.", - "user_url_previews_default_on": "Masz domyślnie włączone podglądy linków." + "url_previews_section": "Podgląd linków", + "user_url_previews_default_off": "Podgląd linków jest domyślnie wyłączony.", + "user_url_previews_default_on": "Podgląd linków jest domyślnie włączony." }, "notifications": { "browse_button": "Przeglądaj", @@ -3800,7 +3802,6 @@ }, "redact_button": "Usuń ostatnie wiadomości", "revoke_invite": "Odwołaj zaproszenie", - "role_label": "Role w ", "room_encrypted": "Wiadomości w tym pokoju są szyfrowane end-to-end.", "room_encrypted_detail": "Twoje wiadomości są zabezpieczone i tylko Ty i Twój odbiorca posiadacie unikalne klucze, aby je odblokować.", "room_unencrypted": "Wiadomości w tym pokoju nie są szyfrowane end-to-end.", diff --git a/src/i18n/strings/pt_BR.json b/src/i18n/strings/pt_BR.json index 61c632dddf..8dc2d3567c 100644 --- a/src/i18n/strings/pt_BR.json +++ b/src/i18n/strings/pt_BR.json @@ -2550,7 +2550,6 @@ }, "redact_button": "Apagar mensagens desta pessoa na sala", "revoke_invite": "Revogar o convite", - "role_label": "Cargo em ", "room_encrypted": "As mensagens nesta sala estão criptografadas de ponta a ponta.", "room_encrypted_detail": "Suas mensagens são protegidas e somente você e o destinatário têm as chaves exclusivas para desbloqueá-las.", "room_unencrypted": "As mensagens nesta sala não estão criptografadas de ponta a ponta.", diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 37beb7194a..79afe8b52a 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -3659,7 +3659,6 @@ }, "redact_button": "Удалить последние сообщения", "revoke_invite": "Отозвать приглашение", - "role_label": "Роль в ", "room_encrypted": "Сообщения в этой комнате защищены сквозным шифрованием.", "room_encrypted_detail": "Ваши сообщения в безопасности, ключи для расшифровки есть только у вас и получателя.", "room_unencrypted": "Сообщения в этой комнате не защищены сквозным шифрованием.", diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index a8afeae2d6..e4bec50287 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -3689,7 +3689,6 @@ }, "redact_button": "Odstrániť posledné správy", "revoke_invite": "Odvolať pozvánku", - "role_label": "Rola v ", "room_encrypted": "Správy v tejto miestnosti sú šifrované od vás až k príjemcovi.", "room_encrypted_detail": "Vaše správy sú zabezpečené a jedinečné kľúče na ich odomknutie máte len vy a príjemca.", "room_unencrypted": "Správy v tejto miestnosti nie sú šifrované od vás až k príjemcovi.", diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index ab55e38ce4..6563ee0fd1 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -3451,7 +3451,6 @@ }, "redact_button": "Hiq mesazhe së fundi", "revoke_invite": "Shfuqizoje ftesën", - "role_label": "Rol në ", "room_encrypted": "Mesazhet në këtë dhomë janë të fshehtëzuara skaj-më-skaj.", "room_encrypted_detail": "Mesazhet tuaj janë të sigurt dhe vetëm ju dhe marrësi kanë kyçet unikë për t’i shkyçur.", "room_unencrypted": "Mesazhet në këtë dhomë nuk janë të fshehtëzuara skaj-më-skaj.", diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 77fe12ee6e..8e10fa33ac 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -3675,7 +3675,6 @@ }, "redact_button": "Ta bort nyliga meddelanden", "revoke_invite": "Återkalla inbjudan", - "role_label": "Roll i ", "room_encrypted": "Meddelanden i det här rummet är totalsträckskrypterade.", "room_encrypted_detail": "Dina meddelanden är säkrade och endast du och mottagaren har de unika nycklarna för att låsa upp dem.", "room_unencrypted": "Meddelanden i detta rum är inte totalsträckskrypterade.", diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 1f3279ed9d..53300cf08c 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -3586,7 +3586,6 @@ }, "redact_button": "Видалити останні повідомлення", "revoke_invite": "Відкликати запрошення", - "role_label": "Роль у ", "room_encrypted": "Повідомлення у цій кімнаті захищено наскрізним шифруванням.", "room_encrypted_detail": "Ваші повідомлення захищені. Лише ви з отримувачем маєте унікальні ключі їхнього розшифрування.", "room_unencrypted": "Повідомлення у цій кімнаті не захищено наскрізним шифруванням.", diff --git a/src/i18n/strings/vi.json b/src/i18n/strings/vi.json index a3e2488cdb..7abc70dedc 100644 --- a/src/i18n/strings/vi.json +++ b/src/i18n/strings/vi.json @@ -3298,7 +3298,6 @@ }, "redact_button": "Bỏ các tin nhắn gần đây", "revoke_invite": "Thu hồi lời mời", - "role_label": "Vai trò trong ", "room_encrypted": "Tin nhắn trong phòng này đang được mã hóa đầu cuối.", "room_encrypted_detail": "Tin nhắn của bạn được bảo mật và chỉ bạn và người nhận mới có chìa khóa duy nhất để mở khóa.", "room_unencrypted": "Tin nhắn trong phòng này không được mã hóa đầu cuối.", diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index 77dc330ef1..8457984941 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -3292,7 +3292,6 @@ }, "redact_button": "移除最近消息", "revoke_invite": "撤销邀请", - "role_label": " 中的角色", "room_encrypted": "此房间内的消息端到端加密。", "room_encrypted_detail": "你的消息是安全的,只有你和接收者有解开它们的唯一密钥。", "room_unencrypted": "此房间内的消息未端到端加密。", diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index f4ab63d787..57b31e1769 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3577,7 +3577,6 @@ }, "redact_button": "移除最近的訊息", "revoke_invite": "撤銷邀請", - "role_label": " 中的角色", "room_encrypted": "此聊天室內的訊息有端對端加密。", "room_encrypted_detail": "您的訊息已受保護,只有您與收件人才有獨特的金鑰將其解鎖。", "room_unencrypted": "此聊天室內的訊息未經端到端加密。", From d202295015fbd127852befbab8688fa76abdac0d Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Fri, 19 Jul 2024 07:20:58 +0100 Subject: [PATCH 51/59] [create-pull-request] automated change (#12795) 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 3b63306ecb..8d474d9fe9 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:1e71b0a038807a93d586f0624c6db2b49eeff371765d2f2abb240cdad1c246cb"; +const DOCKER_TAG = "develop@sha256:ee66fc1ebbf15f9dde375cdb2afd544491b88b81ac3c82e6c4282bc3b7f332bc"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From 0fc1c53a8e4e62e7c60128a9eab63401a446293a Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Fri, 19 Jul 2024 18:17:40 +0100 Subject: [PATCH 52/59] Iterate design of right panel empty state (#12796) * Add reusable empty state for the right panel Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve coverage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- playwright/e2e/right-panel/file-panel.spec.ts | 2 +- .../right-panel/notification-panel.spec.ts | 2 +- .../e2e/right-panel/right-panel.spec.ts | 2 +- .../file-panel.spec.ts/empty-linux.png | Bin 9580 -> 72623 bytes .../empty-linux.png | Bin 9062 -> 71187 bytes res/css/_components.pcss | 2 +- res/css/structures/_FilePanel.pcss | 4 - res/css/structures/_NotificationPanel.pcss | 19 --- res/css/structures/_RightPanel.pcss | 27 ---- res/css/views/right_panel/_EmptyState.pcss | 45 +++++++ res/css/views/right_panel/_ThreadPanel.pcss | 75 ++--------- src/components/structures/FilePanel.tsx | 11 +- .../structures/NotificationPanel.tsx | 11 +- src/components/structures/ThreadPanel.tsx | 119 +++++------------- .../views/right_panel/EmptyState.tsx | 42 +++++++ src/i18n/strings/en_EN.json | 7 +- test/components/structures/FilePanel-test.tsx | 58 +++++++++ .../structures/ThreadPanel-test.tsx | 47 +------ .../__snapshots__/FilePanel-test.tsx.snap | 58 +++++++++ .../__snapshots__/ThreadPanel-test.tsx.snap | 14 --- test/test-utils/test-utils.ts | 1 + 21 files changed, 266 insertions(+), 280 deletions(-) delete mode 100644 res/css/structures/_NotificationPanel.pcss create mode 100644 res/css/views/right_panel/_EmptyState.pcss create mode 100644 src/components/views/right_panel/EmptyState.tsx create mode 100644 test/components/structures/FilePanel-test.tsx create mode 100644 test/components/structures/__snapshots__/FilePanel-test.tsx.snap diff --git a/playwright/e2e/right-panel/file-panel.spec.ts b/playwright/e2e/right-panel/file-panel.spec.ts index 84e7614e8e..52dd113314 100644 --- a/playwright/e2e/right-panel/file-panel.spec.ts +++ b/playwright/e2e/right-panel/file-panel.spec.ts @@ -50,7 +50,7 @@ test.describe("FilePanel", () => { test.describe("render", () => { test("should render empty state", async ({ page }) => { // Wait until the information about the empty state is rendered - await expect(page.locator(".mx_FilePanel_empty")).toBeVisible(); + await expect(page.locator(".mx_EmptyState")).toBeVisible(); // Take a snapshot of RightPanel - fix https://github.com/vector-im/element-web/issues/25332 await expect(page.locator(".mx_RightPanel")).toMatchScreenshot("empty.png"); diff --git a/playwright/e2e/right-panel/notification-panel.spec.ts b/playwright/e2e/right-panel/notification-panel.spec.ts index 6223c1c13f..aa7dedf73a 100644 --- a/playwright/e2e/right-panel/notification-panel.spec.ts +++ b/playwright/e2e/right-panel/notification-panel.spec.ts @@ -35,7 +35,7 @@ test.describe("NotificationPanel", () => { await page.getByRole("button", { name: "Notifications" }).click(); // Wait until the information about the empty state is rendered - await expect(page.locator(".mx_NotificationPanel_empty")).toBeVisible(); + await expect(page.locator(".mx_EmptyState")).toBeVisible(); // Take a snapshot of RightPanel await expect(page.locator(".mx_RightPanel")).toMatchScreenshot("empty.png"); diff --git a/playwright/e2e/right-panel/right-panel.spec.ts b/playwright/e2e/right-panel/right-panel.spec.ts index 51ebb3df92..632f709245 100644 --- a/playwright/e2e/right-panel/right-panel.spec.ts +++ b/playwright/e2e/right-panel/right-panel.spec.ts @@ -104,7 +104,7 @@ test.describe("RightPanel", () => { await page.getByRole("menuitem", { name: "Files" }).click(); await expect(page.locator(".mx_FilePanel")).toBeVisible(); - await expect(page.locator(".mx_FilePanel_empty")).toBeVisible(); + await expect(page.locator(".mx_EmptyState")).toBeVisible(); await page.getByTestId("base-card-back-button").click(); await checkRoomSummaryCard(page, ROOM_NAME); diff --git a/playwright/snapshots/right-panel/file-panel.spec.ts/empty-linux.png b/playwright/snapshots/right-panel/file-panel.spec.ts/empty-linux.png index fb6d85ae521f6ff6eda86046b35507793a4d4eff..fdbec37b706fab051803a93b04224e39ca319c4f 100644 GIT binary patch literal 72623 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

    #|E`M^qtu(z^JcPN#~H} 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 bqbmOg<{5$)1_|T@00000NkvXXu0mjfs-S+u literal 9580 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 diff --git a/playwright/snapshots/right-panel/notification-panel.spec.ts/empty-linux.png b/playwright/snapshots/right-panel/notification-panel.spec.ts/empty-linux.png index 5547e7621b6bad765157cee5b62ae8a8c33f1ef5..d18266534def039cadcfe80380451f6e6607b95c 100644 GIT binary patch literal 71187 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

    !>v0 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 literal 9062 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 b { - font-weight: var(--cpd-font-weight-semibold); - } - } -} - -.mx_ThreadPanel_largeIcon { - width: 28px; - height: 28px; - padding: 18px; - background: $system; - border-radius: 50%; - - &::after { - @mixin ThreadSummaryIcon; - width: inherit; - height: inherit; - } -} - .mx_ContextualMenu_wrapper { .mx_ThreadPanel_Header_FilterOptionItem { display: flex; diff --git a/src/components/structures/FilePanel.tsx b/src/components/structures/FilePanel.tsx index 3836863431..c4bf2c3ff7 100644 --- a/src/components/structures/FilePanel.tsx +++ b/src/components/structures/FilePanel.tsx @@ -28,6 +28,7 @@ import { TimelineWindow, } from "matrix-js-sdk/src/matrix"; import { logger } from "matrix-js-sdk/src/logger"; +import { Icon as FilesIcon } from "@vector-im/compound-design-tokens/icons/files.svg"; import { MatrixClientPeg } from "../../MatrixClientPeg"; import EventIndexPeg from "../../indexing/EventIndexPeg"; @@ -40,6 +41,7 @@ import Spinner from "../views/elements/Spinner"; import { Layout } from "../../settings/enums/Layout"; import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext"; import Measured from "../views/elements/Measured"; +import EmptyState from "../views/right_panel/EmptyState"; interface IProps { roomId: string; @@ -255,10 +257,11 @@ class FilePanel extends React.Component { // wrap a TimelinePanel with the jump-to-event bits turned off. const emptyState = ( -

    -

    {_t("file_panel|empty_heading")}

    -

    {_t("file_panel|empty_description")}

    -
    + ); const isRoomEncrypted = this.noRoom ? false : MatrixClientPeg.safeGet().isRoomEncrypted(this.props.roomId); diff --git a/src/components/structures/NotificationPanel.tsx b/src/components/structures/NotificationPanel.tsx index 0da27a19b1..9c56da9609 100644 --- a/src/components/structures/NotificationPanel.tsx +++ b/src/components/structures/NotificationPanel.tsx @@ -16,6 +16,7 @@ limitations under the License. import React from "react"; import { logger } from "matrix-js-sdk/src/logger"; +import { Icon as NotificationsIcon } from "@vector-im/compound-design-tokens/icons/notifications.svg"; import { _t } from "../../languageHandler"; import { MatrixClientPeg } from "../../MatrixClientPeg"; @@ -26,6 +27,7 @@ import { Layout } from "../../settings/enums/Layout"; import RoomContext, { TimelineRenderingType } from "../../contexts/RoomContext"; import Measured from "../views/elements/Measured"; import Heading from "../views/typography/Heading"; +import EmptyState from "../views/right_panel/EmptyState"; interface IProps { onClose(): void; @@ -57,10 +59,11 @@ export default class NotificationPanel extends React.PureComponent -

    {_t("notif_panel|empty_heading")}

    -

    {_t("notif_panel|empty_description")}

    -
    + ); let content: JSX.Element; diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index d9e1cf2aa8..7c7761368d 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -19,6 +19,7 @@ import React, { useContext, useEffect, useRef, useState } from "react"; import { EventTimelineSet, Room, Thread } from "matrix-js-sdk/src/matrix"; import { IconButton, Tooltip } from "@vector-im/compound-web"; import { logger } from "matrix-js-sdk/src/logger"; +import { Icon as ThreadsIcon } from "@vector-im/compound-design-tokens/icons/threads.svg"; import { Icon as MarkAllThreadsReadIcon } from "../../../res/img/element-icons/check-all.svg"; import BaseCard from "../views/right_panel/BaseCard"; @@ -37,6 +38,7 @@ import { ButtonEvent } from "../views/elements/AccessibleButton"; import Spinner from "../views/elements/Spinner"; import Heading from "../views/typography/Heading"; import { clearRoomNotification } from "../../utils/notifications"; +import EmptyState from "../views/right_panel/EmptyState"; interface IProps { roomId: string; @@ -73,8 +75,7 @@ export const ThreadPanelHeaderFilterOptionItem: React.FC< export const ThreadPanelHeader: React.FC<{ filterOption: ThreadFilterType; setFilterOption: (filterOption: ThreadFilterType) => void; - empty: boolean; -}> = ({ filterOption, setFilterOption, empty }) => { +}> = ({ filterOption, setFilterOption }) => { const mxClient = useMatrixClientContext(); const roomContext = useRoomContext(); const [menuDisplayed, button, openMenu, closeMenu] = useContextMenu(); @@ -140,86 +141,24 @@ export const ThreadPanelHeader: React.FC<{ {_t("common|threads")} - {!empty && ( - <> - - - - - -
    - { - openMenu(); - PosthogTrackers.trackInteraction("WebRightPanelThreadPanelFilterDropdown", ev); - }} - > - {`${_t("threads|show_thread_filter")} ${value?.label}`} - - {contextMenu} - - )} -
    - ); -}; - -interface EmptyThreadIProps { - hasThreads: boolean; - filterOption: ThreadFilterType; - showAllThreadsCallback: () => void; -} - -const EmptyThread: React.FC = ({ hasThreads, filterOption, showAllThreadsCallback }) => { - let body: JSX.Element; - if (hasThreads) { - body = ( - <> -

    - {_t("threads|empty_has_threads_tip", { - replyInThread: _t("action|reply_in_thread"), - })} -

    -

    - {/* Always display that paragraph to prevent layout shift when hiding the button */} - {filterOption === ThreadFilterType.My ? ( - - ) : ( - <>  - )} -

    - - ); - } else { - body = ( - <> -

    {_t("threads|empty_explainer")}

    -

    - {_t( - "threads|empty_tip", - { - replyInThread: _t("action|reply_in_thread"), - }, - { - b: (sub) => {sub}, - }, - )} -

    - - ); - } - - return ( -
    -
    -

    {_t("threads|empty_heading")}

    - {body} + + + + + +
    + { + openMenu(); + PosthogTrackers.trackInteraction("WebRightPanelThreadPanelFilterDropdown", ev); + }} + > + {`${_t("threads|show_thread_filter")} ${value?.label}`} + + {contextMenu}
    ); }; @@ -268,11 +207,7 @@ const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => + hasThreads && } id="thread-panel" className="mx_ThreadPanel" @@ -295,10 +230,12 @@ const ThreadPanel: React.FC = ({ roomId, onClose, permalinkCreator }) => timelineSet={timelineSet} showUrlPreview={false} // No URL previews at the threads list level empty={ - setFilterOption(ThreadFilterType.All)} + } alwaysShowTimestamps={true} diff --git a/src/components/views/right_panel/EmptyState.tsx b/src/components/views/right_panel/EmptyState.tsx new file mode 100644 index 0000000000..7189cb8b3a --- /dev/null +++ b/src/components/views/right_panel/EmptyState.tsx @@ -0,0 +1,42 @@ +/* +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, { ComponentType } from "react"; +import { Text } from "@vector-im/compound-web"; + +import { Flex } from "../../utils/Flex"; + +interface Props { + Icon: ComponentType>; + title: string; + description: string; +} + +const EmptyState: React.FC = ({ Icon, title, description }) => { + return ( + + + + {title} + + + {description} + + + ); +}; + +export default EmptyState; diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 03da4e7811..12ad79607d 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -3193,16 +3193,13 @@ "one": "%(count)s reply", "other": "%(count)s replies" }, - "empty_explainer": "Threads help keep your conversations on-topic and easy to track.", - "empty_has_threads_tip": "Reply to an ongoing thread or use “%(replyInThread)s” when hovering over a message to start a new one.", - "empty_heading": "Keep discussions organised with threads", - "empty_tip": "Tip: Use “%(replyInThread)s” when hovering over a message.", + "empty_description": "Use “%(replyInThread)s” when hovering over a message.", + "empty_title": "Threads help keep your conversations on-topic and easy to track.", "error_start_thread_existing_relation": "Can't create a thread from an event with an existing relation", "mark_all_read": "Mark all as read", "my_threads": "My threads", "my_threads_description": "Shows all threads you've participated in", "open_thread": "Open thread", - "show_all_threads": "Show all threads", "show_thread_filter": "Show:" }, "threads_activity_centre": { diff --git a/test/components/structures/FilePanel-test.tsx b/test/components/structures/FilePanel-test.tsx new file mode 100644 index 0000000000..2b53c9c86c --- /dev/null +++ b/test/components/structures/FilePanel-test.tsx @@ -0,0 +1,58 @@ +/* +Copyright 2024 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import React from "react"; +import { EventTimelineSet, PendingEventOrdering, Room } from "matrix-js-sdk/src/matrix"; +import { screen, render, waitFor } from "@testing-library/react"; +import { mocked } from "jest-mock"; + +import FilePanel from "../../../src/components/structures/FilePanel"; +import ResizeNotifier from "../../../src/utils/ResizeNotifier"; +import { stubClient } from "../../test-utils"; +import { MatrixClientPeg } from "../../../src/MatrixClientPeg"; + +jest.mock("matrix-js-sdk/src/matrix", () => ({ + ...jest.requireActual("matrix-js-sdk/src/matrix"), + TimelineWindow: jest.fn().mockReturnValue({ + load: jest.fn().mockResolvedValue(null), + getEvents: jest.fn().mockReturnValue([]), + canPaginate: jest.fn().mockReturnValue(false), + }), +})); + +describe("FilePanel", () => { + beforeEach(() => { + stubClient(); + }); + + it("renders empty state", async () => { + const cli = MatrixClientPeg.safeGet(); + const room = new Room("!room:server", cli, cli.getSafeUserId(), { + pendingEventOrdering: PendingEventOrdering.Detached, + }); + const timelineSet = new EventTimelineSet(room); + room.getOrCreateFilteredTimelineSet = jest.fn().mockReturnValue(timelineSet); + mocked(cli.getRoom).mockReturnValue(room); + + const { asFragment } = render( + , + ); + await waitFor(() => { + expect(screen.getByText("No files visible in this room")).toBeInTheDocument(); + }); + expect(asFragment()).toMatchSnapshot(); + }); +}); diff --git a/test/components/structures/ThreadPanel-test.tsx b/test/components/structures/ThreadPanel-test.tsx index 19122e4cce..f66f58ed84 100644 --- a/test/components/structures/ThreadPanel-test.tsx +++ b/test/components/structures/ThreadPanel-test.tsx @@ -43,44 +43,21 @@ describe("ThreadPanel", () => { describe("Header", () => { it("expect that All filter for ThreadPanelHeader properly renders Show: All threads", () => { const { asFragment } = render( - undefined} - />, + undefined} />, ); expect(asFragment()).toMatchSnapshot(); }); it("expect that My filter for ThreadPanelHeader properly renders Show: My threads", () => { const { asFragment } = render( - undefined} - />, - ); - expect(asFragment()).toMatchSnapshot(); - }); - - it("matches snapshot when no threads", () => { - const { asFragment } = render( - undefined} - />, + undefined} />, ); expect(asFragment()).toMatchSnapshot(); }); it("expect that ThreadPanelHeader properly opens a context menu when clicked on the button", () => { const { container } = render( - undefined} - />, + undefined} />, ); const found = container.querySelector(".mx_ThreadPanel_dropdown"); expect(found).toBeTruthy(); @@ -91,11 +68,7 @@ describe("ThreadPanel", () => { it("expect that ThreadPanelHeader has the correct option selected in the context menu", () => { const { container } = render( - undefined} - />, + undefined} />, ); fireEvent.click(container.querySelector(".mx_ThreadPanel_dropdown")!); const found = screen.queryAllByRole("menuitemradio"); @@ -118,11 +91,7 @@ describe("ThreadPanel", () => { const { container } = render( - undefined} - /> + undefined} /> , ); @@ -136,11 +105,7 @@ describe("ThreadPanel", () => { const mockClient = createTestClient(); const { container } = render( - undefined} - /> + undefined} /> , ); fireEvent.click(getByRole(container, "button", { name: "Mark all as read" })); diff --git a/test/components/structures/__snapshots__/FilePanel-test.tsx.snap b/test/components/structures/__snapshots__/FilePanel-test.tsx.snap new file mode 100644 index 0000000000..87ffc5da2e --- /dev/null +++ b/test/components/structures/__snapshots__/FilePanel-test.tsx.snap @@ -0,0 +1,58 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`FilePanel renders empty state 1`] = ` + +
    +
    +
    + +
    +
    +
    +
    +
    +

    + No files visible in this room +

    +

    + Attach files from chat or just drag and drop them anywhere in a room. +

    +
    +
    +
    +
    + +`; diff --git a/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap b/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap index 09bf4ae39b..0a219b8403 100644 --- a/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap +++ b/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap @@ -95,17 +95,3 @@ exports[`ThreadPanel Header expect that ThreadPanelHeader has the correct option
    `; - -exports[`ThreadPanel Header matches snapshot when no threads 1`] = ` - -
    -

    - Threads -

    -
    -
    -`; diff --git a/test/test-utils/test-utils.ts b/test/test-utils/test-utils.ts index 5370f72b18..856d9b17b7 100644 --- a/test/test-utils/test-utils.ts +++ b/test/test-utils/test-utils.ts @@ -274,6 +274,7 @@ export function createTestClient(): MatrixClient { matrixRTC: createStubMatrixRTC(), isFallbackICEServerAllowed: jest.fn().mockReturnValue(false), getAuthIssuer: jest.fn(), + getOrCreateFilter: jest.fn(), } as unknown as MatrixClient; client.reEmitter = new ReEmitter(client); From 18398951b4da2022d24f88e708266cd463f64d73 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Sat, 20 Jul 2024 07:21:04 +0100 Subject: [PATCH 53/59] [create-pull-request] automated change (#12799) 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 8d474d9fe9..b62c737645 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:ee66fc1ebbf15f9dde375cdb2afd544491b88b81ac3c82e6c4282bc3b7f332bc"; +const DOCKER_TAG = "develop@sha256:14ca769c834220a478a1e97df041361c6fb0a541ccb2f0666d3ce911224f5f7e"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From 62c56255fc8272a6fac0a0feec734cb6d8a38e55 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Mon, 22 Jul 2024 07:15:11 +0100 Subject: [PATCH 54/59] [create-pull-request] automated change (#12800) Co-authored-by: github-merge-queue --- src/i18n/strings/cs.json | 5 ----- src/i18n/strings/de_DE.json | 5 ----- src/i18n/strings/el.json | 4 ---- src/i18n/strings/es.json | 5 ----- src/i18n/strings/et.json | 5 ----- src/i18n/strings/fi.json | 3 --- src/i18n/strings/fr.json | 5 ----- src/i18n/strings/gl.json | 5 ----- src/i18n/strings/he.json | 5 ----- src/i18n/strings/hu.json | 5 ----- src/i18n/strings/id.json | 5 ----- src/i18n/strings/is.json | 3 --- src/i18n/strings/it.json | 5 ----- src/i18n/strings/ja.json | 5 ----- src/i18n/strings/lo.json | 5 ----- src/i18n/strings/nl.json | 5 ----- src/i18n/strings/pl.json | 5 ----- src/i18n/strings/ru.json | 5 ----- src/i18n/strings/sk.json | 5 ----- src/i18n/strings/sq.json | 5 ----- src/i18n/strings/sv.json | 5 ----- src/i18n/strings/uk.json | 5 ----- src/i18n/strings/vi.json | 2 -- src/i18n/strings/zh_Hans.json | 5 ----- src/i18n/strings/zh_Hant.json | 5 ----- 25 files changed, 117 deletions(-) diff --git a/src/i18n/strings/cs.json b/src/i18n/strings/cs.json index b98bcc01ed..25353f30df 100644 --- a/src/i18n/strings/cs.json +++ b/src/i18n/strings/cs.json @@ -3097,15 +3097,10 @@ "one": "%(count)s odpověď", "other": "%(count)s odpovědí" }, - "empty_explainer": "Vlákna pomáhají udržovat konverzace k tématu a snadno je sledovat.", - "empty_has_threads_tip": "Odpovědět na probíhající vlákno nebo použít \"%(replyInThread)s\", když najedete na zprávu a začnete novou.", - "empty_heading": "Udržujte diskuse organizované pomocí vláken", - "empty_tip": "Tip: Použijte \"%(replyInThread)s\" při najetí na zprávu.", "error_start_thread_existing_relation": "Nelze založit vlákno ve vlákně", "my_threads": "Moje vlákna", "my_threads_description": "Zobrazit všechna vlákna, kterých jste se zúčastnili", "open_thread": "Otevřít vlákno", - "show_all_threads": "Zobrazit všechna vlákna", "show_thread_filter": "Zobrazit:" }, "threads_activity_centre": { diff --git a/src/i18n/strings/de_DE.json b/src/i18n/strings/de_DE.json index 4ac9291038..5097bb2440 100644 --- a/src/i18n/strings/de_DE.json +++ b/src/i18n/strings/de_DE.json @@ -3073,15 +3073,10 @@ "one": "%(count)s Antwort", "other": "%(count)s Antworten" }, - "empty_explainer": "Threads helfen dabei, dass deine Konversationen beim Thema und leicht nachverfolgbar bleiben.", - "empty_has_threads_tip": "Antworte auf einen Thread oder klicke bei einer Nachricht auf „%(replyInThread)s“, um einen Thread zu starten.", - "empty_heading": "Organisiere Diskussionen mit Threads", - "empty_tip": "Tipp: Nutze “%(replyInThread)s” beim Schweben über eine Nachricht.", "error_start_thread_existing_relation": "Du kannst keinen Thread in einem Thread starten", "my_threads": "Meine Threads", "my_threads_description": "Zeigt alle Threads, an denen du teilgenommen hast", "open_thread": "Thread anzeigen", - "show_all_threads": "Alle Threads anzeigen", "show_thread_filter": "Zeige:" }, "time": { diff --git a/src/i18n/strings/el.json b/src/i18n/strings/el.json index d7ea9063ac..2e75cc9689 100644 --- a/src/i18n/strings/el.json +++ b/src/i18n/strings/el.json @@ -2441,14 +2441,10 @@ "one": "%(count)s απάντηση", "other": "%(count)s απαντήσεις" }, - "empty_explainer": "Τα νήματα σας βοηθούν να οργανώνετε και να παρακολουθείτε καλύτερα τις συνομιλίες σας.", - "empty_has_threads_tip": "Απαντήστε σε ένα νήμα εκτέλεσης που βρίσκεται σε εξέλιξη ή χρησιμοποιήστε το \"%(replyInThread)s\" όταν τοποθετείτε το δείκτη του ποντικιού πάνω από ένα μήνυμα για να ξεκινήσετε ένα νέο.", - "empty_heading": "Διατηρήστε τις συζητήσεις οργανωμένες με νήματα", "error_start_thread_existing_relation": "Δεν είναι δυνατή η δημιουργία νήματος από ένα συμβάν με μια υπάρχουσα σχέση", "my_threads": "Τα νήματα μου", "my_threads_description": "Εμφανίζει όλα τα νήματα στα οποία έχετε συμμετάσχει", "open_thread": "Άνοιγμα νήματος", - "show_all_threads": "Εμφάνιση όλων των νημάτων", "show_thread_filter": "Εμφάνισε:" }, "time": { diff --git a/src/i18n/strings/es.json b/src/i18n/strings/es.json index 794ac603ba..bec39f8174 100644 --- a/src/i18n/strings/es.json +++ b/src/i18n/strings/es.json @@ -2822,15 +2822,10 @@ "one": "%(count)s respuesta", "other": "%(count)s respuestas" }, - "empty_explainer": "Los hilos ayudan a mantener tus conversaciones centradas y a que sean fáciles de seguir.", - "empty_has_threads_tip": "Responde a un hilo en curso o usa «%(replyInThread)s» al pasar el ratón por encima de un mensaje para iniciar uno nuevo.", - "empty_heading": "Organiza los temas de conversación en hilos", - "empty_tip": "Consejo: Usa «%(replyInThread)s» mientras pasas el ratón sobre un mensaje.", "error_start_thread_existing_relation": "No ha sido posible crear un hilo a partir de un evento con una relación existente", "my_threads": "Mis hilos", "my_threads_description": "Ver todos los hilos en los que has participado", "open_thread": "Abrir hilo", - "show_all_threads": "Ver todos los hilos", "show_thread_filter": "Mostrar:" }, "time": { diff --git a/src/i18n/strings/et.json b/src/i18n/strings/et.json index 4c714a9949..96e163f0ae 100644 --- a/src/i18n/strings/et.json +++ b/src/i18n/strings/et.json @@ -3044,15 +3044,10 @@ "one": "%(count)s vastus", "other": "%(count)s vastust" }, - "empty_explainer": "Jutulõngad aitavad hoida vestlused teemakohastena ning mugavalt loetavatena.", - "empty_has_threads_tip": "Vasta jätkuvas jutulõngas või uue jutulõnga loomiseks kasuta „%(replyInThread)s“ valikut, mida kuvatakse hiire liigutamisel sõnumi kohal.", - "empty_heading": "Halda vestlusi jutulõngadena", - "empty_tip": "Soovitus: Sõnumi kohal avanevast valikust kasuta „%(replyInThread)s“ võimalust.", "error_start_thread_existing_relation": "Jutulõnga ei saa luua sõnumist, mis juba on jutulõnga osa", "my_threads": "Minu jutulõngad", "my_threads_description": "Näitab kõiki jutulõngasid, kus sa oled osalenud", "open_thread": "Ava jutulõng", - "show_all_threads": "Näita kõiki jutulõngasid", "show_thread_filter": "Näita:" }, "time": { diff --git a/src/i18n/strings/fi.json b/src/i18n/strings/fi.json index 177029d11b..f44567a25d 100644 --- a/src/i18n/strings/fi.json +++ b/src/i18n/strings/fi.json @@ -2695,12 +2695,9 @@ "one": "%(count)s vastaus", "other": "%(count)s vastausta" }, - "empty_explainer": "Ketjut auttavat pitämään keskustelut asiayhteyteen sopivina ja helposti seurattavina.", - "empty_heading": "Pidä keskustelut järjestyksessä ketjuissa", "my_threads": "Omat ketjut", "my_threads_description": "Näyttää kaikki ketjut, joissa olet ollut osallinen", "open_thread": "Avaa ketju", - "show_all_threads": "Näytä kaikki ketjut", "show_thread_filter": "Näytä:" }, "time": { diff --git a/src/i18n/strings/fr.json b/src/i18n/strings/fr.json index a8df8fc902..55fc6ad1d5 100644 --- a/src/i18n/strings/fr.json +++ b/src/i18n/strings/fr.json @@ -3125,16 +3125,11 @@ "one": "%(count)s réponse", "other": "%(count)s réponses" }, - "empty_explainer": "Les fils de discussion vous permettent de recentrer vos conversations et de les rendre facile à suivre.", - "empty_has_threads_tip": "Répondez à un fil de discussion en cours ou utilisez \"%(replyInThread)s\" lorsque vous passez la souris sur un message pour en commencer un nouveau.", - "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": { diff --git a/src/i18n/strings/gl.json b/src/i18n/strings/gl.json index 99b4388671..7f8fa3cb2d 100644 --- a/src/i18n/strings/gl.json +++ b/src/i18n/strings/gl.json @@ -2598,15 +2598,10 @@ "one": "%(count)s resposta", "other": "%(count)s respostas" }, - "empty_explainer": "Os fíos axúdanche a manter as conversas no tema e facilitan o seguimento.", - "empty_has_threads_tip": "Responde a unha conversa en curso ou usa \"%(replyInThread)s\" cando pasas por enriba dunha mensaxe co rato para iniciar unha nova.", - "empty_heading": "Manter as conversas organizadas con fíos", - "empty_tip": "Truco: Usa \"%(replyInThread)s\" ao poñerte enriba dunha mensaxe.", "error_start_thread_existing_relation": "Non se pode crear un tema con unha relación existente desde un evento", "my_threads": "As miñas conversas", "my_threads_description": "Mostra tódalas conversas nas que participaches", "open_thread": "Abrir fío", - "show_all_threads": "Mostra tódolos temas", "show_thread_filter": "Mostrar:" }, "time": { diff --git a/src/i18n/strings/he.json b/src/i18n/strings/he.json index 4f8991ff6e..8c67ee5dac 100644 --- a/src/i18n/strings/he.json +++ b/src/i18n/strings/he.json @@ -2076,15 +2076,10 @@ "threads": { "all_threads": "כל הקישורים", "all_threads_description": "הצג את כל הקישורים מחדר זה", - "empty_explainer": "שרשורים עוזרים לשמור על השיחות שלכם בנושא וקל למעקב.", - "empty_has_threads_tip": "השיבו לשרשור מתמשך או השתמשו ב-\"%(replyInThread)s\" כשאתם מרחפים מעל הודעה כדי להתחיל הודעה חדשה.", - "empty_heading": "שימרו על דיונים מאורגנים בשרשורים", - "empty_tip": "טיפ: השתמש ב-\"%(replyInThread)s\" כשאתם מרחפים מעל הודעה.", "error_start_thread_existing_relation": "לא ניתן ליצור שרשור מאירוע עם קשר קיים", "my_threads": "הקישורים שלי", "my_threads_description": "הצג את כל השרשורים שאתם משתתפים בהם", "open_thread": "פתיחת שרשור", - "show_all_threads": "הצג את כל השרשורים", "show_thread_filter": "הצג:" }, "time": { diff --git a/src/i18n/strings/hu.json b/src/i18n/strings/hu.json index 526bd81639..6b90b22d1e 100644 --- a/src/i18n/strings/hu.json +++ b/src/i18n/strings/hu.json @@ -3012,15 +3012,10 @@ "one": "%(count)s válasz", "other": "%(count)s válasz" }, - "empty_explainer": "Az üzenetszálak segítenek a különböző témájú beszélgetések figyelemmel kísérésében.", - "empty_has_threads_tip": "Válaszoljon egy meglévő üzenetszálban, vagy új üzenetszál indításához használja a „%(replyInThread)s” lehetőséget az üzenet sarkában megjelenő menüben.", - "empty_heading": "Beszélgetések üzenetszálakba rendezése", - "empty_tip": "Tipp: Használja a „%(replyInThread)s” lehetőséget a szöveg fölé navigálva.", "error_start_thread_existing_relation": "Nem lehet üzenetszálat indítani olyan eseményről ami már rendelkezik kapcsolattal", "my_threads": "Saját üzenetszálak", "my_threads_description": "Minden üzenetszál megjelenítése, amelyben részt vesz", "open_thread": "Üzenetszál megnyitása", - "show_all_threads": "Minden üzenetszál megjelenítése", "show_thread_filter": "Megjelenítés:" }, "time": { diff --git a/src/i18n/strings/id.json b/src/i18n/strings/id.json index 79697d7dad..c3b8c462e2 100644 --- a/src/i18n/strings/id.json +++ b/src/i18n/strings/id.json @@ -3046,15 +3046,10 @@ "one": "%(count)s balasan", "other": "%(count)s balasan" }, - "empty_explainer": "Utasan membantu membuat obrolan sesuai topik dan mudah untuk dilacak.", - "empty_has_threads_tip": "Balas ke utasan yang sedang terjadi atau gunakan “%(replyInThread)s” ketika kursor diletakkan pada pesan untuk memulai yang baru.", - "empty_heading": "Buat diskusi tetap teratur dengan utasan", - "empty_tip": "Tip: Gunakan “%(replyInThread)s” ketika kursor di atas pesan.", "error_start_thread_existing_relation": "Tidak dapat membuat utasan dari sebuah peristiwa dengan relasi yang sudah ada", "my_threads": "Utasan saya", "my_threads_description": "Menampilkan semua utasan yang Anda berpartisipasi", "open_thread": "Buka utasan", - "show_all_threads": "Tampilkan semua utasan", "show_thread_filter": "Tampilkan:" }, "time": { diff --git a/src/i18n/strings/is.json b/src/i18n/strings/is.json index 10c477173a..3688882ada 100644 --- a/src/i18n/strings/is.json +++ b/src/i18n/strings/is.json @@ -2505,12 +2505,9 @@ "one": "%(count)s svar", "other": "%(count)s svör" }, - "empty_explainer": "Spjallþræðir hjálpa til við að halda samræðum við efnið og gerir auðveldara að rekja þær.", - "empty_heading": "Haltu umræðum skipulögðum með spjallþráðum", "my_threads": "Spjallþræðirnir mínir", "my_threads_description": "Birtir alla spjallþræði sem þú hefur tekið þátt í", "open_thread": "Opna spjallþráð", - "show_all_threads": "Birta alla spjallþræði", "show_thread_filter": "Sýna:" }, "time": { diff --git a/src/i18n/strings/it.json b/src/i18n/strings/it.json index c8a700b6e6..59d807a957 100644 --- a/src/i18n/strings/it.json +++ b/src/i18n/strings/it.json @@ -3090,15 +3090,10 @@ "one": "%(count)s risposta", "other": "%(count)s risposte" }, - "empty_explainer": "Le conversazioni ti aiutano a tenere le tue discussioni in tema e rintracciabili.", - "empty_has_threads_tip": "Rispondi ad una conversazione in corso o usa \"%(replyInThread)s\" passando sopra ad un messaggio per iniziarne una nuova.", - "empty_heading": "Tieni le discussioni organizzate in conversazioni", - "empty_tip": "Consiglio: usa \"%(replyInThread)s\" passando sopra un messaggio.", "error_start_thread_existing_relation": "Impossibile creare una conversazione da un evento con una relazione esistente", "my_threads": "Le mie conversazioni", "my_threads_description": "Mostra tutte le conversazioni a cui hai partecipato", "open_thread": "Apri conversazione", - "show_all_threads": "Mostra tutte le conversazioni", "show_thread_filter": "Mostra:" }, "threads_activity_centre": { diff --git a/src/i18n/strings/ja.json b/src/i18n/strings/ja.json index e07756ffd1..69aec14f82 100644 --- a/src/i18n/strings/ja.json +++ b/src/i18n/strings/ja.json @@ -2827,15 +2827,10 @@ "other": "%(count)s件の返信", "one": "%(count)s件の返信" }, - "empty_explainer": "スレッド機能を使うと、会話のテーマを維持したり、会話を簡単に追跡したりすることができます。", - "empty_has_threads_tip": "既存のスレッドに返信するか、メッセージの「%(replyInThread)s」機能を使用すると新しいスレッドを開始できます。", - "empty_heading": "スレッド機能を使って、会話をまとめましょう", - "empty_tip": "ヒント:メッセージの「%(replyInThread)s」機能を使用すると新しいスレッドを開始できます。", "error_start_thread_existing_relation": "既存の関係のあるイベントからスレッドを作成することはできません", "my_threads": "自分のスレッド", "my_threads_description": "参加している全スレッドを表示", "open_thread": "スレッドを開く", - "show_all_threads": "全てのスレッドを表示", "show_thread_filter": "表示:" }, "time": { diff --git a/src/i18n/strings/lo.json b/src/i18n/strings/lo.json index 8cfe241876..a7f36be946 100644 --- a/src/i18n/strings/lo.json +++ b/src/i18n/strings/lo.json @@ -2457,15 +2457,10 @@ "one": "%(count)s ຕອບກັບ", "other": "%(count)s ຕອບກັບ" }, - "empty_explainer": "ກະທູ້ຊ່ວຍໃຫ້ການສົນທະນາຂອງທ່ານຢູ່ໃນຫົວຂໍ້ ແລະ ງ່າຍຕໍ່ການຕິດຕາມ.", - "empty_has_threads_tip": "ຕອບກັບຫາກະທູ້ທີ່ກຳລັງດຳເນີນ ຫຼືໃຊ້ ຢູ່“%(replyInThread)s” ເມື່ອເລື່ອນໃສ່ຂໍ້ຄວາມເພື່ອເລີ່ມຕົ້ນອັນໃໝ່.", - "empty_heading": "ຮັກສາການສົນທະນາທີ່ມີການຈັດລະບຽບ", - "empty_tip": "ເຄັດລັບ: ໃຊ້ “%(replyInThread)s” ເມື່ອເລື່ອນໃສ່ຂໍ້ຄວາມ.", "error_start_thread_existing_relation": "ບໍ່ສາມາດສ້າງກະທູ້ຈາກເຫດການທີ່ມີຄວາມສໍາພັນທີ່ມີຢູ່ແລ້ວ", "my_threads": "ກະທູ້ຂອງຂ້ອຍ", "my_threads_description": "ສະແດງຫົວຂໍ້ທັງໝົດທີ່ທ່ານໄດ້ເຂົ້າຮ່ວມ", "open_thread": "ເປີດກະທູ້", - "show_all_threads": "ສະແດງຫົວຂໍ້ທັງໝົດ", "show_thread_filter": "ສະແດງ:" }, "time": { diff --git a/src/i18n/strings/nl.json b/src/i18n/strings/nl.json index dbd0b4ddd3..1927341c57 100644 --- a/src/i18n/strings/nl.json +++ b/src/i18n/strings/nl.json @@ -2620,15 +2620,10 @@ "one": "%(count)s reactie", "other": "%(count)s reacties" }, - "empty_explainer": "Threads helpen jou gesprekken on-topic te houden en gemakkelijk bij te houden.", - "empty_has_threads_tip": "Reageer op een lopende thread of gebruik \"%(replyInThread)s\" wanneer je de muisaanwijzer op een bericht plaatst om een nieuwe te starten.", - "empty_heading": "Houd threads georganiseerd", - "empty_tip": "Tip: Gebruik “%(replyInThread)s” met de muiscursor boven een bericht.", "error_start_thread_existing_relation": "Kan geen discussie maken van een gebeurtenis met een bestaande relatie", "my_threads": "Mijn discussies", "my_threads_description": "Toon alle threads waarin je hebt bijgedragen", "open_thread": "Open discussie", - "show_all_threads": "Threads weergeven", "show_thread_filter": "Toon:" }, "time": { diff --git a/src/i18n/strings/pl.json b/src/i18n/strings/pl.json index 671ec8c738..90ea7ea988 100644 --- a/src/i18n/strings/pl.json +++ b/src/i18n/strings/pl.json @@ -3197,16 +3197,11 @@ "one": "%(count)s odpowiedź", "other": "%(count)s odpowiedzi" }, - "empty_explainer": "Dzięki wątkom Twoje rozmowy są zorganizowane i łatwe do śledzenia.", - "empty_has_threads_tip": "Odpowiedz do trwającego już wątku lub użyj “%(replyInThread)s” najeżdżając na wiadomość, aby rozpocząć nową.", - "empty_heading": "Organizuj dyskusje za pomocą wątków", - "empty_tip": "Tip: Użyj “%(replyInThread)s” najeżdżając na wiadomość.", "error_start_thread_existing_relation": "Nie można utworzyć wątku z wydarzenia z istniejącą relacją", "mark_all_read": "Oznacz wszystkie jako przeczytane", "my_threads": "Moje wątki", "my_threads_description": "Pokazuje wszystkie wątki, w których brałeś udział", "open_thread": "Otwórz wątek", - "show_all_threads": "Pokaż wszystkie wątki", "show_thread_filter": "Pokaż:" }, "threads_activity_centre": { diff --git a/src/i18n/strings/ru.json b/src/i18n/strings/ru.json index 79afe8b52a..45d229ca61 100644 --- a/src/i18n/strings/ru.json +++ b/src/i18n/strings/ru.json @@ -3074,15 +3074,10 @@ "one": "%(count)s ответ", "other": "%(count)s ответов" }, - "empty_explainer": "Обсуждения помогают поддерживать и легко отслеживать тематику бесед.", - "empty_has_threads_tip": "Ответьте в текущее обсуждение или создайте новое, наведя курсор на сообщение и нажав «%(replyInThread)s».", - "empty_heading": "Организуйте обсуждения с помощью обсуждений", - "empty_tip": "Совет: Используйте “%(replyInThread)s” при наведении курсора на сообщение.", "error_start_thread_existing_relation": "Невозможно создать обсуждение из события с существующей связью", "my_threads": "Мои обсуждения", "my_threads_description": "Показывает все обсуждения, в которых вы принимали участие", "open_thread": "Открыть ветку", - "show_all_threads": "Показать все обсуждения", "show_thread_filter": "Показать:" }, "time": { diff --git a/src/i18n/strings/sk.json b/src/i18n/strings/sk.json index e4bec50287..47a00bb12e 100644 --- a/src/i18n/strings/sk.json +++ b/src/i18n/strings/sk.json @@ -3077,15 +3077,10 @@ "one": "%(count)s odpoveď", "other": "%(count)s odpovedí" }, - "empty_explainer": "Vlákna pomáhajú udržiavať konverzácie v téme a uľahčujú ich sledovanie.", - "empty_has_threads_tip": "Odpovedzte na prebiehajúce vlákno alebo použite \"%(replyInThread)s\", keď prejdete nad správu a začnete novú.", - "empty_heading": "Udržujte diskusie organizované pomocou vlákien", - "empty_tip": "Tip: Použite položku “%(replyInThread)s”, keď prejdete ponad správu.", "error_start_thread_existing_relation": "Nie je možné vytvoriť vlákno z udalosti s existujúcim vzťahom", "my_threads": "Moje vlákna", "my_threads_description": "Zobrazí všetky vlákna, v ktorých ste sa zúčastnili", "open_thread": "Otvoriť vlákno", - "show_all_threads": "Zobraziť všetky vlákna", "show_thread_filter": "Zobraziť:" }, "time": { diff --git a/src/i18n/strings/sq.json b/src/i18n/strings/sq.json index 6563ee0fd1..5c67bb8d5b 100644 --- a/src/i18n/strings/sq.json +++ b/src/i18n/strings/sq.json @@ -2894,15 +2894,10 @@ "one": "%(count)s përgjigje", "other": "%(count)s përgjigje" }, - "empty_explainer": "Rrjedhat ndihmojnë që të mbahen bisedat tuaja brenda temës dhe të ndiqen kollaj.", - "empty_has_threads_tip": "Përgjigjuni te një rrjedhë në zhvillim e sipër, ose përdorni “%(replyInThread)s”, kur kalohet kursori sipër një mesazhi për të filluar një të re.", - "empty_heading": "Mbajini diskutimet të sistemuara në rrjedha", - "empty_tip": "Ndihmëz: Përdorni “%(replyInThread)s”, teksa kaloni kursorin sipër një mesazhi.", "error_start_thread_existing_relation": "S’mund të krijohet një rrjedhë prej një akti me një marrëdhënie ekzistuese", "my_threads": "Rrjedhat e mia", "my_threads_description": "Shfaq krejt rrjedhat ku keni marrë pjesë", "open_thread": "Hape rrjedhën", - "show_all_threads": "Shfaqi krejt rrjedhat", "show_thread_filter": "Shfaq:" }, "time": { diff --git a/src/i18n/strings/sv.json b/src/i18n/strings/sv.json index 8e10fa33ac..6774e882ef 100644 --- a/src/i18n/strings/sv.json +++ b/src/i18n/strings/sv.json @@ -3089,15 +3089,10 @@ "one": "%(count)s svar", "other": "%(count)s svar" }, - "empty_explainer": "Trådar underlättar för att hålla konversationer till ämnet och gör dem lättare att följa.", - "empty_has_threads_tip": "Svara i en pågående tråd eller använd \"%(replyInThread)s\" när du håller över ett meddelande för att starta en ny tråd.", - "empty_heading": "Håll diskussioner organiserade med trådar", - "empty_tip": "Tips: Välj \"%(replyInThread)s\" när du håller över ett meddelande.", "error_start_thread_existing_relation": "Kan inte skapa tråd från en händelse med en existerande relation", "my_threads": "Mina trådar", "my_threads_description": "Visar alla trådar du har medverkat i", "open_thread": "Öppna tråd", - "show_all_threads": "Visa alla trådar", "show_thread_filter": "Visa:" }, "threads_activity_centre": { diff --git a/src/i18n/strings/uk.json b/src/i18n/strings/uk.json index 53300cf08c..932b7e8689 100644 --- a/src/i18n/strings/uk.json +++ b/src/i18n/strings/uk.json @@ -3009,15 +3009,10 @@ "one": "%(count)s відповідь", "other": "%(count)s відповідей" }, - "empty_explainer": "Гілки допомагають підтримувати розмови за темою та за ними легко стежити.", - "empty_has_threads_tip": "Дайте відповідь у наявну гілку, або створіть нову, навівши курсор на повідомлення й натиснувши «%(replyInThread)s».", - "empty_heading": "Упорядкуйте обговорення за допомогою гілок", - "empty_tip": "Порада: Використовуйте «%(replyInThread)s» навівши вказівник на повідомлення.", "error_start_thread_existing_relation": "Неможливо створити гілку з події з наявним відношенням", "my_threads": "Мої гілки", "my_threads_description": "Показує всі гілки, де ви брали участь", "open_thread": "Відкрити гілку", - "show_all_threads": "Показати всі гілки", "show_thread_filter": "Показати:" }, "time": { diff --git a/src/i18n/strings/vi.json b/src/i18n/strings/vi.json index 7abc70dedc..359c0e3182 100644 --- a/src/i18n/strings/vi.json +++ b/src/i18n/strings/vi.json @@ -2768,10 +2768,8 @@ "one": "%(count)s trả lời", "other": "%(count)s trả lời" }, - "empty_heading": "Giữ các cuộc thảo luận được tổ chức với các chủ đề này", "my_threads": "Các chủ đề của tôi", "my_threads_description": "Hiển thị tất cả các chủ đề bạn đã tham gia", - "show_all_threads": "Hiển thị tất cả chủ đề", "show_thread_filter": "Hiển thị:" }, "time": { diff --git a/src/i18n/strings/zh_Hans.json b/src/i18n/strings/zh_Hans.json index 8457984941..3b2269e9a5 100644 --- a/src/i18n/strings/zh_Hans.json +++ b/src/i18n/strings/zh_Hans.json @@ -2752,15 +2752,10 @@ "one": "%(count)s 条回复", "other": "%(count)s 条回复" }, - "empty_explainer": "消息列帮助保持你的对话切题并易于追踪。", - "empty_has_threads_tip": "回复进行中的消息列或当悬停在消息上时使用%(replyInThread)s来发起新的消息列。", - "empty_heading": "用消息列使讨论井然有序", - "empty_tip": "实用提示:悬停在消息上时使用“%(replyInThread)s”。", "error_start_thread_existing_relation": "无法从既有关系的事件创建消息列", "my_threads": "我的消息列", "my_threads_description": "显示您参与的所有消息列", "open_thread": "打开消息列", - "show_all_threads": "显示所有消息列", "show_thread_filter": "显示:" }, "time": { diff --git a/src/i18n/strings/zh_Hant.json b/src/i18n/strings/zh_Hant.json index 57b31e1769..8715591fcb 100644 --- a/src/i18n/strings/zh_Hant.json +++ b/src/i18n/strings/zh_Hant.json @@ -3004,15 +3004,10 @@ "one": "%(count)s 回覆", "other": "%(count)s 回覆" }, - "empty_explainer": "「討論串」功能可以協助您的對話不離題且易於追蹤。", - "empty_has_threads_tip": "將滑鼠游標停留在訊息上來開始新的討論串時,回覆正在進行的討論串或使用「%(replyInThread)s」。", - "empty_heading": "使用「討論串」功能,讓討論保持有條不紊", - "empty_tip": "秘訣:在滑鼠游標停於訊息上時使用「%(replyInThread)s」。", "error_start_thread_existing_relation": "無法從討論串既有的關係建立活動", "my_threads": "我的討論串", "my_threads_description": "顯示您參與的所有討論串", "open_thread": "開啟討論串", - "show_all_threads": "顯示所有討論串", "show_thread_filter": "顯示:" }, "time": { From 2fd291c23c77f8d5cb85c5ee74c1efaabad3ed22 Mon Sep 17 00:00:00 2001 From: ElementRobot Date: Tue, 23 Jul 2024 07:20:25 +0100 Subject: [PATCH 55/59] [create-pull-request] automated change (#12804) 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 b62c737645..5cf6391720 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:14ca769c834220a478a1e97df041361c6fb0a541ccb2f0666d3ce911224f5f7e"; +const DOCKER_TAG = "develop@sha256:9e193236098ae5ff66c9bf79252e318fd561ceb1322d5495780a11d9dbdcfb17"; async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise> { const templateDir = path.join(__dirname, "templates", opts.template); From 5308c91842a241e8726d44de07246d3dfbf16863 Mon Sep 17 00:00:00 2001 From: David Baker Date: Tue, 23 Jul 2024 09:08:22 +0100 Subject: [PATCH 56/59] Close any open modals on logout (#12777) * Close any open modals on logout Split out from https://github.com/matrix-org/matrix-react-sdk/pull/12666 * Add test --- src/Modal.tsx | 18 +++++++++++++++++- test/Modal-test.ts | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/Modal.tsx b/src/Modal.tsx index b72180097c..b8dacdbc1e 100644 --- a/src/Modal.tsx +++ b/src/Modal.tsx @@ -22,9 +22,10 @@ import { IDeferred, defer, sleep } from "matrix-js-sdk/src/utils"; import { TypedEventEmitter } from "matrix-js-sdk/src/matrix"; import { Glass } from "@vector-im/compound-web"; -import dis from "./dispatcher/dispatcher"; +import dis, { defaultDispatcher } from "./dispatcher/dispatcher"; import AsyncWrapper from "./AsyncWrapper"; import { Defaultize } from "./@types/common"; +import { ActionPayload } from "./dispatcher/payloads"; const DIALOG_CONTAINER_ID = "mx_Dialog_Container"; const STATIC_DIALOG_CONTAINER_ID = "mx_Dialog_StaticContainer"; @@ -114,6 +115,21 @@ export class ModalManager extends TypedEventEmitter { + if (payload.action === "logout") { + this.forceCloseAllModals(); + } + }; + public toggleCurrentDialogVisibility(): void { const modal = this.getCurrentModal(); if (!modal) return; diff --git a/test/Modal-test.ts b/test/Modal-test.ts index d7630bd2da..6114446743 100644 --- a/test/Modal-test.ts +++ b/test/Modal-test.ts @@ -16,6 +16,7 @@ limitations under the License. import Modal from "../src/Modal"; import QuestionDialog from "../src/components/views/dialogs/QuestionDialog"; +import defaultDispatcher from "../src/dispatcher/dispatcher"; describe("Modal", () => { test("forceCloseAllModals should close all open modals", () => { @@ -29,4 +30,28 @@ describe("Modal", () => { Modal.forceCloseAllModals(); expect(Modal.hasDialogs()).toBe(false); }); + + test("open modals should be closed on logout", () => { + const modal1OnFinished = jest.fn(); + const modal2OnFinished = jest.fn(); + + Modal.createDialog(QuestionDialog, { + title: "Test dialog 1", + description: "This is a test dialog", + button: "Word", + onFinished: modal1OnFinished, + }); + + Modal.createDialog(QuestionDialog, { + title: "Test dialog 2", + description: "This is a test dialog", + button: "Word", + onFinished: modal2OnFinished, + }); + + defaultDispatcher.dispatch({ action: "logout" }, true); + + expect(modal1OnFinished).toHaveBeenCalled(); + expect(modal2OnFinished).toHaveBeenCalled(); + }); }); From 25fcd6a65fac2744ce3668421815eac2a28135bb Mon Sep 17 00:00:00 2001 From: Michael Telatynski <7t3chguy@gmail.com> Date: Tue, 23 Jul 2024 10:12:07 +0100 Subject: [PATCH 57/59] Update Thread Panel to match latest designs (#12797) * Add reusable empty state for the right panel Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Improve coverage Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update Thread Panel to match latest Figma Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Update tests Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * i18n Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> * Use --cpd-space var Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --------- Signed-off-by: Michael Telatynski <7t3chguy@gmail.com> --- res/css/_common.pcss | 2 +- res/css/views/right_panel/_ThreadPanel.pcss | 9 +++++---- res/css/views/rooms/_EventTile.pcss | 4 ++-- res/img/element-icons/thread-summary.svg | 1 - src/components/structures/ThreadPanel.tsx | 4 ---- .../structures/__snapshots__/ThreadPanel-test.tsx.snap | 10 ---------- 6 files changed, 8 insertions(+), 22 deletions(-) delete mode 100644 res/img/element-icons/thread-summary.svg diff --git a/res/css/_common.pcss b/res/css/_common.pcss index a454789efc..8264ccb704 100644 --- a/res/css/_common.pcss +++ b/res/css/_common.pcss @@ -851,7 +851,7 @@ legend { @define-mixin ThreadSummaryIcon { content: ""; display: inline-block; - mask-image: url("$(res)/img/element-icons/thread-summary.svg"); + mask-image: url("@vector-im/compound-design-tokens/icons/threads.svg"); mask-position: center; mask-repeat: no-repeat; mask-size: contain; diff --git a/res/css/views/right_panel/_ThreadPanel.pcss b/res/css/views/right_panel/_ThreadPanel.pcss index 612fd96747..fc1d39c9ca 100644 --- a/res/css/views/right_panel/_ThreadPanel.pcss +++ b/res/css/views/right_panel/_ThreadPanel.pcss @@ -18,12 +18,13 @@ limitations under the License. height: 100px; overflow: visible; + /* Unset flex on the thread list, but not the thread view */ + &:not(.mx_ThreadView) .mx_BaseCard_header .mx_BaseCard_header_title { + flex: unset; + } + .mx_BaseCard_header { .mx_BaseCard_header_title { - .mx_BaseCard_header_title_heading { - margin-right: auto; - } - .mx_AccessibleButton { font-size: 12px; color: $secondary-content; diff --git a/res/css/views/rooms/_EventTile.pcss b/res/css/views/rooms/_EventTile.pcss index 46f0ba900f..66c60f5f15 100644 --- a/res/css/views/rooms/_EventTile.pcss +++ b/res/css/views/rooms/_EventTile.pcss @@ -1024,7 +1024,7 @@ $left-gutter: 64px; $notification-dot-size: 8px; /* notification dot next to the timestamp */ margin: calc(var(--topOffset) + $hrHeight) 0 var(--topOffset); /* include the height of horizontal line */ - padding: $padding $spacing-24 $padding $padding; + padding: $padding; border-radius: $borderRadius; display: flex; @@ -1039,7 +1039,7 @@ $left-gutter: 64px; &::after { $inset-block-start: auto; - $inset-inline-end: calc(32px - $padding); + $inset-inline-end: calc(-1 * var(--cpd-space-2x)); $inset-block-end: calc(-1 * var(--topOffset) - $hrHeight); /* exclude the height of horizontal line */ $inset-inline-start: calc(var(--leftOffset) + $padding); inset: $inset-block-start $inset-inline-end $inset-block-end $inset-inline-start; diff --git a/res/img/element-icons/thread-summary.svg b/res/img/element-icons/thread-summary.svg deleted file mode 100644 index 2c4f0ead0c..0000000000 --- a/res/img/element-icons/thread-summary.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/src/components/structures/ThreadPanel.tsx b/src/components/structures/ThreadPanel.tsx index 7c7761368d..547d185bf1 100644 --- a/src/components/structures/ThreadPanel.tsx +++ b/src/components/structures/ThreadPanel.tsx @@ -36,7 +36,6 @@ import Measured from "../views/elements/Measured"; import PosthogTrackers from "../../PosthogTrackers"; import { ButtonEvent } from "../views/elements/AccessibleButton"; import Spinner from "../views/elements/Spinner"; -import Heading from "../views/typography/Heading"; import { clearRoomNotification } from "../../utils/notifications"; import EmptyState from "../views/right_panel/EmptyState"; @@ -138,9 +137,6 @@ export const ThreadPanelHeader: React.FC<{ return (
    - - {_t("common|threads")} - diff --git a/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap b/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap index 0a219b8403..21a08b8a6c 100644 --- a/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap +++ b/test/components/structures/__snapshots__/ThreadPanel-test.tsx.snap @@ -5,11 +5,6 @@ exports[`ThreadPanel Header expect that All filter for ThreadPanelHeader properl
    -

    - Threads -

    +
    + + + + +
    +
    +
    +
    + + u + u
    + 2
    -
    -
    - @user:example.com -
    -
    -
    -
    + + u +
    + + @user:example.com + +
    +
    + +
    + + + + +
    +
    +
    +
    + + u + u
    + 2
    -
    -
    - @user:example.com -
    -
    -
    -
    + + u +
    + + @user:example.com + +
    +
    + +
    + + + + +
    +
    +
    +
    + + u + u
    + 2
    -
    -
    - @user:example.com -
    -
    -
    -
    + + u +
    + + @user:example.com + +
    +
    + +
    + + + + +
    +
    +
    +
    + + u + u
    + 2
    - -
    - -
    -
    - @user:example.com -
    -
    -
    Date: Tue, 23 Jul 2024 17:16:24 +0530 Subject: [PATCH 59/59] Add release announcement for the new room header (#12802) --- src/components/views/rooms/RoomHeader.tsx | 136 ++++++++++-------- src/i18n/strings/en_EN.json | 2 + src/stores/ReleaseAnnouncementStore.ts | 2 +- .../__snapshots__/RoomHeader-test.tsx.snap | 2 + test/stores/ReleaseAnnouncementStore-test.tsx | 17 ++- 5 files changed, 91 insertions(+), 68 deletions(-) diff --git a/src/components/views/rooms/RoomHeader.tsx b/src/components/views/rooms/RoomHeader.tsx index 19b368cd18..c7b1673166 100644 --- a/src/components/views/rooms/RoomHeader.tsx +++ b/src/components/views/rooms/RoomHeader.tsx @@ -57,6 +57,9 @@ import { isVideoRoom } from "../../../utils/video-rooms"; import { notificationLevelToIndicator } from "../../../utils/notifications"; import { CallGuestLinkButton } from "./RoomHeader/CallGuestLinkButton"; import { ButtonEvent } from "../elements/AccessibleButton"; +import { ReleaseAnnouncement } from "../../structures/ReleaseAnnouncement"; +import { useIsReleaseAnnouncementOpen } from "../../../hooks/useIsReleaseAnnouncementOpen"; +import { ReleaseAnnouncementStore } from "../../../stores/ReleaseAnnouncementStore"; export default function RoomHeader({ room, @@ -238,74 +241,87 @@ export default function RoomHeader({ voiceCallButton = undefined; } + const isReleaseAnnouncementOpen = useIsReleaseAnnouncementOpen("newRoomHeader"); + return ( <> - + {roomTopic && ( + + {roomTopicBody} + + )} + + + {additionalButtons?.map((props) => { const label = props.label(); diff --git a/src/i18n/strings/en_EN.json b/src/i18n/strings/en_EN.json index 12ad79607d..37e69b7a77 100644 --- a/src/i18n/strings/en_EN.json +++ b/src/i18n/strings/en_EN.json @@ -1950,6 +1950,8 @@ "one": "Asking to join", "other": "%(count)s people asking to join" }, + "release_announcement_description": "Enjoy a simpler, more accessible room header.", + "release_announcement_header": "New design!", "room_is_public": "This room is public", "show_widgets_button": "Show Widgets", "video_call_button_ec": "Video call (%(brand)s)", diff --git a/src/stores/ReleaseAnnouncementStore.ts b/src/stores/ReleaseAnnouncementStore.ts index 604c13fc49..1fd3388982 100644 --- a/src/stores/ReleaseAnnouncementStore.ts +++ b/src/stores/ReleaseAnnouncementStore.ts @@ -27,7 +27,7 @@ import { Features } from "../settings/Settings"; /** * The features are shown in the array order. */ -const FEATURES = ["threadsActivityCentre"] as const; +const FEATURES = ["threadsActivityCentre", "newRoomHeader"] as const; /** * All the features that can be shown in the release announcements. */ diff --git a/test/components/views/rooms/__snapshots__/RoomHeader-test.tsx.snap b/test/components/views/rooms/__snapshots__/RoomHeader-test.tsx.snap index 58abdb0991..dd76c36367 100644 --- a/test/components/views/rooms/__snapshots__/RoomHeader-test.tsx.snap +++ b/test/components/views/rooms/__snapshots__/RoomHeader-test.tsx.snap @@ -7,6 +7,8 @@ exports[`RoomHeader does not show the face pile for DMs 1`] = ` style="--mx-flex-display: flex; --mx-flex-direction: row; --mx-flex-align: center; --mx-flex-justify: start; --mx-flex-gap: var(--cpd-space-3x);" >