Compare commits

..

64 Commits

Author SHA1 Message Date
fkwp
e98b0ed1ed indentation 2025-04-11 00:06:03 +02:00
fkwp
d97332f47a Merge branch 'livekit' into fkwp/doc_update 2025-04-09 20:30:24 +02:00
fkwp
6551ce8e18 Merge pull request #3178 from nordeck/fix-selfhosting-docs
Update self-hosting.md docs formatting
2025-04-09 20:30:01 +02:00
fkwp
3c5594b7e1 prettier 2025-04-09 13:34:58 +02:00
fkwp
eb9593a4e5 add information about CORS headers 2025-04-09 13:16:25 +02:00
fkwp
078f36c14a add Community Guides & How-Tos section 2025-04-09 13:04:41 +02:00
Kim Brose
7297dbcc00 Update self-hosting.md docs formatting 2025-04-09 11:32:56 +02:00
fkwp
ba382eef75 Merge pull request #3175 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.10.0
2025-04-08 16:45:36 +02:00
fkwp
23b1a5fff5 cleanup yarn.lock 2025-04-08 16:39:09 +02:00
fkwp
95fed3fc2d bump to 2.10.0 2025-04-08 09:52:48 +02:00
renovate[bot]
6398fd2783 Update dependency livekit-client to v2.9.9 2025-04-08 07:15:13 +00:00
fkwp
e8f0398f59 Merge pull request #3165 from element-hq/fkwp/update_readme
Update readme
2025-04-08 08:52:01 +02:00
Timo
a7dc289b2d Add yarn and bundled element call renovate group. (#3173) 2025-04-07 17:52:19 +02:00
fkwp
db10903ea0 Update README.md
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
2025-04-07 16:58:07 +02:00
fkwp
ca1410bc85 hint towards cs api 2025-04-07 11:30:34 +02:00
fkwp
c78360fce2 Update README.md
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
2025-04-05 19:29:08 +02:00
renovate[bot]
e5358e8609 Update dependency vite to v6.2.5 [SECURITY] (#3169)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-04 23:26:09 +02:00
Valere Fedronic
bc0ea20343 Default vite config to support using local build of crypto wasm (#3038)
* Devex: Default vite config to support using local build of crypto wasm

* use realpathSync and make it work with linked and not-linked
We need to use sync because an async defineConfig fails for the embedded exports.

* also allow just linking matrix-sdk-crypto-wasm (without js-sdk linking)
---------

Co-authored-by: Timo <toger5@hotmail.de>
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
Co-authored-by: Robin <robin@robin.town>
2025-04-04 23:24:42 +02:00
fkwp
ab8a86e451 prettier 2025-04-04 23:12:41 +02:00
fkwp
45b0a5c2a6 reordering 2025-04-04 23:12:41 +02:00
fkwp
c20aa5c1c8 rephrase Packaging and adding Figures 2025-04-04 23:12:41 +02:00
fkwp
d5481d8c20 indentation 2025-04-04 23:12:41 +02:00
fkwp
bef57b677c center images 2025-04-04 23:12:41 +02:00
fkwp
ce1c5437fc add note about in-app calling requirements 2025-04-04 23:12:41 +02:00
fkwp
46f059947b Merge pull request #3168 from element-hq/toger5/add-link-disable-enable-scripts
Add yarn scripts for disabling/enabling `.links.yaml`
2025-04-04 15:31:00 +02:00
fkwp
cf0cb2ebd2 Merge pull request #3153 from element-hq/renovate/github-actions
Pin dependencies
2025-04-04 15:28:57 +02:00
fkwp
2b35db3f39 Merge pull request #3145 from element-hq/toger5/github-release-note-categories
Add simple release note automation
2025-04-04 15:26:51 +02:00
Timo
a3f01a35c8 Add yarn scripts for disabling/enabling .links.yaml 2025-04-04 12:35:21 +02:00
Timo
14b3e49de6 Use PR- labels 2025-04-04 11:34:44 +02:00
Timo
6ceaa073a9 Add simple release note automation 2025-04-04 11:34:44 +02:00
Valere Fedronic
deac07dd13 Merge pull request #3163 from element-hq/valere/add_missing_to_device_permission
Widget: Add missing to device permission for encryption keys
2025-04-04 09:37:40 +02:00
Valere
f0126f41fb Widget: Add missing to device permission for encryption keys 2025-04-04 09:32:34 +02:00
Valere Fedronic
8bd44344e7 Merge pull request #3164 from element-hq/toger5/fix-src-js-sdk-imports
Fix lint and playwright errors caused by matrix-js-sdk/src import
2025-04-04 09:31:24 +02:00
Valere
9b945d00f7 cleaning: Remove deprecated config option for EC url 2025-04-04 09:18:58 +02:00
Valere
e9e82ca3e1 Cleaning + update docker compose pull policy for eweb 2025-04-04 09:12:27 +02:00
Timo
c91d9e5790 do the setting set later 2025-04-03 18:06:38 +02:00
Timo
7561e33e38 use localhost ew 2025-04-03 18:01:43 +02:00
Timo
afced3eb73 test fix experiment 2025-04-03 17:02:48 +02:00
Timo
70c97fa8be Fix lint errors caused by matrix-js-sdl/src import 2025-04-03 15:51:47 +02:00
Valere Fedronic
9acc1d1fe9 Merge pull request #3123 from element-hq/valere/playwright_widget_tests
Test: End to end integrated test for ElementCall in widget mode
2025-04-03 09:52:45 +02:00
renovate[bot]
622d91d7cc Update dependency vite to v6.2.4 [SECURITY] (#3151)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 11:12:25 +02:00
renovate[bot]
e7086ff8fc Pin dependencies 2025-04-01 02:20:37 +00:00
ElementRobot
5f0c3435fa Merge pull request #3152 from element-hq/actions/localazy-download
Localazy Download
2025-03-31 22:36:50 +02:00
fkwp
18972c2fb9 Translations updates 2025-03-31 20:33:53 +00:00
Hugh Nimmo-Smith
d1753c33f5 Use correct rageshake URL when running in embedded package + tests (#3132)
* Use correct rageshake URL when running in embedded package

It was incorrectly trying to use the one from config.json

* Refactor to add tests

* Empty mock config
2025-03-31 16:38:25 +01:00
Hugh Nimmo-Smith
e4c222a4e8 Expose version string in embedded SwiftPM and AAR (#3144)
* Expose version string in embedded SwiftPM and AAR

Implements https://github.com/element-hq/element-call/issues/3143

* Fix filename

* Fix location of `Version.kt`

* Use the right path for the sed replacement in the publishing workflow for Android

---------

Co-authored-by: Jorge Martín <jorgem@element.io>
2025-03-31 14:55:20 +01:00
fkwp
d12d616e28 Merge pull request #3136 from element-hq/fkwp/update_readme
Fix example JWT service .well-known endpoints in self-hosting.md
2025-03-31 15:08:57 +02:00
Timo
2073cd3ac1 Rename EULA to SSLA (#3135)
* Change EULA to SSLA
 - rename i18n fields
 - update the config property to `ssla` and deprecate `eula`
 - use `eula` instead of ssla in case it is provided in the config.

* fix default config

* completely remove eula fallback
2025-03-31 14:18:45 +02:00
Hugh Nimmo-Smith
9f2f1d8641 Improve documentation for how to use the embedded package (#3146) 2025-03-28 18:26:22 +00:00
Hugh Nimmo-Smith
fd2c1f6410 Clarify who is responsible for compliance and consent in relation to analytics (#3116)
It varies depending on if you are using the full or embedded package.
2025-03-28 14:18:53 +00:00
Hugh Nimmo-Smith
1be0733011 Always run build CI workflow (#3139)
As identified in https://github.com/element-hq/element-call/pull/3116#issuecomment-2759148857 depending on the contents of a PR it may not be possible to merge due to required workflows not actually being run.

This change will mean that the build CI workflow is run irrespective of the contents.
2025-03-28 15:06:00 +01:00
Hugh Nimmo-Smith
bfd4bb2ec1 Show URL params and environment variables in developer tab (#3134) 2025-03-27 16:35:31 -04:00
Robin
f845397b87 Merge pull request #3093 from element-hq/toger5/src-to-lib-import
Transition from consuming js-sdk source to `lib` (build output)
2025-03-27 16:13:05 -04:00
Robin
aab4efe03a Use type imports consistently 2025-03-27 16:09:59 -04:00
Robin
eb18cbef78 Consolidate imports 2025-03-27 16:04:03 -04:00
Robin
ae339ea5cc Fix formatting issues 2025-03-27 14:47:01 -04:00
Robin
33700d1529 Merge branch 'livekit' into toger5/src-to-lib-import 2025-03-27 14:35:08 -04:00
Robin
21140f6f2c Merge pull request #3095 from element-hq/robin/berry
Upgrade to Yarn v4 (Berry)
2025-03-27 14:21:10 -04:00
fkwp
53fa21b97a update .well-known example using the proposed endpoint routing 2025-03-26 22:36:47 +01:00
Valere
0fbde40359 test: End to end integrated test for call widget 2025-03-25 16:09:38 +01:00
Timo
6f93a037cf import cleanups 2025-03-13 18:00:24 -04:00
Timo
f0545ced65 make it work withotu js-sdk changes 2025-03-13 18:00:24 -04:00
Timo
46f5c44db0 temp2 2025-03-13 18:00:07 -04:00
Timo
adb5934f0b temp 2025-03-13 17:51:41 -04:00
152 changed files with 1160 additions and 469 deletions

30
.github/realease.yml vendored Normal file
View File

@@ -0,0 +1,30 @@
changelog:
categories:
- title: 🛠 Breaking Changes
labels:
- PR-Breaking-Change
- title: ✨ Features
labels:
- PR-Feature
- title: 🙌 Improvements
labels:
- PR-Improvement
- title: 📄 Documentation
labels:
- PR-Documentation
- title: 🐛 Bugfixes
labels:
- PR-Bug-Fix
- title: 💾 Developer Experience
labels:
- PR-Developer-Experience
- title: Others
labels:
- "*"
exclude:
labels:
- PR-Task
- dependencies
- title: 👒 Dependencies
labels:
- dependencies

View File

@@ -10,7 +10,7 @@ jobs:
pull-requests: read
steps:
- name: Add notice
uses: actions/github-script@v7
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7
if: contains(github.event.pull_request.labels.*.name, 'X-Blocked')
with:
script: |

View File

@@ -26,7 +26,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 📥 Download artifact
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ inputs.artifact_run_id }}
@@ -34,7 +34,7 @@ jobs:
path: dist
- name: Log in to container registry
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0
uses: docker/login-action@74a5d142397b4f367a81961eba4e8cd7edddf772 # v3.4.0
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}

View File

@@ -31,7 +31,7 @@ jobs:
- name: Enable Corepack
run: corepack enable
- name: Yarn cache
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
@@ -60,7 +60,7 @@ jobs:
VITE_APP_VERSION: ${{ inputs.vite_app_version }}
NODE_OPTIONS: "--max-old-space-size=4096"
- name: Upload Artifact
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: build-output-${{ inputs.package }}
path: dist

View File

@@ -5,16 +5,8 @@ on:
- synchronize
- opened
- labeled
paths-ignore:
- ".github/ISSUE_TEMPLATE/**"
- ".github/CODEOWNERS"
- "docs/**"
push:
branches: [livekit, full-mesh]
paths-ignore:
- ".github/ISSUE_TEMPLATE/**"
- ".github/CODEOWNERS"
- "docs/**"
jobs:
build_full_element_call:
# Use the full package vite build

View File

@@ -46,7 +46,7 @@ jobs:
Exercise caution. Use test accounts.
- name: 📥 Download artifact
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
run-id: ${{ inputs.artifact_run_id }}

View File

@@ -11,7 +11,7 @@ jobs:
- name: Enable Corepack
run: corepack enable
- name: Yarn cache
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"

View File

@@ -42,7 +42,7 @@ jobs:
- name: Determine filename
run: echo "FILENAME_PREFIX=element-call-embedded-${VERSION:1}" >> "$GITHUB_ENV"
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -73,7 +73,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -82,7 +82,7 @@ jobs:
# n.b. We don't enable corepack here because we are using plain npm
- name: Setup node
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
node-version-file: .node-version
registry-url: "https://registry.npmjs.org"
@@ -108,7 +108,7 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -124,6 +124,9 @@ jobs:
- name: Get artifact version
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
- name: Set version string
run: sed -i "s/0.0.0/${{ env.ARTIFACT_VERSION }}/g" embedded/android/lib/src/main/kotlin/io/element/android/call/embedded/Version.kt
- name: Publish AAR
working-directory: embedded/android
env:
@@ -148,7 +151,7 @@ jobs:
path: element-call
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
@@ -165,13 +168,16 @@ jobs:
- name: Copy files
run: rsync -a --delete --exclude .git element-call/embedded/ios/ element-call-swift
- name: Get artifact version
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
- name: Set version string
run: sed -i "s/0.0.0/${{ env.ARTIFACT_VERSION }}/g" element-call-swift/Sources/EmbeddedElementCall/EmbeddedElementCall.swift
- name: Test build
working-directory: element-call-swift
run: swift build
- name: Get artifact version
run: echo "ARTIFACT_VERSION=${VERSION:1}" >> "$GITHUB_ENV"
- name: Commit and tag
working-directory: element-call-swift
run: |

View File

@@ -31,7 +31,7 @@ jobs:
- name: Determine filename
run: echo "FILENAME_PREFIX=element-call-${VERSION:1}" >> "$GITHUB_ENV"
- name: 📥 Download built element-call artifact
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
uses: actions/download-artifact@95815c38cf2ff2164869cbab79da8d1f422bc89e # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}

View File

@@ -13,7 +13,7 @@ jobs:
- name: Enable Corepack
run: corepack enable
- name: Yarn cache
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
@@ -33,10 +33,10 @@ jobs:
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-node@v4
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
@@ -52,7 +52,7 @@ jobs:
run: cp config/config.devenv.json public/config.json
- name: Run Playwright tests
run: yarn playwright test
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
if: ${{ !cancelled() }}
with:
name: playwright-report

View File

@@ -18,7 +18,7 @@ jobs:
- name: Enable Corepack
run: corepack enable
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
- uses: actions/setup-node@cdca7365b2dadb8aad0a33bc7601856ffabcc48e # v4
with:
cache: "yarn"
node-version-file: ".node-version"
@@ -42,7 +42,7 @@ jobs:
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # v7.0.7
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
branch: actions/localazy-download

2
.gitignore vendored
View File

@@ -26,4 +26,4 @@ yarn-error.log
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/
/playwright/.cache/

103
README.md
View File

@@ -45,30 +45,35 @@ organize the flow of the meeting.
**Emoji Reactions** Users can react with emojis 👍️ 🎉 👏 🤘, adding
engagement and interactivity to the conversation.
## 🚀 Deployment Options
## 🚀 Deployment & Packaging Options
Element Call can be packaged in two ways:
Element Call is developed using the
[Matrix js-sdk](https://github.com/matrix-org/matrix-js-sdk) with Matroska mode.
This allows the app to run either as a Standalone App directly connected to a
homeserver with login interfaces or it can be used as a widget within a Matrix
client.
**Full Package** Supports both **Standalone** and **Widget** mode. Hosted as
a static web page and accessed via a URL when used as a widget.
### 🖥️ Standalone Mode
**Embedded Package** Designed for **Widget mode** only. Bundled with a
messenger app for seamless integration. This is the recommended method for
embedding Element Call into a messenger app.
<p align="center">
<img src="./docs/element_call_standalone.drawio.png" alt="Element Call in Standalone Mode">
</p>
See the [here](./docs/embedded-standalone.md) for more information on the packages.
### Standalone mode
![Element Call in Standalone Mode](./docs/element_call_standalone.drawio.png)
In Standalone mode Element Call operates as an independent, full-featured video
conferencing web application, allowing users to join or host calls without
In Standalone mode, Element Call operates as an independent, full-featured video
conferencing web application, enabling users to join or host calls without
requiring a separate Matrix client.
### Widget mode embedded in Messenger Apps
### 📲 In-App Calling (Widget Mode in Messenger Apps)
![Element Call in Widget Mode](./docs/element_call_widget.drawio.png)
When used as a widget 🧩, Element Call is solely responsible on the core calling
functionality (MatrixRTC). Authentication, event handling, and room state
updates (via the Client-Server API) are handled by the hosting client.
Communication between Element Call and the client is managed through the widget
API.
<p align="center">
<img src="./docs/element_call_widget.drawio.png" alt="Element Call in Widget Mode">
</p>
Element Call can be embedded as a widget inside apps like
[**Element Web**](https://github.com/element-hq/element-web) or **Element X
@@ -80,6 +85,30 @@ and voice calls within Matrix rooms.
> [!IMPORTANT]
> Embedded packaging is recommended for Element Call in widget mode!
### 📦 Element Call Packaging
Element Call offers two packaging options: one for standalone or widget
deployment, and another for seamless widget-based integration into messenger
apps. Below is an overview of each option.
**Full Package** Supports both **Standalone** and **Widget** mode. It is
hosted as a static web page and can be accessed via a URL when used as a widget.
<p align="center">
<img src="./docs/full_package.drawio.png" alt="Element Call Full Package">
</p>
**Embedded Package** Designed specifically for **Widget mode** only. It is
bundled with a messenger app for seamless integration and this is the
recommended method for embedding Element Call.
<p align="center">
<img src="./docs/embedded_package.drawio.png" alt="Element Call Embedded Package">
</p>
For more details on the packages, see the
[Embedded vs. Standalone Guide](./docs/embedded-standalone.md).
## 🛠️ Self-Hosting
For operating and deploying Element Call on your own server, refer to the
@@ -91,13 +120,15 @@ For proper Element Call operation each site deployment needs a MatrixRTC backend
setup as outlined in the [Self-Hosting](#self-hosting). A typical federated site
deployment for three different sites A, B and C is depicted below.
![Element Call federated setup](./docs/Federated_Setup.drawio.png)
<p align="center">
<img src="./docs/Federated_Setup.drawio.png" alt="Element Call federated setup">
</p>
### Backend Discovery
MatrixRTC backend (according to
[MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143))
is announced by the Matrix site's `.well-known/matrix/client` file and discovered
[MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143)) is
announced by the Matrix site's `.well-known/matrix/client` file and discovered
via the `org.matrix.msc4143.rtc_foci` key, e.g.:
```json
@@ -130,8 +161,11 @@ points them to a Matrix LiveKit JWT Auth Service via `livekit_service_url`.
The example below illustrates how backend selection works across **Matrix
federation**, using the setup from sites A, B, and C. It demonstrates backend
selection for **Matrix rooms 123 and 456**, which include users from different
homeservers.
![Element Call SFU selection over Matrix federation](./docs/SFU_selection.drawio.png)
homeservers.
<p align="center">
<img src="./docs/SFU_selection.drawio.png" alt="Element Call SFU selection over Matrix federation">
</p>
## 🌍 Translation
@@ -198,21 +232,23 @@ yarn backend
### Playwright tests
Our Playwright tests run automatically as part of our CI along with our other tests,
on every pull request.
Our Playwright tests run automatically as part of our CI along with our other
tests, on every pull request.
You may need to follow instructions to set up your development environment for running
Playwright by following <https://playwright.dev/docs/browsers#install-browsers> and
You may need to follow instructions to set up your development environment for
running Playwright by following
<https://playwright.dev/docs/browsers#install-browsers> and
<https://playwright.dev/docs/browsers#install-system-dependencies>.
However the Playwright tests are run, an element-call instance must be running on
https://localhost:3000 (this is configured in `playwright.config.ts`) - this is what will
be tested.
However the Playwright tests are run, an element-call instance must be running
on https://localhost:3000 (this is configured in `playwright.config.ts`) - this
is what will be tested.
The local backend environment should be running for the test to work:
`yarn backend`
There are a few different ways to run the tests yourself. The simplest is to run:
There are a few different ways to run the tests yourself. The simplest is to
run:
```shell
yarn run test:playwright
@@ -237,8 +273,8 @@ to test visibility, text content and clicking.
##### Investigate a failed test from the CI
In the failed action page, click on the failed job, then scroll down to the `upload-artifact` step.
You will find a link to download the zip report, as per:
In the failed action page, click on the failed job, then scroll down to the
`upload-artifact` step. You will find a link to download the zip report, as per:
```
Artifact playwright-report has been successfully uploaded! Final size is 1360358 bytes. Artifact ID is 2746265841
@@ -252,7 +288,8 @@ npx playwright show-report ~/Downloads/playwright-report/
```
Under the failed test there is a small icon looking like "3 columns" (next to
the test name file name), click on it to see the live screenshots/console output.
the test name file name), click on it to see the live screenshots/console
output.
### Test Coverage

28
WIDGET_TEST.md Normal file
View File

@@ -0,0 +1,28 @@
# Testing Element-Call in widget mode
When running `yarn backend` the latest element-web develop will be deployed and served on `http://localhost:8081`.
In a development environment, you might prefer to just use the `element-web` repo directly, but this setup is useful for CI/CD testing.
## Setup
The element-web configuration is modified to:
- Enable to use the local widget instance (`element_call.url` https://localhost:3000).
- Enable the labs features (`feature_group_calls`, `feature_element_call_video_rooms`).
The default configuration used by docker-compose is in `test-container/config.json`. There is a fixture for playwright
that uses
## Running the element-web instance
It is part of the existing backend setup. To start the backend, run:
```sh
yarn backend
```
Then open `http://localhost:8081` in your browser.
## Basic fixture
A base fixture is provided in `/playwright/fixtures/widget-user.ts` that will register two users that shares a room.

View File

@@ -0,0 +1,53 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "http://synapse.localhost:8008",
"server_name": "synapse.localhost"
}
},
"disable_custom_urls": false,
"disable_guests": false,
"disable_login_language_selector": false,
"disable_3pid_login": false,
"force_verification": false,
"brand": "Element",
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"default_widget_container_height": 280,
"default_country_code": "GB",
"show_labs_settings": false,
"features": {
"feature_element_call_video_rooms": true,
"feature_video_rooms": true,
"feature_group_calls": true,
"feature_release_announcement": false
},
"default_federate": true,
"default_theme": "light",
"room_directory": {
"servers": ["matrix.org"]
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"setting_defaults": {
"breadcrumbs": true,
"feature_group_calls": true
},
"jitsi": {
"preferred_domain": "meet.element.io"
},
"element_call": {
"participant_limit": 8,
"brand": "Element Call"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}

View File

@@ -11,5 +11,5 @@
"features": {
"feature_use_device_session_member_events": true
},
"eula": "https://static.element.io/legal/online-EULA.pdf"
"ssla": "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf"
}

View File

@@ -11,5 +11,5 @@
"features": {
"feature_use_device_session_member_events": true
},
"eula": "https://static.element.io/legal/online-EULA.pdf"
"ssla": "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf"
}

View File

@@ -68,6 +68,18 @@ services:
networks:
- ecbackend
element-web:
image: ghcr.io/element-hq/element-web:develop
pull_policy: always
volumes:
- ./backend/ew.test.config.json:/app/config.json
environment:
ELEMENT_WEB_PORT: 81
ports:
- "8081:81"
networks:
- ecbackend
nginx:
# openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout tls_localhost_key.pem -out tls_localhost_cert.pem -subj "/C=GB/ST=London/L=London/O=Alros/OU=IT Department/CN=localhost"
hostname: synapse.localhost

View File

@@ -1,17 +1,32 @@
## Element Call packages
Element Call is available as two different packages: Full Package and Embedded Package. The Full Package is designed for standalone use, while the Embedded Package is designed for widget mode only. The table below provides a comparison of the two packages:
Element Call is available as two different packages: Full Package and Embedded Package.
| | Full Package | Embedded Package |
| ------------------------------ | ------------------------------------------------------------------------ | ------------------------------------------------------- |
| **Supports use as standalone** | ✅ | ❌ |
| **Supports use as widget** | ✅ | ✅ |
| **Deployment mode** | Hosted as a static web page and accessed via a URL when used as a widget | Bundled within a messenger app for seamless integration |
| **Release artifacts** | Docker Image, Tarball | Tarball, NPM for Web, Android AAR, SwiftPM for iOS |
| **Recommended for** | Standalone/guest access usage | Embedding within messenger apps |
The Full Package is designed for standalone use, while the Embedded Package is designed for widget mode only.
For examples of how to use the platform specific release artifacts (e.g. Android AAR) see
the Element Messenger apps for: [Web](https://github.com/element-hq/element-web), [iOS](https://github.com/element-hq/element-x-ios) and [Android](https://github.com/element-hq/element-x-android).
The table below provides a comparison of the two packages:
| | Full Package | Embedded Package |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Supports use as standalone** | ✅ | ❌ |
| **Supports use as widget** | ✅ | ✅ |
| **Deployment mode** | Hosted as a static web page and accessed via a URL when used as a widget | Bundled within a messenger app for seamless integration |
| **Release artifacts** | Docker Image, Tarball | Tarball, NPM for Web, Android AAR, SwiftPM for iOS |
| **Recommended for** | Standalone/guest access usage | Embedding within messenger apps |
| **Responsibility for regulatory compliance** | The administrator that is deploying the app is responsible for compliance with any applicable regulations (e.g. privacy) | The developer of the messenger app is responsible for compliance |
| **Analytics consent** | Element Call will show a consent UI. | Element Call will not show a consent UI. The messenger app should only provide the embedded Element Call with the [analytics URL parameters](./url-params.md#embedded-only-parameters) if consent has been granted. |
| **Analytics data** | Element Call will send data to the Posthog, Sentry and Open Telemetry targets specified by the administrator in the `config.json` | Element Call will send data to the Posthog and Sentry targets specified in the URL parameters by the messenger app |
### Using the embedded package within a messenger app
Currently the best way to understand the necessary steps is to look at the implementations in the Element Messenger apps: [Web](https://github.com/element-hq/element-web/pull/29309), [iOS](https://github.com/element-hq/element-x-ios/pull/3939) and [Android](https://github.com/element-hq/element-x-android/pull/4470).
The basics are:
1. Add the appropriate platform dependency as given for a [release](https://github.com/element-hq/element-call/releases), or use the embedded tarball. e.g. `npm install @element-hq/element-call-embedded@0.9.0`
2. Include the assets from the platform dependency in the build process. e.g. copy the assets during a [Webpack](https://github.com/element-hq/element-web/blob/247cd8d56d832d006d7dfb919d1042529d712b59/webpack.config.js#L677-L682) build.
3. Use the `index.html` entrypointof the imported assets when you are constructing the WebView or iframe. e.g. using a [relative path in a webapp](https://github.com/element-hq/element-web/blob/247cd8d56d832d006d7dfb919d1042529d712b59/src/models/Call.ts#L680), or on the the Android [WebViewAssetLoader](https://github.com/element-hq/element-x-android/blob/fe5aab6588ecdcf9354a3bfbd9e97c1b31175a8f/features/call/impl/src/main/kotlin/io/element/android/features/call/impl/utils/DefaultCallWidgetProvider.kt#L20)
4. Set any of the [embedded-only URL parameters](./url-params.md#embedded-only-parameters) that you need.
## Widget vs standalone mode

Binary file not shown.

After

Width:  |  Height:  |  Size: 302 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@@ -1,5 +1,9 @@
# Self-Hosting Element Call
> [!NOTE]
> For In-App calling (Element X, Element Web, Element Desktop) use-case only
> section [Prerequisites](#Prerequisites) is required.
## Prerequisites
> [!IMPORTANT]
@@ -51,9 +55,10 @@ rc_message:
# Note key sharing events are bursty
per_second: 0.5
burst_count: 30
rc_delayed_event_mgmt:
# This needs to match at least the heart-beat frequency plus a bit of headroom
# Currently the heart-beat is every 5 seconds which translates into a rate of 0.2s
rc_delayed_event_mgmt:
per_second: 1
burst_count: 20
```
@@ -130,11 +135,11 @@ server {
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://matrix-rtc.example.com"
"livekit_service_url": "https://matrix-rtc.example.com/livekit/jwt"
},
{
"type": "livekit",
"livekit_service_url": "https://matrix-rtc-2.example.com"
"livekit_service_url": "https://matrix-rtc-2.example.com/livekit/jwt"
},
{
"type": "nextgen_new_foci_type",
@@ -143,6 +148,17 @@ server {
]
```
Make sure this file is served with the correct MIME type (`application/json`).
Additionally, ensure the appropriate CORS headers are set to allow web clients
to access it across origins. For more details, refer to the
[Matrix Client-Server API: 2. Web Browser Clients](https://spec.matrix.org/latest/client-server-api/#web-browser-clients).
```
Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization
```
> [!NOTE]
> Most `org.matrix.msc4143.rtc_foci` configurations will only have one entry in
> the array
@@ -219,3 +235,30 @@ federation, so as to prevent spam registrations (if you keep registrations open)
and to ensure Element Call continues to work in case any user decides to log in
to their Element Call account using the standard Element app and joins normal
rooms that Element Call cannot handle.
# 📚 Community Guides & How-Tos
Looking for real-world tips, tutorials, and experiences from the community?
Below is a collection of blog posts, walkthroughs, and how-tos created by other
self-hosters and developers working with Element Call.
> [!NOTE]
> These resources are community-created and may reflect different setups or
> versions. Use them alongside the official documentation for best results.
## 🌐 Blog Posts & Articles
- [How to resolve stuck MatrixRTC calls](https://sspaeth.de/2025/02/how-to-resolve-stuck-matrixrtc-calls/)
## 🛠️ How-Tos & Tutorials
- [MatrixRTC aka Element-call setup (Geek warning)](https://sspaeth.de/2024/11/sfu/)
- [MatrixRTC with Synology Container Manager (Docker)](https://ztfr.de/matrixrtc-with-synology-container-manager-docker/)
- [Encrypted & Scalable Video Calls: How to deploy an Element Call backend with Synapse Using Docker-Compose](https://willlewis.co.uk/blog/posts/deploy-element-call-backend-with-synapse-and-docker-compose/)
- [Element Call einrichten: Verschlüsselte Videoanrufe mit Element X und Matrix Synapse](https://www.cleveradmin.de/blog/2025/04/matrixrtc-element-call-backend-einrichten/)
## 🤝 Want to Contribute?
Have a guide or blog post you'd like to share? Open a
[PR](https://github.com/element-hq/element-call/pulls) to add it here, or drop a
link in the [#webrtc:matrix.org](https://matrix.to/#/#webrtc:matrix.org) room.

View File

@@ -0,0 +1,8 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
const val VERSION = "0.0.0"

View File

@@ -1,5 +1,14 @@
//
// Copyright 2025 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
// Please see LICENSE files in the repository root for full details.
//
import Foundation
public let appURL = Bundle.module.url(forResource: "index", withExtension: "html", subdirectory: "dist")
public let bundle = Bundle.module
public let version = "0.0.0"

View File

@@ -65,12 +65,14 @@
"debug_tile_layout_label": "Kachel-Layout debuggen",
"device_id": "Geräte-ID: {{id}}",
"duplicate_tiles_label": "Anzahl zusätzlicher Kachelkopien pro Teilnehmer",
"environment_variables": "Umgebungsvariablen",
"hostname": "Hostname: {{hostname}}",
"livekit_server_info": "LiveKit-Server Informationen",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix-ID: {{id}}",
"show_connection_stats": "Verbindungsstatistiken anzeigen",
"show_non_member_tiles": "Kacheln für Nicht-Mitgliedermedien anzeigen",
"url_params": "URL-Parameter",
"use_new_membership_manager": "Neuen MembershipManager verwenden"
},
"disconnected_banner": "Die Verbindung zum Server wurde getrennt.",
@@ -142,9 +144,9 @@
"rageshake_sending": "Senden …",
"rageshake_sending_logs": "Sende Debug-Protokolle …",
"rageshake_sent": "Danke!",
"recaptcha_caption": "Diese Seite wird durch reCAPTCHA geschützt und es gelten Googles <2>Datenschutzerklärung</2> und <6>Nutzungsbedingungen</6>. <9></9>Mit einem Klick auf „Registrieren“ akzeptierst du unseren <2>Endbenutzer-Lizenzvertrag (EULA)</2>",
"recaptcha_dismissed": "Recaptcha abgelehnt",
"recaptcha_not_loaded": "Recaptcha nicht geladen",
"recaptcha_ssla_caption": "Diese Website wird durch ReCAPTCHA geschützt, und es gelten die Google <2>Datenschutzbestimmungen</2> sowie die <6>Nutzungsbedingungen</6>.<9></9> Durch das Klicken auf \"Registrieren\" wird der <12>Software- und Dienstleistungslizenzvereinbarung (SSLA)</12> zugestimmt.",
"register": {
"passwords_must_match": "Passwörter müssen übereinstimmen",
"registering": "Registrierung …"
@@ -154,7 +156,7 @@
"register_heading": "Erstelle Dein Konto",
"return_home_button": "Zurück zur Startseite",
"room_auth_view_continue_button": "Weiter",
"room_auth_view_eula_caption": "Mit einem Klick auf „Weiter“ akzeptierst du unseren <2>Endbenutzer-Lizenzvertrag (EULA)</2>",
"room_auth_view_ssla_caption": "Durch das Klicken auf \"Anruf jetzt beitreten\" wird dem <2>Software and Services License Agreement (SSLA)</2> zugestimmt.",
"screenshare_button_label": "Bildschirm teilen",
"settings": {
"audio_tab": {
@@ -200,8 +202,8 @@
"submitting": "Sende …",
"switch_camera": "Kamera wechseln",
"unauthenticated_view_body": "Noch nicht registriert? <2>Konto erstellen</2>",
"unauthenticated_view_eula_caption": "Mit einem Klick auf „Los gehts“ akzeptierst du unseren <2>Endbenutzer-Lizenzvertrag (EULA)</2>",
"unauthenticated_view_login_button": "Melde dich mit deinem Konto an",
"unauthenticated_view_ssla_caption": "Durch das Klicken auf \"Weiter\" wird dem <2>Software and Services License Agreement (SSLA)</2> zugestimmt.",
"unmute_microphone_button_label": "Mikrofon einschalten",
"version": "{{productName}} Version: {{version}}",
"video_tile": {

View File

@@ -65,12 +65,14 @@
"debug_tile_layout_label": "Debug tile layout",
"device_id": "Device ID: {{id}}",
"duplicate_tiles_label": "Number of additional tile copies per participant",
"environment_variables": "Environment variables",
"hostname": "Hostname: {{hostname}}",
"livekit_server_info": "LiveKit Server Info",
"livekit_sfu": "LiveKit SFU: {{url}}",
"matrix_id": "Matrix ID: {{id}}",
"show_connection_stats": "Show connection statistics",
"show_non_member_tiles": "Show tiles for non-member media",
"url_params": "URL parameters",
"use_new_membership_manager": "Use the new implementation of the call MembershipManager"
},
"disconnected_banner": "Connectivity to the server has been lost.",
@@ -142,9 +144,9 @@
"rageshake_sending": "Sending…",
"rageshake_sending_logs": "Sending debug logs…",
"rageshake_sent": "Thanks!",
"recaptcha_caption": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>End User Licensing Agreement (EULA)</12>",
"recaptcha_dismissed": "Recaptcha dismissed",
"recaptcha_not_loaded": "Recaptcha not loaded",
"recaptcha_ssla_caption": "This site is protected by ReCAPTCHA and the Google <2>Privacy Policy</2> and <6>Terms of Service</6> apply.<9></9>By clicking \"Register\", you agree to our <12>Software and Services License Agreement (SSLA)</12>",
"register": {
"passwords_must_match": "Passwords must match",
"registering": "Registering…"
@@ -154,7 +156,7 @@
"register_heading": "Create your account",
"return_home_button": "Return to home screen",
"room_auth_view_continue_button": "Continue",
"room_auth_view_eula_caption": "By clicking \"Continue\", you agree to our <2>End User Licensing Agreement (EULA)</2>",
"room_auth_view_ssla_caption": "By clicking \"Join call now\", you agree to our <2>Software and Services License Agreement (SSLA)</2>",
"screenshare_button_label": "Share screen",
"settings": {
"audio_tab": {
@@ -200,8 +202,8 @@
"submitting": "Submitting…",
"switch_camera": "Switch camera",
"unauthenticated_view_body": "Not registered yet? <2>Create an account</2>",
"unauthenticated_view_eula_caption": "By clicking \"Go\", you agree to our <2>End User Licensing Agreement (EULA)</2>",
"unauthenticated_view_login_button": "Login to your account",
"unauthenticated_view_ssla_caption": "By clicking \"Go\", you agree to our <2>Software and Services License Agreement (SSLA)</2>",
"unmute_microphone_button_label": "Unmute microphone",
"version": "{{productName}} version: {{version}}",
"video_tile": {

View File

@@ -50,7 +50,6 @@
"rageshake_send_logs": "Enviar registros de depuración",
"rageshake_sending": "Enviando…",
"rageshake_sending_logs": "Enviando registros de depuración…",
"recaptcha_caption": "Este sitio está protegido por ReCAPTCHA y se aplican la <2>Política de Privacidad</2> y los <6>Términos de Servicio de Google.<9></9>Al hacer clic en \"Registrar\", aceptas nuestro <12>Contrato de Licencia de Usuario Final (CLUF)</12>",
"recaptcha_dismissed": "Recaptcha cancelado",
"recaptcha_not_loaded": "No se ha cargado el Recaptcha",
"register": {
@@ -60,7 +59,6 @@
"register_auth_links": "<0>¿Ya tienes una cuenta?</0><1><0>Iniciar sesión</0> o <2>Acceder como invitado</2></1>",
"register_confirm_password_label": "Confirmar contraseña",
"return_home_button": "Volver a la pantalla de inicio",
"room_auth_view_eula_caption": "Al hacer clic en \"Unirse a la llamada ahora\", aceptas nuestro <2>Contrato de Licencia de Usuario Final (CLUF)</2>",
"screenshare_button_label": "Compartir pantalla",
"settings": {
"developer_tab_title": "Desarrollador",
@@ -76,7 +74,6 @@
"star_rating_input_label_other": "{{count}} estrellas",
"submitting": "Enviando…",
"unauthenticated_view_body": "¿No estás registrado todavía? <2>Crear una cuenta</2>",
"unauthenticated_view_eula_caption": "Al hacer clic en \"Comenzar\", aceptas nuestro <2>Contrato de Licencia de Usuario Final (CLUF)</2>",
"unauthenticated_view_login_button": "Iniciar sesión en tu cuenta",
"version": "Versión: {{version}}"
}

View File

@@ -78,7 +78,6 @@
"rageshake_sending": "Saatmine…",
"rageshake_sending_logs": "Veaotsingulogide saatmine…",
"rageshake_sent": "Tänud!",
"recaptcha_caption": "Selles saidis on kasutusel ReCAPTCHA ja kehtivad Google'i <2>Privaatsuspoliitika</2> ning <6>Teenusetingimused</6>.<9></9>Klõpsides „Registreeru“, sa nõustud meie <12>Lõppkasutaja litsentsilepingu (EULA) tingimustega</12>",
"recaptcha_dismissed": "Robotilõks on vahele jäetud",
"recaptcha_not_loaded": "Robotilõks pole laetud",
"register": {
@@ -88,7 +87,6 @@
"register_auth_links": "<0>On sul juba konto?</0><1><0>Logi sisse</0> Või <2>Logi sisse külalisena</2></1>",
"register_confirm_password_label": "Kinnita salasõna",
"return_home_button": "Tagasi avalehele",
"room_auth_view_eula_caption": "Klõpsides „Liitu kõnega kohe“, nõustud sa meie <2>Lõppkasutaja litsentsilepinguga (EULA)</2>",
"screenshare_button_label": "Jaga ekraani",
"settings": {
"developer_tab_title": "Arendaja",
@@ -108,7 +106,6 @@
"stop_video_button_label": "Peata videovoog",
"submitting": "Saadan…",
"unauthenticated_view_body": "Sa pole veel registreerunud? <2>Loo kasutajakonto</2>",
"unauthenticated_view_eula_caption": "Klõpsides „Jätka“, nõustud sa meie <2>Lõppkasutaja litsentsilepinguga (EULA)</2>",
"unauthenticated_view_login_button": "Logi oma kontosse sisse",
"unmute_microphone_button_label": "Lülita mikrofon sisse",
"version": "Versioon: {{version}}"

View File

@@ -77,7 +77,6 @@
"rageshake_sending": "Envoi…",
"rageshake_sending_logs": "Envoi des journaux de débogage…",
"rageshake_sent": "Merci !",
"recaptcha_caption": "Ce site est protégé par ReCAPTCHA, la <2>politique de confidentialité</2> et les <6>conditions dutilisation</6> de Google sappliquent.<9></9>En cliquant sur « Senregistrer » vous acceptez également notre <12>Contrat de Licence Utilisateur Final (CLUF)</12>",
"recaptcha_dismissed": "Recaptcha refusé",
"recaptcha_not_loaded": "Recaptcha non chargé",
"register": {
@@ -87,7 +86,6 @@
"register_auth_links": "<0>Vous avez déjà un compte ?</0><1><0>Se connecter</0> Ou <2>Accès invité</2></1>",
"register_confirm_password_label": "Confirmer le mot de passe",
"return_home_button": "Retour à laccueil",
"room_auth_view_eula_caption": "En cliquant sur « Rejoindre lappel maintenant », vous acceptez notre <2>Contrat de Licence Utilisateur Final (CLUF)</2>",
"screenshare_button_label": "Partage décran",
"settings": {
"developer_tab_title": "Développeur",
@@ -107,7 +105,6 @@
"stop_video_button_label": "Arrêter la vidéo",
"submitting": "Envoi…",
"unauthenticated_view_body": "Pas encore de compte ? <2>En créer un</2>",
"unauthenticated_view_eula_caption": "En cliquant sur « Commencer », vous acceptez notre <2>Contrat de Licence Utilisateur Final (CLUF)</2>",
"unauthenticated_view_login_button": "Connectez vous à votre compte",
"unmute_microphone_button_label": "Allumer le microphone",
"version": "Version : {{version}}"

View File

@@ -77,7 +77,6 @@
"rageshake_sending": "Mengirimkan…",
"rageshake_sending_logs": "Mengirimkan catatan pengawakutuan…",
"rageshake_sent": "Terima kasih!",
"recaptcha_caption": "Situs ini dilindungi oleh reCAPTCHA dan <2>Kebijakan Privasi</2> dan <6>Ketentuan Layanan</6> Google berlaku.<9></9>Dengan mengeklik \"Daftar\", Anda menyetujui <12>Perjanjian Lisensi Pengguna Akhir (EULA)</12> kami",
"recaptcha_dismissed": "Recaptcha ditutup",
"recaptcha_not_loaded": "Recaptcha tidak dimuat",
"register": {
@@ -87,7 +86,6 @@
"register_auth_links": "<0>Sudah punya akun?</0><1><0>Masuk</0> Atau <2>Akses sebagai tamu</2></1>",
"register_confirm_password_label": "Konfirmasi kata sandi",
"return_home_button": "Kembali ke layar beranda",
"room_auth_view_eula_caption": "Dengan mengeklik \"Bergabung ke panggilan sekarang\", Anda menyetujui <2>Perjanjian Lisensi Pengguna Akhir (EULA)</2> kami",
"screenshare_button_label": "Bagikan layar",
"settings": {
"developer_tab_title": "Pengembang",
@@ -107,7 +105,6 @@
"stop_video_button_label": "Matikan video",
"submitting": "Mengirim…",
"unauthenticated_view_body": "Belum terdaftar? <2>Buat sebuah akun</2>",
"unauthenticated_view_eula_caption": "Dengan mengeklik \"Bergabung\", Anda menyetujui <2>Perjanjian Lisensi Pengguna Akhir (EULA)</2>",
"unauthenticated_view_login_button": "Masuk ke akun Anda",
"unmute_microphone_button_label": "Nyalakan mikrofon",
"version": "Versi: {{version}}"

View File

@@ -75,7 +75,6 @@
"rageshake_sending": "Invio…",
"rageshake_sending_logs": "Invio dei registri di debug…",
"rageshake_sent": "Grazie!",
"recaptcha_caption": "Questo sito è protetto da ReCAPTCHA e si applicano l'<2>informativa sulla privacy</2> e i <6>termini di servizio</6> di Google.<9></9>Cliccando \"Registra\", accetti il nostro <12>accordo di licenza con l'utente finale (EULA)</12>",
"recaptcha_dismissed": "Recaptcha annullato",
"recaptcha_not_loaded": "Recaptcha non caricato",
"register": {
@@ -85,7 +84,6 @@
"register_auth_links": "<0>Hai già un profilo?</0><1><0>Accedi</0> o <2>Accedi come ospite</2></1>",
"register_confirm_password_label": "Conferma password",
"return_home_button": "Torna alla schermata di iniziale",
"room_auth_view_eula_caption": "Cliccando \"Entra in chiamata ora\", accetti il nostro <2>accordo di licenza con l'utente finale (EULA)</2>",
"screenshare_button_label": "Condividi schermo",
"settings": {
"developer_tab_title": "Sviluppatore",
@@ -104,7 +102,6 @@
"stop_video_button_label": "Ferma video",
"submitting": "Invio…",
"unauthenticated_view_body": "Non hai ancora un profilo? <2>Creane uno</2>",
"unauthenticated_view_eula_caption": "Cliccando \"Vai\", accetti il nostro <2>accordo di licenza con l'utente finale (EULA)</2>",
"unauthenticated_view_login_button": "Accedi al tuo profilo",
"unmute_microphone_button_label": "Riaccendi il microfono",
"version": "Versione: {{version}}"

View File

@@ -57,7 +57,6 @@
"rageshake_sending": "Nosūta…",
"rageshake_sending_logs": "Nosūta atkļūdošanas žurnāla ierakstus…",
"rageshake_sent": "Paldies!",
"recaptcha_caption": "Šo vietni aizsargā ReCAPTCHA, un ir attiecināmi Google <2>privātuma nosacījumi</2> un <6>pakalpojuma noteikumi</6>.<9></9>Klikšķināšana uz \"Reģistrēties\" sniedz piekrišanu mūsu <12>galalietotāja licencēšanas nolīgumam (GLLN)</12>",
"recaptcha_dismissed": "ReCaptcha atmesta",
"recaptcha_not_loaded": "ReCaptcha nav ielādēta",
"register": {
@@ -67,7 +66,6 @@
"register_auth_links": "<0>Jau ir konts?</0><1><0>Pieteikties</0> vai <2>Piekļūt kā viesim</2></1>",
"register_confirm_password_label": "Apstiprināt paroli",
"return_home_button": "Atgriezties sākuma ekrānā",
"room_auth_view_eula_caption": "Klikšķināšana uz \"Pievienoties zvanam tagad\" apliecina piekrišanu mūsu <2>galalietotāja licencēšanas nolīgumam (GLLN)</2>",
"screenshare_button_label": "Kopīgot ekrānu",
"settings": {
"developer_tab_title": "Izstrādātājs",
@@ -83,7 +81,6 @@
"star_rating_input_label_other": "{{count}} zvaigznes",
"submitting": "Iesniedz…",
"unauthenticated_view_body": "Vēl neesi reģistrējies? <2>Izveidot kontu</2>",
"unauthenticated_view_eula_caption": "Klikšķināšana uz \"Aiziet\" apliecina piekrišanu mūsu <2>galalietotāja licencēšanas nolīgumam (GLLN)</2>",
"unauthenticated_view_login_button": "Pieteikties kontā",
"version": "Versija: {{version}}"
}

View File

@@ -80,7 +80,6 @@
"rageshake_sending": "Wysyłanie…",
"rageshake_sending_logs": "Wysyłanie dzienników debugowania…",
"rageshake_sent": "Dziękujemy!",
"recaptcha_caption": "Ta witryna jest chroniona przez ReCAPTCHA, więc obowiązują <2>Polityka prywatności</2> i <6>Warunki usług</6> Google. Klikając \"Zarejestruj\", zgadzasz się na naszą <12>Umowę licencyjną (EULA)</12>",
"recaptcha_dismissed": "Recaptcha odrzucona",
"recaptcha_not_loaded": "Recaptcha nie została załadowana",
"register": {
@@ -90,7 +89,6 @@
"register_auth_links": "<0>Masz już konto?</0><1><0>Zaloguj się</0> lub <2>Dołącz jako gość</2></1>",
"register_confirm_password_label": "Potwierdź hasło",
"return_home_button": "Powróć do strony głównej",
"room_auth_view_eula_caption": "Klikając \"Dołącz teraz do rozmowy\", zgadzasz się na naszą <2>Umowę licencyjną (EULA)</2>",
"screenshare_button_label": "Udostępnij ekran",
"settings": {
"developer_tab_title": "Programista",
@@ -110,7 +108,6 @@
"stop_video_button_label": "Zakończ wideo",
"submitting": "Wysyłanie…",
"unauthenticated_view_body": "Nie masz konta? <2>Utwórz je</2>",
"unauthenticated_view_eula_caption": "Klikając \"Przejdź\", zgadzasz się na naszą <2>Umowę licencyjną (EULA)</2>",
"unauthenticated_view_login_button": "Zaloguj się do swojego konta",
"unmute_microphone_button_label": "Odcisz mikrofon",
"version": "Wersja: {{version}}"

View File

@@ -117,7 +117,6 @@
"rageshake_sending": "Trimiterea...",
"rageshake_sending_logs": "Trimiterea jurnalelor de depanare...",
"rageshake_sent": "Multumesc!",
"recaptcha_caption": "Acest site este protejat de reCAPTCHA și se aplică Politica de <2> confidențialitate Google </2> și <6> Termenii și condițiile. </6> <9></9>Făcând clic pe „Înregistrare”, sunteți de acord cu Acordul nostru de licențiere pentru utilizatorul <12> final (EULA) </12>",
"recaptcha_dismissed": "Recaptcha a fost respins",
"recaptcha_not_loaded": "Recaptcha nu a fost încărcat",
"register": {
@@ -129,7 +128,6 @@
"register_heading": "Creează-ți contul",
"return_home_button": "Reveniți la ecranul de pornire",
"room_auth_view_continue_button": "Continuă",
"room_auth_view_eula_caption": "Făcând clic pe „Continuați”, sunteți de acord cu Acordul nostru de licențiere pentru utilizatorul <2> final (EULA) </2>",
"screenshare_button_label": "Partajare ecran",
"settings": {
"audio_tab": {
@@ -158,7 +156,6 @@
"submitting": "Trimiterea...",
"switch_camera": "Comutați camera",
"unauthenticated_view_body": "Nu sunteți încă înregistrat? <2>Creați un cont </2>",
"unauthenticated_view_eula_caption": "Făcând clic pe „Go”, sunteți de acord cu Acordul nostru de licențiere pentru utilizatorul <2> final (EULA) </2>",
"unauthenticated_view_login_button": "Conectați-vă la contul dvs.",
"unmute_microphone_button_label": "Anulează microfonul",
"version": "{{productName}}Versiune: {{version}}",

View File

@@ -78,7 +78,6 @@
"rageshake_sending": "Odosielanie…",
"rageshake_sending_logs": "Odosielanie záznamov o ladení…",
"rageshake_sent": "Ďakujeme!",
"recaptcha_caption": "Táto stránka je chránená systémom ReCAPTCHA a platia na ňu <2>Pravidlá ochrany osobných údajov spoločnosti Google</2> a <6>Podmienky poskytovania služieb</6>.<9></9>Kliknutím na tlačidlo \"Registrovať sa\" súhlasíte s našou <12>Licenčnou zmluvou s koncovým používateľom (EULA)</12>",
"recaptcha_dismissed": "Recaptcha zamietnutá",
"recaptcha_not_loaded": "Recaptcha sa nenačítala",
"register": {
@@ -88,7 +87,6 @@
"register_auth_links": "<0>Už máte konto?</0><1><0>Prihláste sa</0> Alebo <2>Prihlásiť sa ako hosť</2></1>",
"register_confirm_password_label": "Potvrdiť heslo",
"return_home_button": "Návrat na domovskú obrazovku",
"room_auth_view_eula_caption": "Kliknutím na \"Pripojiť sa k hovoru teraz\" súhlasíte s našou <2>Licenčnou zmluvou s koncovým používateľom (EULA)</2>",
"screenshare_button_label": "Zdieľať obrazovku",
"settings": {
"developer_tab_title": "Vývojár",
@@ -108,7 +106,6 @@
"stop_video_button_label": "Zastaviť video",
"submitting": "Odosielanie…",
"unauthenticated_view_body": "Ešte nie ste zaregistrovaný? <2>Vytvorte si účet</2>",
"unauthenticated_view_eula_caption": "Kliknutím na tlačidlo \"Prejsť\" vyjadrujete súhlas s našou <2>Licenčnou zmluvou s koncovým používateľom (EULA)</2>",
"unauthenticated_view_login_button": "Prihláste sa do svojho konta",
"unmute_microphone_button_label": "Zrušiť stlmenie mikrofónu",
"version": "Verzia: {{version}}"

View File

@@ -80,7 +80,6 @@
"rageshake_sending": "Надсилання…",
"rageshake_sending_logs": "Надсилання журналу налагодження…",
"rageshake_sent": "Дякуємо!",
"recaptcha_caption": "Цей сайт захищений ReCAPTCHA і до нього застосовується <2>Політика приватності</2> і <6>Умови надання послуг</6> Google.<9></9>Натискаючи \"Зареєструватися\", ви погоджуєтеся з нашою <12>Ліцензійною угодою з кінцевим користувачем (EULA)</12>",
"recaptcha_dismissed": "Recaptcha не пройдено",
"recaptcha_not_loaded": "Recaptcha не завантажено",
"register": {
@@ -90,7 +89,6 @@
"register_auth_links": "<0>Уже маєте обліковий запис?</0><1><0>Увійти</0> Or <2>Отримати доступ як гість</2></1>",
"register_confirm_password_label": "Підтвердити пароль",
"return_home_button": "Повернутися на екран домівки",
"room_auth_view_eula_caption": "Натискаючи \"Приєднатися до виклику зараз\", ви погоджуєтеся з нашою <2>Ліцензійною угодою з кінцевим користувачем (EULA)</2>",
"screenshare_button_label": "Поділитися екраном",
"settings": {
"developer_tab_title": "Розробнику",
@@ -110,7 +108,6 @@
"stop_video_button_label": "Зупинити відео",
"submitting": "Надсилання…",
"unauthenticated_view_body": "Ще не зареєстровані? <2>Створіть обліковий запис</2>",
"unauthenticated_view_eula_caption": "Натискаючи \"Далі\", ви погоджуєтеся з нашою <2>Ліцензійною угодою з кінцевим користувачем (EULA)</2>",
"unauthenticated_view_login_button": "Увійдіть до свого облікового запису",
"unmute_microphone_button_label": "Увімкнути мікрофон",
"version": "Версія: {{version}}"

View File

@@ -73,7 +73,6 @@
"rageshake_sending": "正在发送……",
"rageshake_sending_logs": "正在发送调试日志……",
"rageshake_sent": "谢谢!",
"recaptcha_caption": "该站点受 ReCAPTCHA 保护适用于Google的 <2>隐私政策</2>和 <6>服务条款</6>。 <9></9>点击 \"注册\",即表示您同意我们的 <12>最终用户许可协议 (EULA)</12>",
"recaptcha_dismissed": "人机验证失败",
"recaptcha_not_loaded": "recaptcha未加载",
"register": {
@@ -83,7 +82,6 @@
"register_auth_links": "<0>已有账户?</0><1><0>登录</0> Or <2>以访客身份继续</2></1>",
"register_confirm_password_label": "确认密码",
"return_home_button": "返回主页",
"room_auth_view_eula_caption": "点击 \"加入通话\",即表示您同意我们的<2>最终用户许可协议 (EULA)</2>",
"screenshare_button_label": "屏幕共享",
"settings": {
"developer_tab_title": "开发者",
@@ -103,7 +101,6 @@
"stop_video_button_label": "停止视频",
"submitting": "提交中…",
"unauthenticated_view_body": "还没有注册? <2>创建账户<2>",
"unauthenticated_view_eula_caption": "点击 \"开始\",即表示您同意我们的<2>最终用户许可协议 (EULA)</2>",
"unauthenticated_view_login_button": "登录你的账户",
"unmute_microphone_button_label": "取消麦克风静音",
"version": "版本:{{version}}"

View File

@@ -80,7 +80,6 @@
"rageshake_sending": "傳送中…",
"rageshake_sending_logs": "傳送除錯記錄檔中…",
"rageshake_sent": "感謝!",
"recaptcha_caption": "此網站被 ReCAPTCHA 保護,並適用 Google 的<2>隱私權政策</2>與<6>服務條款</6>。<9></9>點擊「註冊」即表示您同意我們的<12>終端使用者授權協議 (EULA)</12>",
"recaptcha_dismissed": "略過驗證碼",
"recaptcha_not_loaded": "驗證碼未載入",
"register": {
@@ -90,7 +89,6 @@
"register_auth_links": "<0>已經有帳號?</0><1><0>登入</0> 或<2>以訪客身份登入</2></1>",
"register_confirm_password_label": "確認密碼",
"return_home_button": "回到首頁",
"room_auth_view_eula_caption": "點擊「立刻加入通話」即表示您同意我們的<2>終端使用者授權協議 (EULA)</2>",
"screenshare_button_label": "分享畫面",
"settings": {
"developer_tab_title": "開發者",
@@ -110,7 +108,6 @@
"stop_video_button_label": "停止影片",
"submitting": "正在遞交……",
"unauthenticated_view_body": "還沒註冊嗎?<2>建立帳號</2>",
"unauthenticated_view_eula_caption": "點擊「前往」即表示您同意我們的<2>終端使用者授權協議 (EULA)</2>",
"unauthenticated_view_login_button": "登入您的帳號",
"unmute_microphone_button_label": "將麥克風取消靜音",
"version": "版本: {{version}}"

View File

@@ -23,7 +23,9 @@
"test:coverage": "vitest --coverage",
"backend": "docker-compose -f dev-backend-docker-compose.yml up",
"test:playwright": "playwright test",
"test:playwright:open": "yarn test:playwright --ui"
"test:playwright:open": "yarn test:playwright --ui",
"links:enable": "mv .links.disabled.yaml .links.yaml & touch .links.yaml",
"links:disable": "mv .links.yaml .links.disabled.yaml"
},
"devDependencies": {
"@babel/core": "^7.16.5",
@@ -95,7 +97,7 @@
"i18next-parser": "^9.1.0",
"jsdom": "^26.0.0",
"knip": "^5.27.2",
"livekit-client": "2.9.1",
"livekit-client": "2.10.0",
"lodash-es": "^4.17.21",
"loglevel": "^1.9.1",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#8395919f0fd1af7cab1e793d736f2cdf18ef7686",

View File

@@ -51,6 +51,17 @@ services:
networks:
- ecbackend
element-web:
image: ghcr.io/element-hq/element-web:develop
volumes:
- ./backend/ew.test.config.json:/app/config.json
environment:
ELEMENT_WEB_PORT: 81
ports:
- "8081:81"
networks:
- ecbackend
synapse:
hostname: homeserver
image: docker.io/matrixdotorg/synapse:latest

View File

@@ -0,0 +1,185 @@
/*
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.
*/
import { type Page, test, expect, type JSHandle } from "@playwright/test";
import type { MatrixClient } from "matrix-js-sdk";
export type UserBaseFixture = {
mxId: string;
page: Page;
clientHandle: JSHandle<MatrixClient>;
};
export type BaseWidgetSetup = {
brooks: UserBaseFixture;
whistler: UserBaseFixture;
};
export interface MyFixtures {
asWidget: BaseWidgetSetup;
}
const PASSWORD = "foobarbaz1!";
// Minimal config.json for the local element-web instance
const CONFIG_JSON = {
default_server_config: {
"m.homeserver": {
base_url: "http://synapse.localhost:8008",
server_name: "synapse.localhost",
},
},
element_call: {
participant_limit: 8,
brand: "Element Call",
},
// The default language is set here for test consistency
setting_defaults: {
language: "en-GB",
feature_group_calls: true,
},
// the location tests want a map style url.
map_style_url:
"https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx",
features: {
// We don't want to go through the feature announcement during the e2e test
feature_release_announcement: false,
feature_element_call_video_rooms: true,
feature_video_rooms: true,
feature_group_calls: true,
},
};
/**
* Set the Element Call URL in the dev tool settings using `window.mxSettingsStore` via `page.evaluate`.
* @param page
*/
async function setDevToolElementCallDevUrl(page: Page): Promise<void> {
await page.evaluate(() => {
window.mxSettingsStore.setValue(
"Developer.elementCallUrl",
null,
"device",
"https://localhost:3000/room",
);
});
}
export const widgetTest = test.extend<MyFixtures>({
asWidget: async ({ browser, context }, pUse) => {
await context.route(`http://localhost:8081/config.json*`, async (route) => {
await route.fulfill({ json: CONFIG_JSON });
});
const userA = `brooks_${Date.now()}`;
const userB = `whistler_${Date.now()}`;
const user1Context = await browser.newContext({
reducedMotion: "reduce",
});
const ewPage1 = await user1Context.newPage();
// Register the first user
await ewPage1.goto("http://localhost:8081/#/welcome");
await ewPage1.getByRole("link", { name: "Create Account" }).click();
await ewPage1.getByRole("textbox", { name: "Username" }).fill(userA);
await ewPage1
.getByRole("textbox", { name: "Password", exact: true })
.fill(PASSWORD);
await ewPage1.getByRole("textbox", { name: "Confirm password" }).click();
await ewPage1
.getByRole("textbox", { name: "Confirm password" })
.fill(PASSWORD);
await ewPage1.getByRole("button", { name: "Register" }).click();
await expect(
ewPage1.getByRole("heading", { name: `Welcome ${userA}` }),
).toBeVisible();
await setDevToolElementCallDevUrl(ewPage1);
const brooksClientHandle = await ewPage1.evaluateHandle(() =>
window.mxMatrixClientPeg.get(),
);
const brooksMxId = (await brooksClientHandle.evaluate((cli) => {
return cli.getUserId();
}, brooksClientHandle))!;
const user2Context = await browser.newContext({
reducedMotion: "reduce",
});
const ewPage2 = await user2Context.newPage();
// Register the second user
await ewPage2.goto("http://localhost:8081/#/welcome");
await ewPage2.getByRole("link", { name: "Create Account" }).click();
await ewPage2.getByRole("textbox", { name: "Username" }).fill(userB);
await ewPage2
.getByRole("textbox", { name: "Password", exact: true })
.fill(PASSWORD);
await ewPage2.getByRole("textbox", { name: "Confirm password" }).click();
await ewPage2
.getByRole("textbox", { name: "Confirm password" })
.fill(PASSWORD);
await ewPage2.getByRole("button", { name: "Register" }).click();
await expect(
ewPage2.getByRole("heading", { name: `Welcome ${userB}` }),
).toBeVisible();
await setDevToolElementCallDevUrl(ewPage2);
const whistlerClientHandle = await ewPage2.evaluateHandle(() =>
window.mxMatrixClientPeg.get(),
);
const whistlerMxId = (await whistlerClientHandle.evaluate((cli) => {
return cli.getUserId();
}, whistlerClientHandle))!;
// Invite the second user
await ewPage1.getByRole("button", { name: "Add room" }).click();
await ewPage1.getByText("New room").click();
await ewPage1.getByRole("textbox", { name: "Name" }).fill("Welcome Room");
await ewPage1.getByRole("button", { name: "Create room" }).click();
await expect(ewPage1.getByText("You created this room.")).toBeVisible();
await expect(ewPage1.getByText("Encryption enabled")).toBeVisible();
await ewPage1
.getByRole("button", { name: "Invite to this room", exact: true })
.click();
await expect(
ewPage1.getByRole("heading", { name: "Invite to Welcome Room" }),
).toBeVisible();
await ewPage1.getByRole("textbox").fill(whistlerMxId);
await ewPage1.getByRole("textbox").click();
await ewPage1.getByRole("button", { name: "Invite" }).click();
// Accept the invite
await expect(
ewPage2.getByRole("treeitem", { name: "Welcome Room" }),
).toBeVisible();
await ewPage2.getByRole("treeitem", { name: "Welcome Room" }).click();
await ewPage2.getByRole("button", { name: "Accept" }).click();
await expect(
ewPage2.getByRole("main").getByRole("heading", { name: "Welcome Room" }),
).toBeVisible();
// Renamed use to pUse, as a workaround for eslint error that was thinking this use was a react use.
await pUse({
brooks: {
mxId: brooksMxId,
page: ewPage1,
clientHandle: brooksClientHandle,
},
whistler: {
mxId: whistlerMxId,
page: ewPage2,
clientHandle: whistlerClientHandle,
},
});
},
});

24
playwright/global.d.ts vendored Normal file
View File

@@ -0,0 +1,24 @@
/*
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.
*/
import type * as Matrix from "matrix-js-sdk";
declare global {
interface Window {
mxMatrixClientPeg: {
get(): Matrix.MatrixClient;
};
mxSettingsStore: {
setValue: (
settingKey: string,
room: string | null,
level: string,
setting: string,
) => void;
};
}
}

View File

@@ -0,0 +1,97 @@
/*
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.
*/
import { expect, test } from "@playwright/test";
import { widgetTest } from "../fixtures/widget-user.ts";
widgetTest("Start a new call as widget", async ({ asWidget, browserName }) => {
test.skip(
browserName === "firefox",
"This test is not working on firefox, after hangup brooks is locked in a strange state with a blank widget",
);
const { brooks, whistler } = asWidget;
await expect(
brooks.page.getByRole("button", { name: "Video call" }),
).toBeVisible();
await brooks.page.getByRole("button", { name: "Video call" }).click();
await expect(
brooks.page.getByRole("menuitem", { name: "Legacy Call" }),
).toBeVisible();
await expect(
brooks.page.getByRole("menuitem", { name: "Element Call" }),
).toBeVisible();
await brooks.page.getByRole("menuitem", { name: "Element Call" }).click();
await expect(
brooks.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall"),
).toBeVisible();
await brooks.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall")
.click();
// Check the join indicator on the room list
await expect(
brooks.page.locator("div").filter({ hasText: /^Joined • 1$/ }),
).toBeVisible();
// Join from the other side
await expect(whistler.page.getByText("Video call started")).toBeVisible();
await expect(
whistler.page.getByRole("button", { name: "Join" }),
).toBeVisible();
await whistler.page.getByRole("button", { name: "Join" }).click();
await expect(
whistler.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall"),
).toBeVisible();
await whistler.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("lobby_joinCall")
.click();
await expect(
whistler.page.locator("div").filter({ hasText: /^Joined • 2$/ }),
).toBeVisible();
await expect(
brooks.page.locator("div").filter({ hasText: /^Joined • 2$/ }),
).toBeVisible();
// Whistler leaves
await whistler.page.waitForTimeout(1000);
await whistler.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("incall_leave")
.click();
// Brooks leaves
await brooks.page
.locator('iframe[title="Element Call"]')
.contentFrame()
.getByTestId("incall_leave")
.click();
await expect(whistler.page.locator(".mx_BasicMessageComposer")).toBeVisible();
await expect(brooks.page.locator(".mx_BasicMessageComposer")).toBeVisible();
});

View File

@@ -48,6 +48,20 @@
"groupName": "Vaul",
"matchDepNames": ["vaul"],
"prHeader": "Please review modals on mobile for visual regressions."
},
{
"groupName": "bundled element-call dependencies",
"matchPackageNames": [
"com.vanniktech.maven.publish",
"com.android.library",
"com.android.tools.build",
"gradle"
]
},
{
"groupName": "Yarn",
"matchPackageNames": ["yarn"],
"extends": ["schedule:weekly"]
}
],
"semanticCommits": "disabled",

View File

@@ -5,7 +5,6 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import "matrix-js-sdk/src/@types/global";
import { type setLogLevel as setLKLogLevel } from "livekit-client";
import type { DurationFormat as PolyfillDurationFormat } from "@formatjs/intl-durationformat";

View File

@@ -11,7 +11,7 @@ import {
} from "../reactions";
// Extend Matrix JS SDK types via Typescript declaration merging to support unspecced event fields and types
declare module "matrix-js-sdk/src/types" {
declare module "matrix-js-sdk/lib/types" {
export interface TimelineEvents {
[ElementCallReactionEventType]: ECallReactionEventContent;
}

View File

@@ -9,7 +9,7 @@ import { type FC, type JSX, Suspense, useEffect, useState } from "react";
import { BrowserRouter, Route, useLocation, Routes } from "react-router-dom";
import * as Sentry from "@sentry/react";
import { TooltipProvider } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { HomePage } from "./home/HomePage";
import { LoginPage } from "./auth/LoginPage";

View File

@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
import { afterEach, expect, test, vi } from "vitest";
import { render, screen } from "@testing-library/react";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import { type FC, type PropsWithChildren } from "react";
import { ClientContextProvider } from "./ClientContext";

View File

@@ -13,7 +13,7 @@ import {
useEffect,
} from "react";
import { Avatar as CompoundAvatar } from "@vector-im/compound-web";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import { useClientState } from "./ClientContext";

View File

@@ -17,9 +17,9 @@ import {
type JSX,
} from "react";
import { useNavigate } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { type ISyncStateData, type SyncState } from "matrix-js-sdk/src/sync";
import { ClientEvent, type MatrixClient } from "matrix-js-sdk/src/client";
import { logger } from "matrix-js-sdk/lib/logger";
import { type ISyncStateData, type SyncState } from "matrix-js-sdk/lib/sync";
import { ClientEvent, type MatrixClient } from "matrix-js-sdk";
import type { WidgetApi } from "matrix-widget-api";
import { ErrorPage } from "./FullScreenView";

View File

@@ -15,7 +15,7 @@ import {
type ReactElement,
} from "react";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { RageshakeButton } from "./settings/RageshakeButton";
import styles from "./ErrorView.module.css";

View File

@@ -9,7 +9,7 @@ import { type FC, type ReactElement, type ReactNode, useEffect } from "react";
import classNames from "classnames";
import { useTranslation } from "react-i18next";
import * as Sentry from "@sentry/react";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { ErrorIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { Header, HeaderLogo, LeftNav, RightNav } from "./Header";

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { IndexedDBStoreWorker } from "matrix-js-sdk/src/indexeddb-worker";
import { IndexedDBStoreWorker } from "matrix-js-sdk/lib/indexeddb-worker";
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const remoteWorker = new IndexedDBStoreWorker((self as any).postMessage);

View File

@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
import { useMemo } from "react";
import { useLocation } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { Config } from "./config/Config";
import { type EncryptionSystem } from "./e2ee/sharedKeyManagement";

View File

@@ -7,7 +7,7 @@ Please see LICENSE in the repository root for full details.
import { type FC, useCallback, useState } from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { useClientLegacy } from "./ClientContext";
import { useProfile } from "./profile/useProfile";

View File

@@ -10,8 +10,8 @@ import posthog, {
type PostHog,
type Properties,
} from "posthog-js";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixClient } from "matrix-js-sdk";
import { type Subscription } from "rxjs";
import { widget } from "../widget";

View File

@@ -6,8 +6,8 @@ Please see LICENSE in the repository root for full details.
*/
import { type DisconnectReason } from "livekit-client";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import {
type IPosthogEvent,

View File

@@ -11,7 +11,7 @@ import {
type Span,
} from "@opentelemetry/sdk-trace-base";
import { hrTimeToMilliseconds } from "@opentelemetry/core";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { PosthogAnalytics } from "./PosthogAnalytics";

View File

@@ -16,9 +16,9 @@ import {
} from "react";
import { useNavigate, useLocation } from "react-router-dom";
import { captureException } from "@sentry/react";
import { sleep } from "matrix-js-sdk/src/utils";
import { sleep } from "matrix-js-sdk/lib/utils";
import { Trans, useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { Button, Text } from "@vector-im/compound-web";
import { FieldRow, InputField, ErrorMessage } from "../input/Input";
@@ -204,7 +204,7 @@ export const RegisterPage: FC = () => {
/>
</FieldRow>
<Text size="sm">
<Trans i18nKey="recaptcha_caption">
<Trans i18nKey="recaptcha_ssla_caption">
This site is protected by ReCAPTCHA and the Google{" "}
<ExternalLink href="https://www.google.com/policies/privacy/">
Privacy Policy
@@ -216,8 +216,8 @@ export const RegisterPage: FC = () => {
apply.
<br />
By clicking "Register", you agree to our{" "}
<ExternalLink href={Config.get().eula}>
End User Licensing Agreement (EULA)
<ExternalLink href={Config.get().ssla}>
Software and Services License Agreement (SSLA)
</ExternalLink>
</Trans>
</Text>

View File

@@ -6,12 +6,12 @@ Please see LICENSE in the repository root for full details.
*/
import { useCallback } from "react";
import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
import { InteractiveAuth } from "matrix-js-sdk";
import {
createClient,
type LoginResponse,
type MatrixClient,
} from "matrix-js-sdk/src/matrix";
} from "matrix-js-sdk";
import { initClient } from "../utils/matrix";
import { type Session } from "../ClientContext";

View File

@@ -6,13 +6,13 @@ Please see LICENSE in the repository root for full details.
*/
import { useState, useEffect, useCallback, useRef } from "react";
import { InteractiveAuth } from "matrix-js-sdk/src/interactive-auth";
import { InteractiveAuth } from "matrix-js-sdk";
import {
createClient,
type MatrixClient,
type RegisterResponse,
} from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
} from "matrix-js-sdk";
import { logger } from "matrix-js-sdk/lib/logger";
import { initClient } from "../utils/matrix";
import { type Session } from "../ClientContext";

View File

@@ -6,9 +6,9 @@ Please see LICENSE in the repository root for full details.
*/
import { useEffect, useCallback, useRef, useState } from "react";
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
import { secureRandomString } from "matrix-js-sdk/lib/randomstring";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { translatedError } from "../TranslatedError";
declare global {

View File

@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { useCallback } from "react";
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
import { secureRandomString } from "matrix-js-sdk/lib/randomstring";
import { useClient } from "../ClientContext";
import { useInteractiveRegistration } from "../auth/useInteractiveRegistration";

View File

@@ -10,7 +10,7 @@ import { expect, test } from "vitest";
import { TooltipProvider } from "@vector-im/compound-web";
import { userEvent } from "@testing-library/user-event";
import { type ReactNode } from "react";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { ReactionToggleButton } from "./ReactionToggleButton";
import { ElementCallReactionEventType } from "../reactions";

View File

@@ -22,7 +22,7 @@ import {
useState,
} from "react";
import { useTranslation } from "react-i18next";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import classNames from "classnames";
import { useObservableState } from "observable-hooks";
import { map } from "rxjs";

View File

@@ -77,9 +77,9 @@ export interface ConfigOptions {
};
/**
* A link to the end-user license agreement (EULA)
* A link to the software and services license agreement (SSLA)
*/
eula?: string;
ssla?: string;
media_devices?: {
/**
@@ -134,7 +134,7 @@ export interface ResolvedConfigOptions extends ConfigOptions {
server_name: string;
};
};
eula: string;
ssla: string;
media_devices: {
enable_audio: boolean;
enable_video: boolean;
@@ -152,7 +152,7 @@ export const DEFAULT_CONFIG: ResolvedConfigOptions = {
features: {
feature_use_device_session_member_events: true,
},
eula: "https://static.element.io/legal/online-EULA.pdf",
ssla: "https://static.element.io/legal/element-software-and-services-license-agreement-uk-1.pdf",
media_devices: {
enable_audio: true,
enable_video: true,

View File

@@ -9,7 +9,7 @@ import { describe, expect, test, vi } from "vitest";
import {
type MatrixRTCSession,
MatrixRTCSessionEvent,
} from "matrix-js-sdk/src/matrixrtc";
} from "matrix-js-sdk/lib/matrixrtc";
import { KeyProviderEvent } from "livekit-client";
import { MatrixKeyProvider } from "./matrixKeyProvider";

View File

@@ -6,11 +6,11 @@ Please see LICENSE in the repository root for full details.
*/
import { BaseKeyProvider, createKeyMaterialFromBuffer } from "livekit-client";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import {
type MatrixRTCSession,
MatrixRTCSessionEvent,
} from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
} from "matrix-js-sdk/lib/matrixrtc";
export class MatrixKeyProvider extends BaseKeyProvider {
private rtcSession?: MatrixRTCSession;

View File

@@ -32,7 +32,7 @@ import {
} from "react";
import useMeasure from "react-use-measure";
import classNames from "classnames";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { useObservableEagerState } from "observable-hooks";
import { fromEvent, map, startWith } from "rxjs";

View File

@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { render, type RenderResult } from "@testing-library/react";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
import { type MatrixClient } from "matrix-js-sdk";
import { MemoryRouter } from "react-router-dom";
import { describe, expect, it } from "vitest";

View File

@@ -6,9 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import { Link } from "react-router-dom";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type RoomMember } from "matrix-js-sdk/src/models/room-member";
import { type Room } from "matrix-js-sdk/src/models/room";
import { type RoomMember, type Room, type MatrixClient } from "matrix-js-sdk";
import { type FC, useCallback, type MouseEvent, useState } from "react";
import { useTranslation } from "react-i18next";
import { IconButton, Text } from "@vector-im/compound-web";

View File

@@ -12,10 +12,10 @@ import {
type FormEventHandler,
type FC,
} from "react";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import { useTranslation } from "react-i18next";
import { Heading, Text } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { Button } from "@vector-im/compound-web";
import { useNavigate } from "react-router-dom";

View File

@@ -6,10 +6,10 @@ Please see LICENSE in the repository root for full details.
*/
import { type FC, useCallback, useState, type FormEventHandler } from "react";
import { secureRandomString } from "matrix-js-sdk/src/randomstring";
import { secureRandomString } from "matrix-js-sdk/lib/randomstring";
import { Trans, useTranslation } from "react-i18next";
import { Button, Heading, Text } from "@vector-im/compound-web";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { useNavigate } from "react-router-dom";
import { useClient } from "../ClientContext";
@@ -185,10 +185,10 @@ export const UnauthenticatedView: FC = () => {
</Text>
)}
<Text size="sm" className={styles.notice}>
<Trans i18nKey="unauthenticated_view_eula_caption">
<Trans i18nKey="unauthenticated_view_ssla_caption">
By clicking "Go", you agree to our{" "}
<ExternalLink href={Config.get().eula}>
End User Licensing Agreement (EULA)
<ExternalLink href={Config.get().ssla}>
Software and Services License Agreement (SSLA)
</ExternalLink>
</Trans>
</Text>

View File

@@ -5,14 +5,21 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type Room, RoomEvent } from "matrix-js-sdk/src/models/room";
import { type RoomMember } from "matrix-js-sdk/src/models/room-member";
import {
type MatrixClient,
type RoomMember,
type Room,
RoomEvent,
EventTimeline,
EventType,
JoinRule,
KnownMembership,
} from "matrix-js-sdk";
import { useState, useEffect } from "react";
import { EventTimeline, EventType, JoinRule } from "matrix-js-sdk/src/matrix";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { MatrixRTCSessionManagerEvents } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSessionManager";
import { KnownMembership } from "matrix-js-sdk/src/types";
import {
MatrixRTCSessionManagerEvents,
type MatrixRTCSession,
} from "matrix-js-sdk/lib/matrixrtc";
import { getKeyForRoom } from "../e2ee/sharedKeyManagement";

View File

@@ -14,7 +14,7 @@ import i18n, {
import { initReactI18next } from "react-i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import * as Sentry from "@sentry/react";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { shouldPolyfill as shouldPolyfillSegmenter } from "@formatjs/intl-segmenter/should-polyfill";
import { shouldPolyfill as shouldPolyfillDurationFormat } from "@formatjs/intl-durationformat/should-polyfill";
import {

View File

@@ -19,7 +19,7 @@ import {
import { createMediaDeviceObserver } from "@livekit/components-core";
import { map, startWith } from "rxjs";
import { useObservableEagerState } from "observable-hooks";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import {
useSetting,

View File

@@ -5,11 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { type IOpenIDToken, type MatrixClient } from "matrix-js-sdk";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { useEffect, useState } from "react";
import { type LivekitFocus } from "matrix-js-sdk/src/matrixrtc/LivekitFocus";
import { type LivekitFocus } from "matrix-js-sdk/lib/matrixrtc";
import { useActiveLivekitFocus } from "../room/useActiveFocus";
import { useErrorBoundary } from "../useErrorBoundary";

View File

@@ -15,7 +15,7 @@ import {
Track,
} from "livekit-client";
import { useCallback, useEffect, useRef, useState } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import * as Sentry from "@sentry/react";
import { type SFUConfig, sfuConfigEquals } from "./openIDSFU";

View File

@@ -15,8 +15,8 @@ import {
} from "livekit-client";
import { useEffect, useMemo, useRef } from "react";
import E2EEWorker from "livekit-client/e2ee-worker?worker";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { defaultLiveKitOptions } from "./options";
import { type SFUConfig } from "./openIDSFU";

View File

@@ -9,12 +9,12 @@ Please see LICENSE in the repository root for full details.
// function gets set. It needs to be not in the same file as we use
// createClient, or the typescript transpiler gets confused about
// dependency references.
import "matrix-js-sdk/src/browser-index";
import "matrix-js-sdk/lib/browser-index";
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import {
setLogExtension as setLKLogExtension,
setLogLevel as setLKLogLevel,

View File

@@ -6,12 +6,12 @@ Please see LICENSE in the repository root for full details.
*/
import { type Span } from "@opentelemetry/api";
import { type MatrixCall } from "matrix-js-sdk/src/matrix";
import { CallEvent } from "matrix-js-sdk/src/webrtc/call";
import { type MatrixCall } from "matrix-js-sdk";
import { CallEvent } from "matrix-js-sdk/lib/webrtc/call";
import {
type TransceiverStats,
type CallFeedStats,
} from "matrix-js-sdk/src/webrtc/stats/statsReport";
} from "matrix-js-sdk/lib/webrtc/stats/statsReport";
import { ObjectFlattener } from "./ObjectFlattener";
import { ElementCallOpenTelemetry } from "./otel";

View File

@@ -6,7 +6,7 @@ Please see LICENSE in the repository root for full details.
*/
import opentelemetry, { type Span } from "@opentelemetry/api";
import { type TrackStats } from "matrix-js-sdk/src/webrtc/stats/statsReport";
import { type TrackStats } from "matrix-js-sdk/lib/webrtc/stats/statsReport";
import { type ElementCallOpenTelemetry } from "./otel";
import { OTelCallMediaStreamTrackSpan } from "./OTelCallMediaStreamTrackSpan";

View File

@@ -9,7 +9,7 @@ import { type Span } from "@opentelemetry/api";
import {
type CallFeedStats,
type TrackStats,
} from "matrix-js-sdk/src/webrtc/stats/statsReport";
} from "matrix-js-sdk/lib/webrtc/stats/statsReport";
import { type ElementCallOpenTelemetry } from "./otel";
import { OTelCallAbstractMediaStreamSpan } from "./OTelCallAbstractMediaStreamSpan";

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type TrackStats } from "matrix-js-sdk/src/webrtc/stats/statsReport";
import { type TrackStats } from "matrix-js-sdk/lib/webrtc/stats/statsReport";
import opentelemetry, { type Span } from "@opentelemetry/api";
import { type ElementCallOpenTelemetry } from "./otel";

View File

@@ -9,7 +9,7 @@ import { type Span } from "@opentelemetry/api";
import {
type TrackStats,
type TransceiverStats,
} from "matrix-js-sdk/src/webrtc/stats/statsReport";
} from "matrix-js-sdk/lib/webrtc/stats/statsReport";
import { type ElementCallOpenTelemetry } from "./otel";
import { OTelCallAbstractMediaStreamSpan } from "./OTelCallAbstractMediaStreamSpan";

View File

@@ -15,26 +15,26 @@ import {
type MatrixClient,
type MatrixEvent,
type RoomMember,
} from "matrix-js-sdk/src/matrix";
import { logger } from "matrix-js-sdk/src/logger";
} from "matrix-js-sdk";
import { logger } from "matrix-js-sdk/lib/logger";
import {
type CallError,
type CallState,
type MatrixCall,
type VoipEvent,
} from "matrix-js-sdk/src/webrtc/call";
} from "matrix-js-sdk/lib/webrtc/call";
import {
type CallsByUserAndDevice,
type GroupCallError,
GroupCallEvent,
type GroupCallStatsReport,
} from "matrix-js-sdk/src/webrtc/groupCall";
} from "matrix-js-sdk/lib/webrtc/groupCall";
import {
type ConnectionStatsReport,
type ByteSentStatsReport,
type SummaryStatsReport,
type CallFeedReport,
} from "matrix-js-sdk/src/webrtc/stats/statsReport";
} from "matrix-js-sdk/lib/webrtc/stats/statsReport";
import { ElementCallOpenTelemetry } from "./otel";
import { ObjectFlattener } from "./ObjectFlattener";

View File

@@ -5,12 +5,12 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type GroupCallStatsReport } from "matrix-js-sdk/src/webrtc/groupCall";
import { type GroupCallStatsReport } from "matrix-js-sdk/lib/webrtc/groupCall";
import {
type AudioConcealment,
type ByteSentStatsReport,
type ConnectionStatsReport,
} from "matrix-js-sdk/src/webrtc/stats/statsReport";
} from "matrix-js-sdk/lib/webrtc/stats/statsReport";
import { describe, expect, it } from "vitest";
import { ObjectFlattener } from "../../src/otel/ObjectFlattener";

View File

@@ -5,13 +5,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type Attributes } from "@opentelemetry/api";
import { type VoipEvent } from "matrix-js-sdk/src/webrtc/call";
import { type GroupCallStatsReport } from "matrix-js-sdk/src/webrtc/groupCall";
import { type VoipEvent } from "matrix-js-sdk/lib/webrtc/call";
import { type GroupCallStatsReport } from "matrix-js-sdk/lib/webrtc/groupCall";
import {
type ByteSentStatsReport,
type ConnectionStatsReport,
type SummaryStatsReport,
} from "matrix-js-sdk/src/webrtc/stats/statsReport";
} from "matrix-js-sdk/lib/webrtc/stats/statsReport";
export class ObjectFlattener {
public static flattenReportObject(

View File

@@ -11,7 +11,7 @@ import { WebTracerProvider } from "@opentelemetry/sdk-trace-web";
import opentelemetry, { type Tracer } from "@opentelemetry/api";
import { Resource } from "@opentelemetry/resources";
import { SemanticResourceAttributes } from "@opentelemetry/semantic-conventions";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { PosthogSpanProcessor } from "../analytics/PosthogSpanProcessor";
import { Config } from "../config/Config";

View File

@@ -5,12 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixEvent } from "matrix-js-sdk/src/models/event";
import { type User, UserEvent } from "matrix-js-sdk/src/models/user";
import { type FileType } from "matrix-js-sdk/src/http-api";
import {
type MatrixEvent,
type User,
type MatrixClient,
UserEvent,
type FileType,
} from "matrix-js-sdk";
import { useState, useCallback, useEffect } from "react";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
interface ProfileLoadState {
success: boolean;

View File

@@ -7,14 +7,14 @@ Please see LICENSE in the repository root for full details.
import { renderHook } from "@testing-library/react";
import { afterEach, test, vitest } from "vitest";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import {
RoomEvent as MatrixRoomEvent,
MatrixEvent,
type IRoomTimelineData,
EventType,
MatrixEventEvent,
} from "matrix-js-sdk/src/matrix";
} from "matrix-js-sdk";
import { ReactionsReader, REACTION_ACTIVE_TIME_MS } from "./ReactionsReader";
import {

View File

@@ -9,15 +9,15 @@ import {
type CallMembership,
MatrixRTCSessionEvent,
type MatrixRTCSession,
} from "matrix-js-sdk/src/matrixrtc";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixEvent, MatrixEventEvent } from "matrix-js-sdk/src/matrix";
import { type ReactionEventContent } from "matrix-js-sdk/src/types";
} from "matrix-js-sdk/lib/matrixrtc";
import { logger } from "matrix-js-sdk/lib/logger";
import { type MatrixEvent, MatrixEventEvent } from "matrix-js-sdk";
import { type ReactionEventContent } from "matrix-js-sdk/lib/types";
import {
RelationType,
EventType,
RoomEvent as MatrixRoomEvent,
} from "matrix-js-sdk/src/matrix";
} from "matrix-js-sdk";
import { BehaviorSubject, delay, type Subscription } from "rxjs";
import {

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { type RelationType } from "matrix-js-sdk/src/types";
import { type RelationType } from "matrix-js-sdk";
import catSoundOgg from "../sound/reactions/cat.ogg?url";
import catSoundMp3 from "../sound/reactions/cat.mp3?url";

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import { EventType, RelationType } from "matrix-js-sdk/src/matrix";
import { EventType, RelationType } from "matrix-js-sdk";
import {
createContext,
useContext,
@@ -14,8 +14,8 @@ import {
useMemo,
type JSX,
} from "react";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { logger } from "matrix-js-sdk/src/logger";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { logger } from "matrix-js-sdk/lib/logger";
import { useObservableEagerState } from "observable-hooks";
import { useMatrixRTCSessionMemberships } from "../useMatrixRTCSessionMemberships";

View File

@@ -15,7 +15,7 @@ import {
import { useTranslation } from "react-i18next";
import { Button, Text } from "@vector-im/compound-web";
import { PopOutIcon } from "@vector-im/compound-design-tokens/assets/web/icons";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import { Modal } from "../Modal";
import { useRoomEncryptionSystem } from "../e2ee/sharedKeyManagement";

View File

@@ -6,11 +6,11 @@ Please see LICENSE in the repository root for full details.
*/
import { type FC, type FormEventHandler, useCallback, useState } from "react";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import { Trans, useTranslation } from "react-i18next";
import { Button, Heading, Text } from "@vector-im/compound-web";
import { useNavigate } from "react-router-dom";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import styles from "./CallEndedView.module.css";
import feedbackStyle from "../input/FeedbackInput.module.css";

View File

@@ -16,7 +16,7 @@ import {
afterEach,
} from "vitest";
import { act } from "react";
import { type CallMembership } from "matrix-js-sdk/src/matrixrtc";
import { type CallMembership } from "matrix-js-sdk/lib/matrixrtc";
import { mockRtcMembership } from "../utils/test";
import {

View File

@@ -14,13 +14,12 @@ import {
vi,
} from "vitest";
import { render, waitFor, screen } from "@testing-library/react";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc";
import { type MatrixClient, JoinRule, type RoomState } from "matrix-js-sdk";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import { of } from "rxjs";
import { JoinRule, type RoomState } from "matrix-js-sdk/src/matrix";
import { BrowserRouter } from "react-router-dom";
import userEvent from "@testing-library/user-event";
import { type RelationsContainer } from "matrix-js-sdk/src/models/relations-container";
import { type RelationsContainer } from "matrix-js-sdk/lib/models/relations-container";
import { useState } from "react";
import { TooltipProvider } from "@vector-im/compound-web";

View File

@@ -13,17 +13,16 @@ import {
useMemo,
useState,
} from "react";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient, JoinRule, type Room } from "matrix-js-sdk";
import {
Room as LivekitRoom,
isE2EESupported as isE2EESupportedBrowser,
} from "livekit-client";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import {
MatrixRTCSessionEvent,
type MatrixRTCSession,
} from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { JoinRule, type Room } from "matrix-js-sdk/src/matrix";
} from "matrix-js-sdk/lib/matrixrtc";
import { useNavigate } from "react-router-dom";
import type { IWidgetApiRequest } from "matrix-widget-api";

View File

@@ -11,7 +11,7 @@ import {
useLocalParticipant,
} from "@livekit/components-react";
import { ConnectionState, type Room } from "livekit-client";
import { type MatrixClient } from "matrix-js-sdk/src/client";
import { type MatrixClient } from "matrix-js-sdk";
import {
type FC,
type PointerEvent,
@@ -26,11 +26,11 @@ import {
type JSX,
} from "react";
import useMeasure from "react-use-measure";
import { type MatrixRTCSession } from "matrix-js-sdk/src/matrixrtc/MatrixRTCSession";
import { type MatrixRTCSession } from "matrix-js-sdk/lib/matrixrtc";
import classNames from "classnames";
import { BehaviorSubject, map } from "rxjs";
import { useObservable, useObservableEagerState } from "observable-hooks";
import { logger } from "matrix-js-sdk/src/logger";
import { logger } from "matrix-js-sdk/lib/logger";
import LogoMark from "../icons/LogoMark.svg?react";
import LogoType from "../icons/LogoType.svg?react";

Some files were not shown because too many files have changed in this diff Show More