Merge pull request #3887 from element-hq/fkwp/support_latest_changes_MSC4195

Transitions Element Call from yarn to pnpm.
This commit is contained in:
Timo
2026-04-21 00:20:18 +08:00
committed by GitHub
26 changed files with 13994 additions and 16816 deletions

View File

@@ -1,11 +1,12 @@
#!/usr/bin/sh #!/usr/bin/sh
FILE=.links.temp-disabled.yaml FILE=.links.cjs
if test -f "$FILE"; then FILE_DIS=.links.temp-disabled.cjs
if test -f "$FILE_DIS"; then
# Only do the post-commit hook if the file was temp-disabled by the pre-commit hook. # Only do the post-commit hook if the file was temp-disabled by the pre-commit hook.
# Otherwise linking was actively (`yarn links:disable`) disabled and this hook should noop. # Otherwise linking was actively (`yarn links:disable`) disabled and this hook should noop.
mv .links.temp-disabled.yaml .links.yaml mv $FILE_DIS $FILE
yarnLog=$(yarn) yarnLog=$(yarn)
echo "[yarn-linker] The post-commit hook has re-enabled .links.yaml." echo "[yarn-linker] The post-commit hook has re-enabled $FILE"
exit 1 exit 1
fi fi

View File

@@ -1,11 +1,12 @@
#!/usr/bin/sh #!/usr/bin/sh
FILE=".links.yaml" FILE=.links.cjs
FILE_DIS=.links.temp-disabled.cjs
if test -f "$FILE"; then if test -f "$FILE"; then
mv .links.yaml .links.temp-disabled.yaml mv $FILE .links.temp-disabled.cjs
# echo "running yarn" # echo "running yarn"
x=$(yarn) x=$(pnpm install)
y=$(git add yarn.lock) y=$(git add pnpm-lock.yaml)
echo "[yarn-linker] The pre-commit hook has disabled .links.yaml and MODIFIED the yarn.lock file. Review the staged changes (the hook added yarn.lock, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links." echo "[yarn-linker] The pre-commit hook has disabled $FILE and MODIFIED the pnpm-lock.yaml file. Review the staged changes (the hook added pnpm-lock.yaml, was this desired?) and run \`git commit \` again if they look okay. The post-commit hook will re-enable your links."
exit 1 exit 1
fi fi

View File

@@ -37,15 +37,15 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Enable Corepack - name: Enable Corepack
run: corepack enable run: corepack enable
- name: Yarn cache - name: pnpm cache
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
cache: "yarn" cache: "pnpm"
node-version-file: ".node-version" node-version-file: ".node-version"
- name: Install dependencies - name: Install dependencies
run: "yarn install --immutable" run: "pnpm install --frozen-lockfile"
- name: Build Element Call - name: Build Element Call
run: yarn run build:"$PACKAGE":"$BUILD_MODE" run: pnpm run build:"$PACKAGE":"$BUILD_MODE"
env: env:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}

View File

@@ -12,20 +12,20 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Enable Corepack - name: Enable Corepack
run: corepack enable run: corepack enable
- name: Yarn cache - name: pnpm cache
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
cache: "yarn" cache: "pnpm"
node-version-file: ".node-version" node-version-file: ".node-version"
- name: Install dependencies - name: Install dependencies
run: "yarn install --immutable" run: "pnpm install --frozen-lockfile"
- name: Prettier - name: Prettier
run: "yarn run prettier:check" run: "pnpm run prettier:check"
- name: i18n - name: i18n
run: "yarn run i18n:check" run: "pnpm run i18n:check"
- name: ESLint - name: ESLint
run: "yarn run lint:eslint" run: "pnpm run lint:eslint"
- name: Type check - name: Type check
run: "yarn run lint:types" run: "pnpm run lint:types"
- name: Dead code analysis - name: Dead code analysis
run: "yarn run lint:knip" run: "pnpm run lint:knip"

View File

@@ -14,15 +14,15 @@ jobs:
persist-credentials: false persist-credentials: false
- name: Enable Corepack - name: Enable Corepack
run: corepack enable run: corepack enable
- name: Yarn cache - name: pnpm cache
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
cache: "yarn" cache: "pnpm"
node-version-file: ".node-version" node-version-file: ".node-version"
- name: Install dependencies - name: Install dependencies
run: "yarn install --immutable" run: "pnpm install --frozen-lockfile"
- name: Vitest - name: Vitest
run: "yarn run test:coverage" run: "pnpm run test:coverage"
- name: Upload to codecov - name: Upload to codecov
uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5 uses: codecov/codecov-action@75cd11691c0faa626561e295848008c8a7dddffe # v5
env: env:
@@ -42,12 +42,12 @@ jobs:
run: corepack enable run: corepack enable
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
cache: "yarn" cache: "pnpm"
node-version-file: ".node-version" node-version-file: ".node-version"
- name: Install dependencies - name: Install dependencies
run: yarn install --immutable run: pnpm install --frozen-lockfile
- name: Install Playwright Browsers - name: Install Playwright Browsers
run: yarn playwright install --with-deps run: pnpm exec playwright install --with-deps
- name: Run backend components - name: Run backend components
run: | run: |
docker compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml pull docker compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml pull
@@ -56,7 +56,7 @@ jobs:
- name: Run Playwright tests - name: Run Playwright tests
env: env:
USE_DOCKER: 1 USE_DOCKER: 1
run: yarn playwright test run: pnpm exec playwright test
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
if: ${{ !cancelled() }} if: ${{ !cancelled() }}
with: with:

View File

@@ -22,11 +22,11 @@ jobs:
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4 - uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4
with: with:
cache: "yarn" cache: "pnpm"
node-version-file: ".node-version" node-version-file: ".node-version"
- name: Install Deps - name: Install Deps
run: "yarn install --immutable" run: "pnpm install --frozen-lockfile"
- name: Prune i18n - name: Prune i18n
run: "rm -R locales" run: "rm -R locales"
@@ -40,7 +40,7 @@ jobs:
run: "sudo chown runner:docker -R locales" run: "sudo chown runner:docker -R locales"
- name: Prettier - name: Prettier
run: yarn prettier:format run: pnpm prettier:format
- name: Create Pull Request - name: Create Pull Request
id: cpr id: cpr

5
.gitignore vendored
View File

@@ -21,9 +21,14 @@ yarn-error.log
!/.yarn/releases !/.yarn/releases
!/.yarn/sdks !/.yarn/sdks
!/.yarn/versions !/.yarn/versions
# old yarn based linking
/.links.yaml /.links.yaml
/.links.disabled.yaml /.links.disabled.yaml
/.links.temp-disabled.yaml /.links.temp-disabled.yaml
# pnpm based linking
/.links.cjs
/.links.disabled.cjs
/.links.temp-disabled.cjs
# Playwright # Playwright
/test-results/ /test-results/

58
.pnpmfile.cjs Normal file
View File

@@ -0,0 +1,58 @@
/*
Copyright 2026 Element Creations Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
// Created based on https://github.com/element-hq/element-call/blob/60fae70a60e3697eb41210ccf1e400cab37df7c8/.yarn/plugins/linker.cjs
// and the following prompt history:
// - Can you convert this yarn plugin into a pnpm plugin.
// - The goal is to not have modifications to the package.json and lock files so that we do not track links on gh.
// This seems to modify the package.json file.
// What can we do with pnpm to have the link inforamtion in a seperate file
// - why do you cache the loaded links. When does this file get executed?
// Do we need this optimization.
// How do we guarantee, that we aleays use the most recent content from the links file?
//
// Manual transition to cjs. Claude proposed manual yaml parsing.
const fs = require("fs");
const path = require("path");
function loadLinks() {
try {
return require(path.join(__dirname, ".links.cjs"));
} catch (e) {
return null;
}
}
function readPackage(pkg, context) {
const links = loadLinks();
if (!links) return pkg;
const manifest = JSON.parse(
fs.readFileSync(path.join(__dirname, "package.json"), "utf8"),
);
if (pkg.name !== manifest.name) return pkg;
for (const [name, linkPath] of Object.entries(links)) {
const resolved = `link:${path.resolve(__dirname, linkPath)}`;
if (pkg.dependencies && pkg.dependencies[name]) {
context.log(`Linking ${name} -> ${resolved}`);
pkg.dependencies[name] = resolved;
} else if (pkg.devDependencies && pkg.devDependencies[name]) {
context.log(`Linking ${name} -> ${resolved}`);
pkg.devDependencies[name] = resolved;
}
}
return pkg;
}
module.exports = {
hooks: {
readPackage,
},
};

View File

@@ -1,2 +1,3 @@
pnpm-lock.yaml
node_modules node_modules
dist dist

View File

@@ -1,91 +0,0 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
module.exports = {
name: "linker",
factory: (require) => ({
hooks: {
// Yarn's plugin system is very light on documentation. The best we have
// for this hook is simply the type definition in
// https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-core/sources/Plugin.ts
registerPackageExtensions: async (config, registerPackageExtension) => {
const { structUtils } = require("@yarnpkg/core");
const { parseSyml } = require("@yarnpkg/parsers");
const path = require("path");
const fs = require("fs");
const process = require("process");
// Create a descriptor that we can use to target our direct dependencies
const projectPath = config.projectCwd
.replace(/\\/g, "/")
.replace("/C:/", "C:/");
const manifestPath = path.join(projectPath, "package.json");
const manifest = JSON.parse(fs.readFileSync(manifestPath, "utf8"));
const selfDescriptor = structUtils.parseDescriptor(
`${manifest.name}@*`,
true,
);
// Load the list of linked packages
const linksPath = path.join(projectPath, ".links.yaml");
let linksFile;
try {
linksFile = fs.readFileSync(linksPath, "utf8");
} catch (e) {
return; // File doesn't exist, there's nothing to link
}
let links;
try {
links = parseSyml(linksFile);
} catch (e) {
console.error(".links.yaml has invalid syntax", e);
process.exit(1);
}
// Resolve paths and turn them into a Yarn package extension
const overrides = Object.fromEntries(
Object.entries(links).map(([name, link]) => [
name,
`portal:${path.resolve(config.projectCwd, link)}`,
]),
);
const overrideIdentHashes = new Set();
for (const name of Object.keys(overrides))
overrideIdentHashes.add(
structUtils.parseDescriptor(`${name}@*`, true).identHash,
);
// Extend our own package's dependencies with these local overrides
registerPackageExtension(selfDescriptor, { dependencies: overrides });
// Filter out the original dependencies from the package spec so Yarn
// actually respects the overrides
const filterDependencies = (original) => {
const pkg = structUtils.copyPackage(original);
pkg.dependencies = new Map(
Array.from(pkg.dependencies.entries()).filter(
([, value]) => !overrideIdentHashes.has(value.identHash),
),
);
return pkg;
};
// Patch Yarn's own normalizePackage method to use the above filter
const originalNormalizePackage = config.normalizePackage;
config.normalizePackage = function (pkg, extensions) {
return originalNormalizePackage.call(
this,
pkg.identHash === selfDescriptor.identHash
? filterDependencies(pkg)
: pkg,
extensions,
);
};
},
},
}),
};

View File

@@ -1,3 +0,0 @@
nodeLinker: node-modules
plugins:
- .yarn/plugins/linker.cjs

View File

@@ -3,7 +3,7 @@ networks:
services: services:
auth-service: auth-service:
image: ghcr.io/element-hq/lk-jwt-service:sha-f8ddd00 image: ghcr.io/element-hq/lk-jwt-service:0.4.4
pull_policy: always pull_policy: always
hostname: auth-server hostname: auth-server
environment: environment:
@@ -25,7 +25,7 @@ services:
- ecbackend - ecbackend
auth-service-1: auth-service-1:
image: ghcr.io/element-hq/lk-jwt-service:sha-f8ddd00 image: ghcr.io/element-hq/lk-jwt-service:0.4.4
pull_policy: always pull_policy: always
hostname: auth-server-1 hostname: auth-server-1
environment: environment:

View File

@@ -1,30 +1,34 @@
# Developing with linked packages # Developing with linked packages
If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. Yarn has a command for this (`yarn link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment. If you want to make changes to a package that Element Call depends on and see those changes applied in real time, you can create a link to a local copy of the package. Pnpm has a command for this (`pnpm link`), but it's not recommended to use it as it ends up modifying package.json with details specific to your development environment.
Instead, you can use our little 'linker' plugin. Create a file named `.links.yaml` in the Element Call project directory, listing the names and paths of any dependencies you want to link. For example: Instead, you can use our little 'linker' plugin. Create a file named `.links.cjs` in the Element Call project directory, listing the names and paths of any dependencies you want to link. For example:
```yaml ```cjs
matrix-js-sdk: ../path/to/matrix-js-sdk // Packages to link to local checkouts
"@vector-im/compound-web": /home/alice/path/to/compound-web module.exports = {
"matrix-js-sdk": "../your/path/matrix-js-sdk",
"matrix-widget-api": "../your/path/matrix-widget-api",
};
``` ```
Then run `yarn install`. Then run `pnpm install`.
## Hooks ## Hooks
Changes in `.links.yaml` will also update `yarn.lock` when `yarn` is executed. The lockfile will then contain the local Changes in `.links.yaml` will also update `pnpm-lock.yaml` when `pnpm` is executed. The lockfile will then contain the local
version of the package which would not work on others dev setups or the github CI. version of the package which would not work on others dev setups or the github CI.
One always needs to run: One always needs to run:
```bash ```bash
mv .links.yaml .links.disabled.yaml mv .links.cjs .links.disabled.cjs
yarn yarn
``` ```
before committing a change. before committing a change.
To make it more convenient to work with this linking system we added git hooks for your conviniece. To make it more convenient to work with this linking system we added git hooks.
A `pre-commit` hook will run `mv .links.yaml .links.disabled.yaml`, `yarn` and `git add yarn.lock` if it detects A `pre-commit` hook will run `mv .links.yaml .links.disabled.yaml`, `yarn` and `git add yarn.lock` if it detects
a `.links.yaml` file and abort the commit. a `.links.yaml` file and abort the commit.
You will than need to check if the resulting changes are appropriate and commit again. You will than need to check if the resulting changes are appropriate and commit again.
@@ -35,5 +39,5 @@ before if a `.links.disabled.yaml` is present. It runs `mv .links.disabled.yaml
To activate the hooks automatically configure git with To activate the hooks automatically configure git with
```bash ```bash
git config --local core.hooksPath .githooks/ git config --local core.hooksPath .githooks
``` ```

View File

@@ -3,23 +3,23 @@
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "yarn dev:full", "dev": "pnpm dev:full",
"dev:full": "vite", "dev:full": "vite",
"dev:embedded": "vite --config vite-embedded.config.js", "dev:embedded": "vite --config vite-embedded.config.js",
"build": "yarn build:full", "build": "pnpm build:full",
"build:full": "NODE_OPTIONS=--max-old-space-size=16384 vite build", "build:full": "NODE_OPTIONS=--max-old-space-size=16384 vite build",
"build:full:production": "yarn build:full", "build:full:production": "pnpm build:full",
"build:full:development": "yarn build:full --mode development", "build:full:development": "pnpm build:full --mode development",
"build:embedded": "yarn build:full --config vite-embedded.config.js", "build:embedded": "pnpm build:full --config vite-embedded.config.js",
"build:embedded:production": "yarn build:embedded", "build:embedded:production": "pnpm build:embedded",
"build:embedded:development": "yarn build:embedded --mode development", "build:embedded:development": "pnpm build:embedded --mode development",
"build:sdk:development": "yarn build:sdk --mode development", "build:sdk:development": "pnpm build:sdk --mode development",
"build:sdk": "yarn build:full --config vite-sdk.config.js", "build:sdk": "pnpm build:full --config vite-sdk.config.js",
"build:sdk:production": "yarn build:sdk", "build:sdk:production": "pnpm build:sdk",
"serve": "vite preview", "serve": "vite preview",
"prettier:check": "prettier -c .", "prettier:check": "prettier -c .",
"prettier:format": "prettier -w .", "prettier:format": "prettier -w .",
"lint": "yarn lint:types && yarn lint:eslint && yarn lint:knip", "lint": "pnpm lint:types && pnpm lint:eslint && pnpm lint:knip",
"lint:eslint": "eslint --max-warnings 0 src playwright", "lint:eslint": "eslint --max-warnings 0 src playwright",
"lint:eslint-fix": "eslint --max-warnings 0 src playwright --fix", "lint:eslint-fix": "eslint --max-warnings 0 src playwright --fix",
"lint:knip": "knip", "lint:knip": "knip",
@@ -31,9 +31,9 @@
"backend": "docker-compose -f dev-backend-docker-compose.yml up", "backend": "docker-compose -f dev-backend-docker-compose.yml up",
"backend-playwright": "docker-compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml up", "backend-playwright": "docker-compose -f playwright-backend-docker-compose.yml -f playwright-backend-docker-compose.override.yml up",
"test:playwright": "playwright test", "test:playwright": "playwright test",
"test:playwright:open": "yarn test:playwright --ui", "test:playwright:open": "pnpm test:playwright --ui",
"links:enable": "mv .links.disabled.yaml .links.yaml & touch .links.yaml", "links:enable": "mv .links.disabled.cjs .links.cjs & touch .links.cjs",
"links:disable": "mv .links.yaml .links.disabled.yaml", "links:disable": "mv .links.cjs .links.disabled.cjs",
"storybook": "storybook dev -p 6006", "storybook": "storybook dev -p 6006",
"build-storybook": "storybook build" "build-storybook": "storybook build"
}, },
@@ -110,7 +110,7 @@
"livekit-client": "^2.18.1", "livekit-client": "^2.18.1",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"loglevel": "^1.9.1", "loglevel": "^1.9.1",
"matrix-js-sdk": "matrix-org/matrix-js-sdk#6e3efef0c5f660df47cf00874927dec1c75cc3cf", "matrix-js-sdk": "matrix-org/matrix-js-sdk#develop",
"matrix-widget-api": "^1.16.1", "matrix-widget-api": "^1.16.1",
"node-stdlib-browser": "^1.3.1", "node-stdlib-browser": "^1.3.1",
"normalize.css": "^8.0.1", "normalize.css": "^8.0.1",
@@ -137,19 +137,24 @@
"vite": "^8.0.0", "vite": "^8.0.0",
"vite-plugin-generate-file": "^0.3.0", "vite-plugin-generate-file": "^0.3.0",
"vite-plugin-html": "^3.2.2", "vite-plugin-html": "^3.2.2",
"vite-plugin-node-polyfills": "^0.26.0",
"vite-plugin-node-stdlib-browser": "^0.2.1", "vite-plugin-node-stdlib-browser": "^0.2.1",
"vite-plugin-svgr": "^4.0.0", "vite-plugin-svgr": "^4.0.0",
"vite-plugin-wasm": "^3.6.0",
"vitest": "^4.0.18", "vitest": "^4.0.18",
"vitest-axe": "^1.0.0-pre.3" "vitest-axe": "^1.0.0-pre.3"
}, },
"resolutions": { "pnpm": {
"@livekit/components-core/rxjs": "^7.8.1", "overrides": {
"@livekit/track-processors/@mediapipe/tasks-vision": "^0.10.18", "@livekit/components-core>rxjs": "^7.8.1",
"minimatch": "^10.2.3", "@livekit/track-processors>@mediapipe/tasks-vision": "^0.10.18",
"tar": "^7.5.11", "minimatch": "^10.2.3",
"glob": "^10.5.0", "tar": "^7.5.11",
"qs": "^6.14.1", "glob": "^10.5.0",
"js-yaml": "^4.1.1" "qs": "^6.14.1",
"js-yaml": "^4.1.1",
"esbuild": "^0.27.7"
}
}, },
"packageManager": "yarn@4.7.0" "packageManager": "pnpm@9.0.0"
} }

13760
pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -5,5 +5,5 @@ set -ex
export VITE_APP_VERSION=$(git describe --tags --abbrev=0) export VITE_APP_VERSION=$(git describe --tags --abbrev=0)
corepack enable corepack enable
yarn install pnpm install
yarn run build pnpm run build

View File

@@ -1,10 +1,10 @@
#!/bin/sh #!/bin/sh
if [ -n "$USE_DOCKER" ]; then if [ -n "$USE_DOCKER" ]; then
set -ex set -ex
yarn build pnpm build
docker build -t element-call:testing . docker build -t element-call:testing .
exec docker run --rm --name element-call-testing -p 8080:8080 -v ./config/config.devenv.json:/app/config.json:ro,Z element-call:testing exec docker run --rm --name element-call-testing -p 8080:8080 -v ./config/config.devenv.json:/app/config.json:ro,Z element-call:testing
else else
cp config/config.devenv.json public/config.json cp config/config.devenv.json public/config.json
exec yarn dev exec pnpm dev --host
fi fi

View File

@@ -17,7 +17,7 @@ exports[`InCallView > rendering > renders 1`] = `
> >
<span <span
aria-label="" aria-label=""
class="_avatar_7h2br_8 roomAvatar _avatar-imageless_7h2br_55" class="_avatar_va14e_8 roomAvatar _avatar-imageless_va14e_55"
data-color="1" data-color="1"
data-type="round" data-type="round"
role="img" role="img"

View File

@@ -204,7 +204,7 @@ exports[`DeveloperSettingsTab > renders and matches snapshot 1`] = `
> >
<input <input
aria-describedby="radix-_r_7_" aria-describedby="radix-_r_7_"
class="_control_sqdq4_10" class="_control_d83jn_10"
id="radix-_r_6_" id="radix-_r_6_"
name="input" name="input"
title="" title=""

View File

@@ -802,7 +802,6 @@ export function enterRTCSession(
makeKeyDelay: matrixRtcSessionConfig?.wait_for_key_rotation_ms, makeKeyDelay: matrixRtcSessionConfig?.wait_for_key_rotation_ms,
membershipEventExpiryMs: membershipEventExpiryMs:
matrixRtcSessionConfig?.membership_event_expiry_ms, matrixRtcSessionConfig?.membership_event_expiry_ms,
useExperimentalToDeviceTransport: true,
unstableSendStickyEvents: matrixRTCMode === MatrixRTCMode.Matrix_2_0, unstableSendStickyEvents: matrixRTCMode === MatrixRTCMode.Matrix_2_0,
}, },
); );

View File

@@ -74,7 +74,26 @@ const panNode = vi.mocked(
* It can also be used to mock the `AudioContext` constructor in tests: * It can also be used to mock the `AudioContext` constructor in tests:
* `vi.stubGlobal("AudioContext", () => testAudioContext);` * `vi.stubGlobal("AudioContext", () => testAudioContext);`
*/ */
export const testAudioContext = { export const testAudioContext: Partial<AudioContext> & {
gain: ReturnType<
typeof vi.mocked<{
connect: (node: AudioNode) => AudioNode;
gain: { setValueAtTime: ReturnType<typeof vi.fn>; value: number };
}>
>;
pan: ReturnType<
typeof vi.mocked<{
connect: (node: AudioNode) => AudioNode;
pan: { setValueAtTime: ReturnType<typeof vi.fn>; value: number };
}>
>;
setSinkId: ReturnType<typeof vi.fn>;
decodeAudioData: ReturnType<typeof vi.fn>;
createBufferSource: ReturnType<typeof vi.fn>;
createGain: ReturnType<typeof vi.fn>;
createStereoPanner: ReturnType<typeof vi.fn>;
close: ReturnType<typeof vi.fn>;
} = {
gain: gainNode, gain: gainNode,
pan: panNode, pan: panNode,
setSinkId: vi.fn().mockResolvedValue(undefined), setSinkId: vi.fn().mockResolvedValue(undefined),

View File

@@ -15,6 +15,7 @@ import {
vitest, vitest,
} from "vitest"; } from "vitest";
import { import {
EventType,
MatrixEvent, MatrixEvent,
type Room as MatrixRoom, type Room as MatrixRoom,
type Room, type Room,
@@ -255,6 +256,7 @@ export function mockRtcMembership(
const event = new MatrixEvent({ const event = new MatrixEvent({
sender: userId, sender: userId,
event_id: `$-ev-${randomUUID()}:example.org`, event_id: `$-ev-${randomUUID()}:example.org`,
type: EventType.GroupCallMemberPrefix,
content: data, content: data,
}); });
@@ -466,7 +468,9 @@ export class MockRTCSession extends TypedEventEmitter<
counters: {}, counters: {},
}; };
public leaveRoomSession = vitest.fn().mockResolvedValue(undefined); public leaveRoomSession: ReturnType<typeof vitest.fn> = vitest
.fn()
.mockResolvedValue(undefined);
public constructor( public constructor(
public readonly room: Room, public readonly room: Room,
@@ -496,7 +500,7 @@ export class MockRTCSession extends TypedEventEmitter<
return this; return this;
} }
public updateCallIntent = vitest public updateCallIntent: ReturnType<typeof vitest.fn> = vitest
.fn() .fn()
.mockImplementation(async () => Promise.resolve()); .mockImplementation(async () => Promise.resolve());

View File

@@ -51,3 +51,53 @@ window.matchMedia = global.matchMedia = (): MediaQueryList =>
addEventListener: () => {}, addEventListener: () => {},
removeEventListener: () => {}, removeEventListener: () => {},
}) as Partial<MediaQueryList> as MediaQueryList; }) as Partial<MediaQueryList> as MediaQueryList;
const storage: Record<string, string> = {};
const localStoragePolyfill = {
getItem(key: string) {
return Object.prototype.hasOwnProperty.call(storage, key)
? storage[key]
: null;
},
setItem(key: string, value: string) {
storage[key] = String(value);
},
removeItem(key: string) {
delete storage[key];
},
clear() {
for (const key in storage) {
delete storage[key];
}
},
key(index: number) {
const keys = Object.keys(storage);
return keys[index] ?? null;
},
get length() {
return Object.keys(storage).length;
},
} as unknown as Storage;
if (
typeof globalThis.localStorage === "undefined" ||
typeof globalThis.localStorage.clear !== "function"
) {
Object.defineProperty(globalThis, "localStorage", {
value: localStoragePolyfill,
writable: true,
configurable: true,
});
}
if (
typeof window !== "undefined" &&
(typeof window.localStorage === "undefined" ||
typeof window.localStorage.clear !== "function")
) {
Object.defineProperty(window, "localStorage", {
value: localStoragePolyfill,
writable: true,
configurable: true,
});
}

View File

@@ -17,6 +17,8 @@ import { createHtmlPlugin } from "vite-plugin-html";
import { codecovVitePlugin } from "@codecov/vite-plugin"; import { codecovVitePlugin } from "@codecov/vite-plugin";
import { sentryVitePlugin } from "@sentry/vite-plugin"; import { sentryVitePlugin } from "@sentry/vite-plugin";
import { nodePolyfills } from "vite-plugin-node-polyfills";
import wasm from "vite-plugin-wasm";
import react from "@vitejs/plugin-react"; import react from "@vitejs/plugin-react";
import { realpathSync } from "fs"; import { realpathSync } from "fs";
@@ -36,6 +38,11 @@ export default ({
process.env.VITE_PACKAGE = packageType ?? "full"; process.env.VITE_PACKAGE = packageType ?? "full";
const plugins: PluginOption[] = [ const plugins: PluginOption[] = [
react(), react(),
wasm(),
nodePolyfills({
// Enables the 'events' module, which is required by the matrix-js-sdk
include: ["events"],
}),
svgrPlugin({ svgrPlugin({
svgrOptions: { svgrOptions: {
// This enables ref forwarding on SVGR components, which is needed, for // This enables ref forwarding on SVGR components, which is needed, for
@@ -43,7 +50,6 @@ export default ({
ref: true, ref: true,
}, },
}), }),
codecovVitePlugin({ codecovVitePlugin({
enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined, enableBundleAnalysis: process.env.CODECOV_TOKEN !== undefined,
bundleName: "element-call", bundleName: "element-call",
@@ -150,12 +156,5 @@ export default ({
"@radix-ui/react-dismissable-layer", "@radix-ui/react-dismissable-layer",
], ],
}, },
// Vite is using esbuild in development mode, which doesn't work with the wasm loader
// in matrix-sdk-crypto-wasm, so we need to exclude it here. This doesn't affect the
// production build (which uses rollup) which still works as expected.
// https://vite.dev/guide/why.html#why-not-bundle-with-esbuild
optimizeDeps: {
exclude: ["@matrix-org/matrix-sdk-crypto-wasm"],
},
}; };
}; };

View File

@@ -17,8 +17,9 @@ export default defineConfig((configEnv) =>
include: ["src/**/*.test.ts", "src/**/*.test.tsx"], include: ["src/**/*.test.ts", "src/**/*.test.tsx"],
coverage: { coverage: {
reporter: ["html", "json"], reporter: ["html", "json"],
include: ["src/"], include: ["src/**/*.{ts,tsx,js,jsx}"],
exclude: [ exclude: [
"src/**/*.md",
"src/**/*.{d,test,stories}.{ts,tsx}", "src/**/*.{d,test,stories}.{ts,tsx}",
"src/utils/test.ts", "src/utils/test.ts",
"src/utils/test-viewmodel.ts", "src/utils/test-viewmodel.ts",

16635
yarn.lock

File diff suppressed because it is too large Load Diff