Merge branch 'develop' of https://github.com/vector-im/element-web into staging

# Conflicts:
#	yarn.lock
This commit is contained in:
Michael Telatynski 2024-07-23 12:53:11 +01:00
commit 88b3b922f9
No known key found for this signature in database
GPG key ID: A2B008A5F49F5D0D
13 changed files with 3337 additions and 1679 deletions

View file

@ -37,10 +37,10 @@ jobs:
run: ${{ matrix.prepare }} run: ${{ matrix.prepare }}
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3 uses: docker/setup-qemu-action@5927c834f5b4fdf503fca6f4c7eccda82949e1ee # v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@d70bba72b1f3fd22344832f00baa16ece964efeb # v3 uses: docker/setup-buildx-action@4fd812986e6c8c2a69e18311145f9371337f27d4 # v3
with: with:
install: true install: true
@ -65,7 +65,7 @@ jobs:
- name: Build and push - name: Build and push
id: build-and-push id: build-and-push
uses: docker/build-push-action@31159d49c0d4756269a0940a750801a1ea5d7003 # v6 uses: docker/build-push-action@1a162644f9a7e87d8f4b053101d1d9a712edc18c # v6
with: with:
context: . context: .
push: true push: true

View file

@ -46,6 +46,7 @@ jobs:
with: with:
cache: "yarn" cache: "yarn"
cache-dependency-path: element-web/yarn.lock cache-dependency-path: element-web/yarn.lock
node-version: "lts/*"
- name: Generate automations docs - name: Generate automations docs
working-directory: element-web working-directory: element-web

View file

@ -56,13 +56,48 @@ jobs:
move_needs_info_issues: move_needs_info_issues:
name: X-Needs-Info issues to Need info column on triage board name: X-Needs-Info issues to Need info column on triage board
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Info')
steps: steps:
- uses: konradpabjan/move-labeled-or-milestoned-issue@190352295fe309fcb113b49193bc81d9aaa9cb01 - id: add_to_project
uses: actions/add-to-project@v1.0.1
with: with:
action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}" project-url: ${{ env.PROJECT_URL }}
project-url: "https://github.com/orgs/element-hq/projects/120" github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
column-name: "Needs info"
label-name: "X-Needs-Info" - id: set_fields
uses: titoportas/update-project-fields@421a54430b3cdc9eefd8f14f9ce0142ab7678751 # v0.1.0
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
item-id: ${{ steps.add_to_project.outputs.itemId }} # Use the item-id output of the previous step
field-keys: Status
field-values: "Needs info"
env:
PROJECT_URL: https://github.com/orgs/element-hq/projects/120
move_flakey_test_issues:
name: Z-Flaky-Test issues to Sized for maintainer column on triage board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'Z-Flaky-Test')
steps:
- id: add_to_project
uses: actions/add-to-project@v1.0.1
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: set_fields
uses: titoportas/update-project-fields@421a54430b3cdc9eefd8f14f9ce0142ab7678751 # v0.1.0
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
item-id: ${{ steps.add_to_project.outputs.itemId }} # Use the item-id output of the previous step
field-keys: Status
field-values: "Sized for maintainer"
env:
PROJECT_URL: https://github.com/orgs/element-hq/projects/120
add_priority_design_issues_to_project: add_priority_design_issues_to_project:
name: P1 X-Needs-Design to Design project board name: P1 X-Needs-Design to Design project board

View file

@ -1,5 +1,5 @@
{ {
"minify": true, "minify": false,
"enableClasses": false, "enableClasses": false,
"feature-detects": [ "feature-detects": [
"test/css/animations", "test/css/animations",
@ -31,6 +31,7 @@
"test/json", "test/json",
"test/network/fetch", "test/network/fetch",
"test/storage/localstorage", "test/storage/localstorage",
"test/window/resizeobserver" "test/window/resizeobserver",
"test/audio/webaudio"
] ]
} }

View file

@ -374,8 +374,8 @@ The VoIP and Jitsi options are:
} }
``` ```
The `widget` is the `content` of a normal widget state event. The `layout` is the layout specifier for the widget being created, The `widget` is the `content` of a normal widget state event. The `layout` is the layout specifier for the widget being created,
as defined by the `io.element.widgets.layout` state event. By default this applies to all rooms, but the behaviour can be skipped for DMs as defined by the `io.element.widgets.layout` state event. By default this applies to all rooms, but the behaviour can be skipped for
by setting the option `widget_build_url_ignore_dm` to `true`. 2-person rooms, causing Element to fall back to 1:1 VoIP, by setting the option `widget_build_url_ignore_dm` to `true`.
5. `audio_stream_url`: Optional URL to pass to Jitsi to enable live streaming. This option is considered experimental and may be removed 5. `audio_stream_url`: Optional URL to pass to Jitsi to enable live streaming. This option is considered experimental and may be removed
at any time without notice. at any time without notice.
6. `element_call`: Optional configuration for native group calls using Element Call, with the following subkeys: 6. `element_call`: Optional configuration for native group calls using Element Call, with the following subkeys:

View file

@ -71,6 +71,7 @@
"@types/react": "17.0.80" "@types/react": "17.0.80"
}, },
"dependencies": { "dependencies": {
"@formatjs/intl-segmenter": "^11.5.7",
"@matrix-org/react-sdk-module-api": "^2.3.0", "@matrix-org/react-sdk-module-api": "^2.3.0",
"jsrsasign": "^11.0.0", "jsrsasign": "^11.0.0",
"katex": "^0.16.0", "katex": "^0.16.0",
@ -187,7 +188,7 @@
"prettier": "3.3.2", "prettier": "3.3.2",
"process": "^0.11.10", "process": "^0.11.10",
"raw-loader": "^4.0.2", "raw-loader": "^4.0.2",
"rimraf": "^5.0.0", "rimraf": "^6.0.0",
"semver": "^7.5.2", "semver": "^7.5.2",
"string-replace-loader": "3", "string-replace-loader": "3",
"style-loader": "4", "style-loader": "4",
@ -197,7 +198,7 @@
"terser-webpack-plugin": "^5.3.9", "terser-webpack-plugin": "^5.3.9",
"ts-node": "^10.9.1", "ts-node": "^10.9.1",
"ts-prune": "^0.10.3", "ts-prune": "^0.10.3",
"typescript": "5.5.2", "typescript": "5.5.3",
"util": "^0.12.5", "util": "^0.12.5",
"webpack": "^5.89.0", "webpack": "^5.89.0",
"webpack-bundle-analyzer": "^4.8.0", "webpack-bundle-analyzer": "^4.8.0",

View file

@ -10,5 +10,5 @@ sonar.exclusions=__mocks__,docs,element.io,nginx
sonar.typescript.tsconfigPath=./tsconfig.json sonar.typescript.tsconfigPath=./tsconfig.json
sonar.javascript.lcov.reportPaths=coverage/lcov.info sonar.javascript.lcov.reportPaths=coverage/lcov.info
sonar.coverage.exclusions=test/**/*,res/**/* sonar.coverage.exclusions=test/**/*,res/**/*,src/vector/modernizr.js
sonar.testExecutionReportPaths=coverage/jest-sonar-report.xml sonar.testExecutionReportPaths=coverage/jest-sonar-report.xml

View file

@ -33,7 +33,9 @@ type ElectronChannel =
| "update-downloaded" | "update-downloaded"
| "userDownloadCompleted" | "userDownloadCompleted"
| "userDownloadAction" | "userDownloadAction"
| "openDesktopCapturerSourcePicker"; | "openDesktopCapturerSourcePicker"
| "userAccessToken"
| "serverSupportedVersions";
declare global { declare global {
interface Window { interface Window {

View file

@ -102,11 +102,15 @@ async function tryUpdateServerSupportMap(clientApiUrl: string, accessToken?: str
const config = fetchConfigForToken(accessToken); const config = fetchConfigForToken(accessToken);
const versions = await (await fetch(`${clientApiUrl}/_matrix/client/versions`, config)).json(); const versions = await (await fetch(`${clientApiUrl}/_matrix/client/versions`, config)).json();
console.log(`[ServiceWorker] /versions response for '${clientApiUrl}': ${JSON.stringify(versions)}`);
serverSupportMap[clientApiUrl] = { serverSupportMap[clientApiUrl] = {
supportsAuthedMedia: Boolean(versions?.versions?.includes("v1.11")), supportsAuthedMedia: Boolean(versions?.versions?.includes("v1.11")),
cacheExpiryTimeMs: new Date().getTime() + 2 * 60 * 60 * 1000, // 2 hours from now cacheExpiryTimeMs: new Date().getTime() + 2 * 60 * 60 * 1000, // 2 hours from now
}; };
console.log(
`[ServiceWorker] serverSupportMap update for '${clientApiUrl}': ${JSON.stringify(serverSupportMap[clientApiUrl])}`,
);
} }
// Ideally we'd use the `Client` interface for `client`, but since it's not available (see 'fetch' listener), we use // Ideally we'd use the `Client` interface for `client`, but since it's not available (see 'fetch' listener), we use

View file

@ -19,6 +19,7 @@ limitations under the License.
*/ */
import { logger } from "matrix-js-sdk/src/logger"; import { logger } from "matrix-js-sdk/src/logger";
import { shouldPolyfill as shouldPolyFillIntlSegmenter } from "@formatjs/intl-segmenter/should-polyfill";
// These are things that can run before the skin loads - be careful not to reference the react-sdk though. // These are things that can run before the skin loads - be careful not to reference the react-sdk though.
import { parseQsFromFragment } from "./url_utils"; import { parseQsFromFragment } from "./url_utils";
@ -75,8 +76,16 @@ function checkBrowserFeatures(): boolean {
() => window.RegExp?.prototype && "unicodeSets" in window.RegExp.prototype, () => window.RegExp?.prototype && "unicodeSets" in window.RegExp.prototype,
); );
// ES2024: https://402.ecma-international.org/9.0/#sec-intl.segmenter // ES2024: https://402.ecma-international.org/9.0/#sec-intl.segmenter
// The built-in modernizer 'intl' check only checks for the presence of the Intl object, not the Segmenter,
// and older Firefox has the former but not the latter, so we add our own.
// This is polyfilled now, but we still want to show the warning because we want to remove the polyfill
// at some point.
window.Modernizr.addTest("intlsegmenter", () => typeof window.Intl?.Segmenter === "function"); window.Modernizr.addTest("intlsegmenter", () => typeof window.Intl?.Segmenter === "function");
// Basic test for WebAssembly support. We could also try instantiating a simple module,
// although this would start to make (more) assumptions about how rust-crypto loads its wasm.
window.Modernizr.addTest("wasm", () => typeof WebAssembly === "object" && typeof WebAssembly.Module === "function");
const featureList = Object.keys(window.Modernizr) as Array<keyof ModernizrStatic>; const featureList = Object.keys(window.Modernizr) as Array<keyof ModernizrStatic>;
let featureComplete = true; let featureComplete = true;
@ -106,6 +115,10 @@ const supportedBrowser = checkBrowserFeatures();
// the browser to use as much parallelism as it can. // the browser to use as much parallelism as it can.
// Load parallelism is based on research in https://github.com/element-hq/element-web/issues/12253 // Load parallelism is based on research in https://github.com/element-hq/element-web/issues/12253
async function start(): Promise<void> { async function start(): Promise<void> {
if (shouldPolyFillIntlSegmenter()) {
await import(/* webpackChunkName: "intl-segmenter-polyfill" */ "@formatjs/intl-segmenter/polyfill-force");
}
// load init.ts async so that its code is not executed immediately and we can catch any exceptions // load init.ts async so that its code is not executed immediately and we can catch any exceptions
const { const {
rageshakePromise, rageshakePromise,
@ -126,6 +139,8 @@ async function start(): Promise<void> {
"./init" "./init"
); );
// Now perform the next stage of initialisation. This has its own try/catch in which we render
// a react error page on failure.
try { try {
// give rageshake a chance to load/fail, we don't actually assert rageshake loads, we allow it to fail if no IDB // give rageshake a chance to load/fail, we don't actually assert rageshake loads, we allow it to fail if no IDB
await settled(rageshakePromise); await settled(rageshakePromise);
@ -238,6 +253,10 @@ async function start(): Promise<void> {
} }
start().catch((err) => { start().catch((err) => {
// If we get here, things have gone terribly wrong and we cannot load the app javascript at all.
// Show a different, very simple iframed-static error page. Or actually, one of two different ones
// depending on whether the browser is supported (ie. we think we should be able to load but
// failed) or unsupported (where we tried anyway and, lo and behold, we failed).
logger.error(err); logger.error(err);
// show the static error in an iframe to not lose any context / console data // show the static error in an iframe to not lose any context / console data
// with some basic styling to make the iframe full page // with some basic styling to make the iframe full page

File diff suppressed because one or more lines are too long

View file

@ -44,6 +44,7 @@ import { UPDATE_EVENT } from "matrix-react-sdk/src/stores/AsyncStore";
import { avatarUrlForRoom, getInitialLetter } from "matrix-react-sdk/src/Avatar"; import { avatarUrlForRoom, getInitialLetter } from "matrix-react-sdk/src/Avatar";
import DesktopCapturerSourcePicker from "matrix-react-sdk/src/components/views/elements/DesktopCapturerSourcePicker"; import DesktopCapturerSourcePicker from "matrix-react-sdk/src/components/views/elements/DesktopCapturerSourcePicker";
import { OidcRegistrationClientMetadata } from "matrix-js-sdk/src/matrix"; import { OidcRegistrationClientMetadata } from "matrix-js-sdk/src/matrix";
import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg";
import VectorBasePlatform from "./VectorBasePlatform"; import VectorBasePlatform from "./VectorBasePlatform";
import { SeshatIndexManager } from "./SeshatIndexManager"; import { SeshatIndexManager } from "./SeshatIndexManager";
@ -127,6 +128,19 @@ export default class ElectronPlatform extends VectorBasePlatform {
}); });
}); });
// `userAccessToken` (IPC) is requested by the main process when appending authentication
// to media downloads. A reply is sent over the same channel.
window.electron.on("userAccessToken", () => {
window.electron!.send("userAccessToken", MatrixClientPeg.get()?.getAccessToken());
});
// `serverSupportedVersions` is requested by the main process when it needs to know if the
// server supports a particular version. This is primarily used to detect authenticated media
// support. A reply is sent over the same channel.
window.electron.on("serverSupportedVersions", async () => {
window.electron!.send("serverSupportedVersions", await MatrixClientPeg.get()?.getVersions());
});
// try to flush the rageshake logs to indexeddb before quit. // try to flush the rageshake logs to indexeddb before quit.
window.electron.on("before-quit", function () { window.electron.on("before-quit", function () {
logger.log("element-desktop closing"); logger.log("element-desktop closing");

2907
yarn.lock

File diff suppressed because it is too large Load diff