Compare commits

...

449 Commits

Author SHA1 Message Date
fkwp
3d52f1695d test livekit-client 2.9.1 2025-03-18 16:11:32 +01:00
fkwp
fd72fc0ccc test livekit-client 2.8.1 2025-03-18 10:06:42 +01:00
fkwp
5c563058a9 test livekit-client 2.9.8 2025-03-18 10:03:15 +01:00
fkwp
5cb1970c41 wip 2025-03-18 09:55:09 +01:00
fkwp
ef2fee708e Merge pull request #3099 from element-hq/fkwp/update_readme
Update readme with new Element Call screenshot
2025-03-17 10:33:23 +01:00
fkwp
ef8e894c0b update Element Call screenshot 2025-03-17 09:55:04 +01:00
fkwp
d01a0de568 fix JSON blob 2025-03-17 09:54:37 +01:00
Valere Fedronic
a204dbe1d4 Merge pull request #3098 from element-hq/valere/playwright_dev_backend_no_ratelimit
Keep rate limits for dev backend, disable only for playwright tests
2025-03-17 09:51:30 +01:00
Valere
bd38a56ccc Keep rate limits for dev backend, disable only for playwright tests 2025-03-17 09:45:43 +01:00
Valere Fedronic
af58161f21 Merge pull request #3097 from element-hq/valere/playwright_initial_setup
Integration Test: Add test for register, login, logout and guest create and join call
2025-03-17 09:43:21 +01:00
Valere Fedronic
ad8ad218f1 Merge pull request #3096 from element-hq/valere/playwright_access_tests
Integration Test: Add test for register, login, logout and guest create and join call
2025-03-17 09:31:44 +01:00
fkwp
c4747dd177 Merge pull request #3026 from element-hq/fkwp/add_rc_delayed_event_mgmt_to_readme
README.md add information about rc_delayed_event_mgmt
2025-03-14 16:18:55 +01:00
Valere Fedronic
39c64afb77 Merge pull request #3091 from element-hq/valere/playwright_initial_setup
First integration tests with playwright
2025-03-14 16:02:46 +01:00
Valere
b9700b9986 code review 2025-03-14 14:50:47 +01:00
Valere
83198c061a Disable rate limiting on dev homeserver to avoid flaky tests 2025-03-14 11:01:25 +01:00
Valere
b5fff42adc Test: Add more integrations test
Testing access, register, login, logout. Create and join as guest
2025-03-14 11:01:19 +01:00
Valere
9dc515f45d Fixup: bad copy in the text 2025-03-13 20:04:26 +01:00
Valere
4c477bc4b1 fix: github action, missing config file for dev env 2025-03-13 20:04:26 +01:00
Valere
45d3a5e332 playwright add ignoreHTTPSErrors option 2025-03-13 20:04:26 +01:00
Valere
4efc32f8e2 fix: local element-call not running 2025-03-13 20:04:26 +01:00
Valere
a7af470549 yml: try docker compose instead of dash compose 2025-03-13 20:04:26 +01:00
Valere
102aaa80e2 typo in playwright.yml timeout 2025-03-13 20:04:26 +01:00
Valere
6eb1a02937 fix: vitest --coverage was running playwright tests 2025-03-13 20:04:26 +01:00
Valere
687dafab3e First integration tests with playwright 2025-03-13 20:04:26 +01:00
Timo
46e7e8e9cd Fix: js-sdk version that uses expected value for isJoined (isJoined will now be false before we left as expected by EC) (#3092) 2025-03-13 19:09:18 +01:00
Hugh Nimmo-Smith
a924c7ffbb Separate widget-only URL parameters in the documentation (#3088) 2025-03-13 10:28:38 +00:00
Valere Fedronic
90a282b46c Merge pull request #3063 from element-hq/valere/fix_add_close_button_in_widget_mode
Error: use a close button instead of go to home when in widget mode
2025-03-13 10:16:26 +01:00
Valere Fedronic
79e294755c Merge pull request #3058 from element-hq/valere/refactor_error_handling
refactor: Centralize group call errors in custom GroupCallErrorBoundary
2025-03-13 10:12:11 +01:00
Hugh Nimmo-Smith
7aac56aac0 Vite embedded build of Element Call (#3077)
* Embedded package build of Element Call

Part of https://github.com/element-hq/element-call/issues/2994

This creates a new "embedded" build (vs "full" build) at the vite level. It will be used by a later PR that actually provides platform specific packages.

Embedded build:

- Uses relative URLs
- Uses relative config.json path and other resource loading
- Has a config.json built in
- Doesn't include the public folder (e.g. favicon)

Out of scope:

- this doesn't attempt to exclude SPA functionality, so technically the build could be used in SPA
- the above means that the crypto-wasm binary is included in the build

* CI artifact name based on type of build

* Update src/config/Config.ts
2025-03-12 17:00:44 +00:00
Hugh Nimmo-Smith
520c0f4925 Fix typing on config: EULA is optional as it has a default (#3074) 2025-03-12 13:52:13 +01:00
Valere
b02ad8871e review: Make widget prop mandatory 2025-03-12 10:27:45 +01:00
Valere
b0a4a954f8 Error: use a close button instead of go to home when in widget mode 2025-03-12 10:12:34 +01:00
Robin
5547e838d3 Merge pull request #3080 from element-hq/robin/pin-matrix-js-sdk
Pin matrix-js-sdk to a specific commit
2025-03-12 05:06:10 -04:00
Valere
612ace137a code review: recoveryActionHandler should not be optional 2025-03-12 09:44:41 +01:00
Robin
3cf0ce3dcb Pin matrix-js-sdk to a specific commit
Whenever we use a Git dependency, we should reference a specific tag or commit rather than a branch name, because Yarn Classic is bad at recognizing when a Git dependency needs to be re-installed due to it resolving to a new version. (It seems to simply use the version from package.json as a cache key.)

This is relevant only for developers who run 'yarn install' on top of a previously up-to-date working copy, not for CI which re-installs the project on every run.
2025-03-11 16:25:03 -04:00
Valere
8584521ade fixup: post rebase fix 2025-03-11 20:19:14 +01:00
Timo
93ae2aed98 New Membership Manager js-sdk develop (#3067)
* fix experimentalDecorators like we do in the js-sdk

* bump-js-sdk

* update to develop branch of js-sdk (new membership manager)
2025-03-11 19:48:02 +01:00
Valere
c0ef6e5e4d fix: Error recover/retry buttons should reset error state 2025-03-11 16:54:19 +01:00
Valere
4c27551014 refactor: Centralize group call errors in custom GroupCallErrorBoundary 2025-03-11 16:54:19 +01:00
ElementRobot
a97c36a335 Merge pull request #3078 from element-hq/actions/localazy-download
Localazy Download
2025-03-11 15:40:53 +00:00
fkwp
1db3e3cbc4 Translations updates 2025-03-11 15:39:33 +00:00
Hugh Nimmo-Smith
1a692b983a Use fetch() in a way that works for file URLs (#3071)
fetch returns a response code of 0 when it successfully loads a `file://` resource.

This means we can't just rely on `response.ok`.

Required for https://github.com/element-hq/element-call/issues/2994
2025-03-11 10:39:51 +01:00
fkwp
f9ced9f10d typo 2025-03-10 20:58:12 +01:00
fkwp
e39fe3bc7f add information about rc_delayed_event_mgmt 2025-03-10 20:55:59 +01:00
fkwp
2885e7e42e Merge pull request #3059 from element-hq/fkwp/doc_update
Refactor README.md
2025-03-10 20:31:09 +01:00
Hugh Nimmo-Smith
88b862b5fd Update README.md 2025-03-10 18:10:25 +00:00
Hugh Nimmo-Smith
30b5bcdfb6 Cache calls to removeHiddenChars() to fix performance bottleneck in Safari (#3066)
* Cache calls to removeHiddenChars() as very slow on Safari

Fixes #3065

* Test

* Split testing for removeHiddenChars
2025-03-10 13:55:03 +00:00
Timo
b635b00b0c Expose setLKLogLevel to window for debugging. (#3064)
* Expose setLKLogLevel to window for debugging.

* fix es lint
2025-03-10 08:59:27 +00:00
Timo
750db09156 Use the New MatrixRTCSession MembershipManager (#3015)
* provide option to use the New MembershipManager

* fix cryptoApi import change

* add error screen

* bump js-sdk

* rename to `setUnrecoverableError` and remove onLeave call because that will be handled by an effect.

* this was doing nothing (it is a fragment back when there was no deprecated `rtcSession.room`)

* rename to error

* Update src/utils/errors.ts

Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>

* Update src/utils/errors.ts

Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>

* review

* bump js-sdk

* expose lk log level changing in `window`

* bump js-sdk
 - always log "Missing own membership: force re-join"
 - also check insertions queue

* change lk log level to warn

* Bump js-sdk

* Bump js-sdk

* .

* Bump js-sdk

* show user count based on meberships not users.

Signed-off-by: Timo K <toger5@hotmail.de>

* bump js-sdk

* rename setting name

* remove unused import

* js sdk bump

* remove `window.setLKLogLevel`

* bump js sdk with reverted incompatible change

* bump js-sdk with one less merge

---------

Signed-off-by: Timo K <toger5@hotmail.de>
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-03-07 16:27:04 +00:00
Timo
c9f2a1c943 Reduce redundant calculations of display name map (#3062)
* Use share() on fromEvent() so that we multiplex subscribers onto the event emitter

* .

* .

* Comment

* Comment

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-03-07 10:18:28 +00:00
fkwp
1958b658c3 make colours dark theme compatible 2025-03-05 21:53:41 +01:00
fkwp
542d36f893 prettier 2025-03-05 21:43:09 +01:00
fkwp
ad10b6c2fa add self-hosting section 2025-03-05 21:20:08 +01:00
fkwp
c29eeff450 indentation 2025-03-05 21:19:56 +01:00
fkwp
af57834c87 format Copyright & License 2025-03-05 21:19:12 +01:00
fkwp
e87e1a8f25 Update documentation 2025-03-05 21:18:17 +01:00
fkwp
5583f621ba Update Development Section 2025-03-05 21:17:54 +01:00
fkwp
1df5872215 update Translation section 2025-03-05 21:16:49 +01:00
fkwp
32a3c9ea5d Add section about MatrixRTC Backend Discovery and Selection 2025-03-05 21:15:57 +01:00
fkwp
93fb299770 add self-hosting section 2025-03-05 21:13:55 +01:00
fkwp
f79d7cfaea Add deployment options section 2025-03-05 21:12:23 +01:00
fkwp
1c233b88f0 add feature section 2025-03-05 21:10:45 +01:00
fkwp
52b40d3116 add Overview section 2025-03-05 19:35:02 +01:00
fkwp
f7379b5683 Add short description of Element Call 2025-03-05 19:34:39 +01:00
fkwp
2c21423f1a add License shield 2025-03-05 19:33:39 +01:00
Robin
b5f5ab329a Merge pull request #3051 from element-hq/robin/return-to-lobby
Respect the returnToLobby flag
2025-03-05 12:17:53 -05:00
Robin
308d42980f Merge pull request #3054 from element-hq/robin/og-brand
Use the configured brand name in OpenGraph tags
2025-03-05 12:09:25 -05:00
Robin
0ca2627bd4 Merge pull request #3055 from element-hq/robin/join-action
Send a 'join' action when entering the call
2025-03-05 12:09:16 -05:00
Robin
359812d8b1 Explain why returnToLobby is false in SPA 2025-03-05 10:40:37 -05:00
Robin
5b1ea4501d Send a 'join' action when entering the call
Following a75952cf77, this is one more upgrade to the widget communication that I'd like to make within this release cycle.

The motivating issue is https://github.com/element-hq/element-web/issues/29429. Fundamentally, without a 'join' action, the only info Element Web can use to determine whether it's joined the call is whether a MatrixRTC membership exists. But membership state events can inaccurately represent the client's actual state (whether because delayed events aren't supported, or because the delayed event hasn't timed out yet), so I suggest we send a 'join' action here just as we do in the Element Web Jitsi wrapper (e9a3625bd6/src/vector/jitsi/index.ts (L503)) to let Element Web tap directly into the widget's local state. (This will need additional Element Web changes, but is certainly backwards compatible.)
2025-03-05 09:25:52 -05:00
Robin
ec73e7fa86 Use the configured brand name in OpenGraph tags
Overlooked some of these when reviewing https://github.com/element-hq/element-call/pull/3006.
2025-03-05 09:18:31 -05:00
fkwp
c579904f29 added rule for ignoring draw.io backup files 2025-03-05 13:37:04 +01:00
Robin
28c45c6107 Avoid closing the widget in returnToLobby mode
If returnToLobby is enabled then we obviously want to keep the widget open once the user leaves the call.
2025-03-05 07:32:25 -05:00
Robin
b5f5edba09 Fix the control flow of GroupCallView render function
2bb5b020e6 refactored the end of the GroupCallView render function to not use any early returns, and clumsily failed to account for the fall-through case that makes returnToLobby work (as opposed to sitting on a blank screen).
2025-03-05 07:29:56 -05:00
Robin
771397389c Prevent PRs with the X-Blocked label from being merged (#3041)
Copied from matrix-js-sdk (https://github.com/matrix-org/matrix-js-sdk/blob/develop/.github/workflows/pull_request.yaml#L31)
2025-03-05 10:44:10 +00:00
Timo
939eac5a66 change lk log level to warn (#3049) 2025-03-04 19:37:51 +01:00
Robin
e783339557 Merge pull request #3035 from element-hq/renovate/all-minor-patch
Update all non-major dependencies
2025-03-04 00:14:56 -05:00
Robin
36203c2017 Work around LiveKit's overly constrained dependencies
We need compatible versions of RxJS in our dependencies and LiveKit's dependencies, but LiveKit has pinned it to a very specific version which is now holding us back from updating. See https://github.com/livekit/components-js/issues/1101 for a request for a proper solution.
2025-03-04 00:13:00 -05:00
Robin
db9f255a4a Update formatting 2025-03-03 23:41:29 -05:00
Robin
6d6852d5b0 Merge pull request #3006 from Harshal-Taori-11/livekit
Added OpenGraph and Twitter meta tags for better link previews
2025-03-03 23:37:10 -05:00
Valere Fedronic
f80e9452ec Merge pull request #3037 from element-hq/valere/fix_i18n_test_not_configured
Fix: i18n not properly configured in vitest
2025-03-03 17:17:53 +01:00
fkwp
815b013d53 Merge pull request #3034 from element-hq/renovate/github-actions
Update GitHub Actions
2025-03-03 17:04:57 +01:00
renovate[bot]
518f1f7bee Update all non-major dependencies 2025-03-03 15:55:00 +00:00
renovate[bot]
8aa95d1ddd Update GitHub Actions 2025-03-03 15:54:20 +00:00
Valere
4c91326edb fix, testing: i18n not properly configured 2025-03-03 14:41:31 +01:00
ElementRobot
05e81a8143 Merge pull request #3030 from element-hq/actions/localazy-download
Localazy Download
2025-02-28 13:40:30 +00:00
fkwp
4fa1b26827 Translations updates 2025-02-28 13:38:53 +00:00
Valere Fedronic
66899f33e2 Merge pull request #3027 from element-hq/valere/missing_livekit_url_config
Error Handling: gracefully handle missing MatrixRTC focus configuration
2025-02-28 13:43:01 +01:00
Valere
f38adf12d9 review: remove not yet used case ErrorCategory in rich error 2025-02-28 12:25:35 +01:00
Valere
5dfc89d36c fixup: lint error 2025-02-28 12:24:43 +01:00
Valere
1fbf8e2686 review: Report unknown exceptions when entering RTC session 2025-02-28 12:17:28 +01:00
Valere
2b35573672 review: Upate error.unexpected_ec_error for consistency 2025-02-28 12:06:31 +01:00
Valere
f8a5de604f review: rename ec-error file to error 2025-02-28 12:04:49 +01:00
fkwp
b355615236 Merge pull request #3029 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.9.5
2025-02-28 11:58:24 +01:00
renovate[bot]
4ebbb3382a Update dependency livekit-client to v2.9.5 2025-02-28 10:56:09 +00:00
Hugh Nimmo-Smith
7761e042fb Update readme to reflect latest config.json and matrix-js-sdk dependency (#3028) 2025-02-28 10:05:36 +00:00
Strac Consulting Engineers Pty Ltd
acc0b64968 Update config.sample.json (#3001)
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-02-27 18:25:24 +00:00
Valere
4701e413fd fixup: MissingRTCFocus error, fix confusion between domain/brand 2025-02-27 10:09:26 +01:00
Valere
b43defedfd fixup: i18n incorrect ordering of keys 2025-02-27 09:32:43 +01:00
Valere
2ba803fcef review: Improve error structure + better RTCFocus error message 2025-02-27 09:26:38 +01:00
Valere
109809182f fixup: Unused (yet) ErrorCode enum value 2025-02-26 15:37:28 +01:00
Valere
3c23e5a4e6 Error Handling: gracefully handle missing livekit service url in config 2025-02-26 15:19:08 +01:00
Valere
7423dfa527 refactor: Introduce specific ElementCall error type with code 2025-02-26 14:58:31 +01:00
Robin
31577d7263 Show an error screen when the SFU is at capacity (#3022)
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
Co-authored-by: fkwp <fkwp@users.noreply.github.com>
2025-02-26 12:00:56 +00:00
Robin
2bb5b020e6 Leave session when error occurs and show error screens in widget mode (#3021)
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
2025-02-26 10:20:30 +00:00
Robin
cd05df3e33 Merge pull request #3020 from element-hq/robin/clarify-use-latest
Clarify what useLatest is for
2025-02-24 18:22:46 +07:00
Robin
9b59544db2 Clarify what useLatest is for
I was touching this file and noticed a chance to clean up this little TODO comment by swapping in our useLatest hook and giving it better documentation.
2025-02-24 18:18:15 +07:00
Robin
91671d9ff1 Merge pull request #3019 from element-hq/robin/actually-hide-header
Actually hide the header on error pages
2025-02-24 17:47:22 +07:00
Robin
e4d7baf7bb Actually hide the header on error pages
Currently, if you set hideHeader to true, you get a big empty <header> on error pages which serves no purpose except to push the screen's content off center.
2025-02-24 17:37:11 +07:00
Robin
832a5aaf57 Merge pull request #3011 from element-hq/robin/close-action
Send a 'close' action when the widget is ready to close
2025-02-24 17:23:33 +07:00
fkwp
5e8395262c Merge pull request #3017 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.9.3
2025-02-24 08:28:40 +01:00
Robin
518c8eadca Finish the hangup procedure even if widget API throws errors 2025-02-24 11:48:05 +07:00
renovate[bot]
ad461a7643 Update dependency livekit-client to v2.9.3 2025-02-24 02:54:51 +00:00
Robin
028b3104e4 Merge pull request #3009 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.9.1
2025-02-20 13:24:17 +07:00
Robin
a75952cf77 Send a 'close' action when the widget is ready to close
By keeping 'hangup' and 'close' as separate actions, we can allow Element Call widgets to stay on an error screen after the user has been disconnected without the widget completely disappearing from the host's UI. We don't have to request any additional capabilities to use a custom widget action like this one.
2025-02-20 11:17:17 +07:00
Timo
4015efa6c6 fix lk usage in test 2025-02-20 06:33:01 +03:00
Harshal Taori
c276af7006 Merge branch 'livekit' of https://github.com/Harshal-Taori-11/element-call into livekit 2025-02-19 14:25:05 +05:30
Harshal-Taori-11
64d33426e4 Merge branch 'element-hq:livekit' into livekit 2025-02-19 14:19:02 +05:30
Harshal Taori
aafae258ac Changed the title to env variable and removed url and domain tags. 2025-02-19 14:17:33 +05:30
Hugh Nimmo-Smith
0f5dc33918 Fix copyright header to say dual license not just AGPL (#3013)
This probably should have been part of https://github.com/element-hq/element-call/pull/2984
2025-02-18 17:59:58 +00:00
renovate[bot]
f111c64264 Update dependency livekit-client to v2.9.1 2025-02-18 15:52:41 +00:00
Harshal Taori
292095abf0 Added OpenGraph and Twitter meta tags for better link previews 2025-02-13 21:29:08 +05:30
Hugh Nimmo-Smith
294e67a5ba Show current SFU and Server Info in developer tab (#3000)
* Show current SFU and Server Info in developer tab

* Lint
2025-02-10 18:22:19 +01:00
Hugh Nimmo-Smith
6e3fd10268 Explicitly build and publish docker for develop/livekit branch (#2996)
We don't need the tarball artifact and we have already done a build
2025-02-07 16:31:44 +00:00
Hugh Nimmo-Smith
0128f2f258 Don't produce compressed assets at build time and instead do it as part of the nginx build (#2995)
The core vite build shouldn't be responsible for implementing optimisations that are specific to a particular distribution mechanism. e.g. static compressed files for nginx.

This way the core build is "clean".

Instead, the packager/distributor of the build should be responsible for it. e.g. the nginx docker distribution should do any optimisations that it chooses.
2025-02-06 15:16:55 +01:00
Hugh Nimmo-Smith
e23d8828ad GitHub Action workflows cannot be in a sub folder 2025-02-06 12:55:28 +00:00
Hugh Nimmo-Smith
613675553f Fix typo in license filename 2025-02-06 12:52:11 +00:00
Hugh Nimmo-Smith
6dcfdf8d39 Cleanup GitHub Actions (#2983)
This is mostly just about naming. Plus removing an unused end-to-end testing workflow.
2025-02-06 13:13:08 +01:00
Hugh Nimmo-Smith
4fc7fbe8fe Use --frozen-lockfile when install deps in CI (#2992) 2025-02-05 17:28:52 +01:00
renovate[bot]
f49355a51f Update LiveKit components (#2962)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-05 16:14:04 +00:00
renovate[bot]
c3ad7844fb Update dependency vitest to v3.0.5 [SECURITY] (#2986)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-05 16:07:33 +00:00
Matthew Hodgson
1fa4a6f2e4 dual license AGPL + Commercial (#2984)
* dual license AGPL + Commercial

* Lint

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-02-05 16:01:51 +00:00
Timo
e25e6caa89 Resolve version clash in matrix-widget-api dependency (#2988)
* Downgrade widget api version to v1.11.0 to not include STATE_UPDATE api version

* Downgrade to v1.10.0 for js-sdk compatibility

* Add "matrix-widget-api" to resolutions block

* bump matrix-widget-api to v1.11.0 for theme change compatibility
2025-02-05 10:11:13 +00:00
Timo
bff2b73c85 Bump matrix-js-sdk to v36.1.0 (#2967)
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-02-03 12:28:12 +00:00
Will Hunt
1dde54daa9 Use matrixIdentifier for screenshare (#2981) 2025-02-03 10:17:19 +00:00
Hugh Nimmo-Smith
1d1289b7bf Fix renovate schedule settings (#2979) 2025-01-29 18:21:08 +00:00
Hugh Nimmo-Smith
7ba7ddcdc5 Adjust renovate bot schedule and enable vulnerability updates (#2977) 2025-01-29 17:27:21 +01:00
Hugh Nimmo-Smith
31e59c1da1 Do run build action in CI when GHA workflows change (#2976) 2025-01-28 12:13:30 +01:00
Hugh Nimmo-Smith
7d444fc261 Automatically deploy livekit branch to call.element.dev via workflow dispatch (#2974) 2025-01-28 10:15:44 +00:00
renovate[bot]
26ce899548 Update dependency @stylistic/eslint-plugin to v3 (#2968)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 09:46:36 +01:00
renovate[bot]
06d4206524 Update dependency livekit-client to v2.8.1 (#2970)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-28 09:45:25 +01:00
renovate[bot]
a16391c342 Update all non-major dependencies (#2969)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-27 13:55:46 +01:00
Will Hunt
3506ca7feb Fix calculation of local membership identifier (#2966) 2025-01-23 13:42:29 +00:00
renovate[bot]
5f78f544b7 Update all non-major dependencies (#2961)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-23 09:25:49 +01:00
renovate[bot]
d862466bb0 Update dependency vite to v6.0.9 [SECURITY] (#2964)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-22 17:58:32 +00:00
Robin
e636542b1e Prevent new devices from automatically starting unmuted in call (#2959) 2025-01-17 15:30:28 +00:00
Robin
cda802a2e9 Make error screens more visually consistent (#2951) 2025-01-17 09:35:39 +00:00
Robin
c218dc2f36 Remember previous mute states when devices disappear and reappear (#2957) 2025-01-17 09:11:17 +00:00
Robin
74d4556878 Merge pull request #2954 from element-hq/renovate/major-vitest-monorepo
Update vitest monorepo to v3 (major)
2025-01-16 15:49:34 -05:00
Robin
e68593ec47 Upgrade to vitest 3.0.1 2025-01-16 15:47:53 -05:00
Robin
e79a32ac63 Merge pull request #2950 from element-hq/renovate/sentry-vite-plugin-3.x
Update dependency @sentry/vite-plugin to v3
2025-01-16 15:34:45 -05:00
Will Hunt
3189bdba2a Fix displayname calculation around RTL / unhomoglyth. (#2953) 2025-01-16 17:26:58 +00:00
renovate[bot]
a1eb5a9770 Update vitest monorepo to v3 2025-01-16 15:31:49 +00:00
Hugh Nimmo-Smith
723fa290ff Bump matrix-js-sdk to latest (#2946)
Co-authored-by: Timo <toger5@hotmail.de>
2025-01-16 10:31:05 -05:00
renovate[bot]
d2e5514928 Update dependency @sentry/vite-plugin to v3 2025-01-15 10:37:27 +00:00
Will Hunt
0f2e67dd60 Disambiguate displaynames (#2918)
* Disambigute displaynames

* Add test

* fixup test functions

* prettier

* lint

* Split displayname utils into own file and add tests.

* Split out fixtures

* Add more testcases for displayname calculation.

* lint

* Also listen for displayname changes. (I stand corrected!)

* fix missing media tiles on missing member
2025-01-14 14:46:39 +00:00
Hugh Nimmo-Smith
d9e0c67315 Use correct Sentry entrypoints for react router v7 (#2943) 2025-01-13 16:34:44 +00:00
renovate[bot]
497ee3c7f7 Update GitHub Actions (#2945)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 17:07:38 +01:00
Hugh Nimmo-Smith
2f5f0978ad Type fixes for react v19 compatibility (#2937) 2025-01-13 15:54:42 +01:00
renovate[bot]
c8b30dd8a7 Update dependency eslint-config-prettier to v10 (#2944)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 15:52:11 +01:00
renovate[bot]
3d2663d740 Update dependency jsdom to v26 (#2938)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 12:05:26 +00:00
renovate[bot]
2206ad287e Update all non-major dependencies (#2942)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 12:03:57 +00:00
renovate[bot]
402d028696 Update dependency global-jsdom to v26 (#2941)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-13 12:01:51 +00:00
Robin
0f40cb77ad Merge pull request #2940 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.8.0
2025-01-10 11:43:43 -05:00
renovate[bot]
df92f4814b Update dependency livekit-client to v2.8.0 2025-01-10 13:55:07 +00:00
Robin
8bfdd1f455 Merge pull request #2910 from robintown/widget-theme-change
React to theme changes in widget mode
2025-01-08 15:56:02 -05:00
renovate[bot]
d985bd3b3f Update dependency strip-ansi to v7 (#2639)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-01-08 17:17:55 +00:00
renovate[bot]
54c669126f Update dependency eslint-plugin-matrix-org to v2 (#2677)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-01-08 17:08:28 +00:00
renovate[bot]
dc784e95cd Update dependency react-router-dom to v7 (#1624)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-01-08 16:42:07 +00:00
Robin
acd4a1f179 Fix tests 2025-01-08 11:41:44 -05:00
Robin
c66b8c0fd3 Merge branch 'livekit' into widget-theme-change 2025-01-08 11:27:46 -05:00
Robin
cdde53cc44 Bump matrix-widget-api 2025-01-08 11:27:33 -05:00
davidegirardi
d5bf65057a Add wave/hello reaction (#2921)
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
Co-authored-by: Davide Girardi <davideg@element.io>
2025-01-08 14:05:07 +00:00
Will Hunt
7e507d6310 Set the document title to the current call name. (#2928)
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2025-01-08 13:24:23 +00:00
renovate[bot]
00759e2431 Update all non-major dependencies (#2934)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 13:26:03 +01:00
renovate[bot]
9bfc08ab53 Update dependency vaul to v1.1.2 (#2935)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 12:13:55 +00:00
renovate[bot]
7a03adb054 Update docker/build-push-action action to v6.11.0 (#2936)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 12:13:06 +00:00
renovate[bot]
50d30809ef Update codecov/codecov-action action to v5 (#2933)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-08 09:26:00 +00:00
renovate[bot]
123942901d Update dependency @vector-im/compound-web to v7.6.2 (#2932)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-07 17:21:30 +00:00
fkwp
9dcd7aaf50 Merge pull request #2930 from element-hq/renovate/github-actions
Update GitHub Actions
2025-01-07 16:59:07 +01:00
renovate[bot]
6420e211c6 Update GitHub Actions 2025-01-07 15:53:36 +00:00
Hugh Nimmo-Smith
8c2844e0b5 Use documented @sentry/vite-plugin config options (#2925) 2025-01-07 10:21:56 -05:00
Hugh Nimmo-Smith
939aaa39eb Remove unnecessary dependency on @testing-library/react-hooks (#2926) 2025-01-07 10:18:45 -05:00
renovate[bot]
698a38a265 Update dependency i18next to v24 (#2822)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
2025-01-06 17:14:17 +00:00
Quentin Gliech
b5f4a07868 Upgrade to React Router v6 (#2919) 2025-01-06 17:00:20 +00:00
renovate[bot]
46a82b2c39 Update dependency @vector-im/compound-design-tokens to v3 (#2896)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 12:18:12 +00:00
renovate[bot]
d6942bc71d Update all non-major dependencies (#2924)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-06 11:34:37 +00:00
Hugh Nimmo-Smith
2c33d65824 Add developer mode option to show RTC connection statistics (#2904)
* Add developer mode option to show RTC connection statistics

* Add note about localization

* Add titles to help explain what the numbers are

* Workaround horizontal scrolling

* Use modal to show detailed stats instead of alert

* Changed styling and fixed fps = 0 (#2916)

(React rendered 0 instead of <Text /> for fps && <Text>{fps}</text>)

---------

Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
2025-01-06 09:47:39 +00:00
fkwp
f521e260b6 Merge pull request #2923 from element-hq/renovate/livekit-components
Update LiveKit components
2025-01-06 10:11:15 +01:00
renovate[bot]
89e33743ae Update LiveKit components 2025-01-06 02:39:08 +00:00
renovate[bot]
dc904fdbd2 Update dependency @livekit/components-react to v2.6.10 (#2920)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-03 14:01:44 +01:00
renovate[bot]
6776c2af35 Update Compound (#2895)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-03 14:00:32 +01:00
Robin
e477c16a0b Fix lint errors 2025-01-02 13:32:39 -05:00
Will Hunt
abf2ecd521 Refactor reactions / hand raised to use rxjs and start ordering tiles based on hand raised. (#2885)
* Add support for using CallViewModel for reactions sounds.

* Drop setting

* Convert reaction sounds to call view model / rxjs

* Use call view model for hand raised reactions

* Support raising reactions for matrix rtc members.

* Tie up last bits of useReactions

* linting

* Update calleventaudiorenderer

* Update reaction audio renderer

* more test bits

* All the test bits and pieces

* More refactors

* Refactor reactions into a sender and receiver.

* Fixup reaction toggle button

* Adapt reactions test

* Tests all pass.

* lint

* fix a couple of bugs

* remove unused helper file

* lint

* finnish notation

* Add tests for useReactionsReader

* remove mistaken vitest file

* fix

* filter

* invert

* fixup tests with fake timers

* Port useReactionsReader hook to ReactionsReader class.

* lint

* exclude some files from coverage

* Add screen share sound effect.

* cancel sub on destroy

* tidy tidy
2024-12-19 15:54:28 +00:00
Will Hunt
7d00f85abc Add screen share sound effect. (#2917) 2024-12-19 12:37:10 +00:00
Hugh Nimmo-Smith
6d5dc0dfb7 Fix loading of matrix-sdk-crypto-wasm when running in local development mode (#2915)
Fixes problem loading rust crypto when using `yarn dev`
2024-12-18 17:03:29 +00:00
Hugh Nimmo-Smith
ba5da7e9af Inform user that their camera is starting in Lobby (#2869)
* Inform user that their camera is starting

Instead of just showing a grey box.

* Review feedback

* Show spinner from design suggestion

* useMemo

* Lint

* Lint

* Feedback from review

* Use colour that actually exists

* Refactor into Avatar superclass

* .

* Remove size limit behaviour

* Add VideoPreview tests
2024-12-18 15:31:45 +00:00
Hugh Nimmo-Smith
19d0f84f02 Introduce intent URL param and make it change the default lobby behaviour (#2828)
* Introduce `intent` URL param and make it change the default lobby behaviour

* Mark skipLobby as deprecated

* Add support for unknown intent which is default for when not specified
2024-12-18 15:30:33 +00:00
Hugh Nimmo-Smith
6b8dddfaaa Bump matrix-js-sdk for bundle improvements (#2911)
Brings in updated version of matrix-sdk-crypto-wasm which helps to reduce bundle size and lazy loading.

Full diff d1de32ea27...e4182eb752
2024-12-18 09:35:42 +00:00
Robin
5d8804d7e8 React to theme changes in widget mode 2024-12-17 20:03:17 -05:00
Hugh Nimmo-Smith
53fff37d5d Use AutoDiscovery.getRawClientConfig() instead of MatrixClient.getClientWellKnown() (#2906)
I'm open to suggestions on what is sensible to test around this...
2024-12-17 17:44:50 +01:00
Hugh Nimmo-Smith
2b6acb9cce Use afterEach from vitest for consistency (#2908)
This slipped through the PR review. Whilst not harmful, for consistency we use it from vitest.
2024-12-17 11:17:37 +01:00
Hugh Nimmo-Smith
79c40f198c Use finnish notation for observables (#2905)
To help make our usage of the observables more readable/intuitive.
2024-12-17 04:01:56 +00:00
Robin
e4bd9d7cf9 Merge pull request #2816 from robintown/firefox-audio-output
Support selection of audio output device when using Firefox
2024-12-16 10:14:27 -05:00
Robin
65cf8bf3ee Merge pull request #2899 from robintown/array-performance
Skip some redundant updates to the grid and spotlight
2024-12-16 10:06:52 -05:00
Timo
ed269e0711 Revert "Wait for .well-known/matrix/client to load before determining MatrixRTC foci" (#2902)
This reverts commit 92afd5d63a.
2024-12-16 14:12:12 +00:00
renovate[bot]
b822b9f80d Update all non-major dependencies (#2900)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-16 13:44:57 +01:00
ElementRobot
f1fa814fa2 Merge pull request #2898 from element-hq/actions/localazy-download
Localazy Download
2024-12-16 11:53:47 +00:00
Hugh Nimmo-Smith
92afd5d63a Wait for .well-known/matrix/client to load before determining MatrixRTC foci (#2901) 2024-12-16 11:22:23 +00:00
Robin
25d0338f35 Skip some redundant updates to the grid and spotlight
While debugging our layout shift issue I learned that a single change to the sort order of the participants can cause 3 or 4 redundant emissions of the same items in the same order. Since each of these would cause React to re-render the grid, skipping these spurious emissions seems like an easy performance win.
2024-12-13 16:40:20 -05:00
Robin
f9e3fe3176 Use observables for more of the media devices logic 2024-12-13 15:37:29 -05:00
Robin
de276b1fc3 Annotate the default device with a label 2024-12-13 15:22:44 -05:00
Robin
9c57720852 Merge branch 'livekit' into firefox-audio-output 2024-12-13 14:55:27 -05:00
Hugh Nimmo-Smith
a723f10d2c Developer setting to show LiveKit participants that do not have MatrixRTC sessions a.k.a. non-member tiles (#2771)
* make tiles based on rtc member

* display missing lk participant + fix tile multiplier

* add show_non_member_participants config option

* per member tiles

* merge fixes

* linter

* linter and tests

* tests

* adapt tests (wip)

* Remove unused keys

* Fix optionality of nonMemberItemCount

* video is optional

* Mock RTC members

* Lint

* Merge fixes

* Fix user id

* Add explicit types for public fields

* isRTCParticipantAvailable => isLiveKitParticipantAvailable

* isLiveKitParticipantAvailable

* Readonly

* More keys removal

* Make local field based on view model class not observable

* Wording

* Fix RTC members in tes

* Tests again

* Lint

* Disable showing non-member tiles by default

* Duplicate screen sharing tiles like we used to

* Lint

* Revert function reordering

* Remove throttleTime from bad merge

* Cleanup

* Tidy config of show non-member settings

* tidy up handling of local rtc member in tests

* tidy up test init

* Fix mocks

* Cleanup

* Apply local override where participant not yet known

* Handle no visible media id

* Assertions for one-on-one view

* Remove isLiveKitParticipantAvailable and show via encryption status

* Handle no local media (yet)

* Remove unused effect for setting

* Tidy settings

* Avoid case of one-to-one layout with missing local or remote

* Iterate

* Remove option to show non-member tiles to simplify code review

* Remove unused code

* Remove more remnants of show-non-member-tiles

* iterate

* back

* Fix unit test

* Refactor

* Expose TestScheduler as global

* Fix incorrect type assertion

* Simplify speaking observer

* Fix

* Whitespace

* Make it clear that we are mocking MatrixRTC memberships

* Test case for only showing tiles for MatrixRTC session members

* Simplify diff

* Simplify diff

These changes are in https://github.com/element-hq/element-call/pull/2809

* .

* Whitespaces

* Use asObservable when exposing subject

* Show "waiting for media..." when no participant

* Additional test case

* Don't show "waiting for media..." in case of local participant

* Make the loading state more subtle
 - instead of a label we show a animated gradient

* Use correct key for matrix rtc foci in code comment. (#2838)

* Update src/tile/SpotlightTile.tsx

Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>

* Update src/state/CallViewModel.ts

Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>

* Make the purpose of BaseMediaViewModel.local explicit

* Use named object instead of unnamed array for spotlightAndPip

* Refactor spotlightAndPip into spotlight and pip

* Use if statement instead of ternary for readability in spotlight and pip logic

* Review feedback

* Fix tests for CallEventAudioRenderer

* Lint

* Developer setting to show non-member tiles

This is based on top of https://github.com/element-hq/element-call/pull/2701

* Lint

* Remove unused code

* Remove changes that should be in https://github.com/element-hq/element-call/pull/2858

* Update src/state/CallViewModel.test.ts

Co-authored-by: Robin <robin@robin.town>

* Merge branch 'livekit' into toger5/show-non-member-tiles

* Remove unused nonMemberItemCount

* Restore default showNonMemberTiles value after test

* Update comments

---------

Co-authored-by: Timo <toger5@hotmail.de>
Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>
Co-authored-by: Robin <robin@robin.town>
2024-12-13 14:53:08 +00:00
robintown
31be6cc804 Translations updates 2024-12-13 14:28:28 +00:00
Robin
0c66ec5d71 Merge pull request #2894 from robintown/stable-visibility
Determine which tiles are on screen in a more stable manner
2024-12-13 09:16:49 -05:00
Hugh Nimmo-Smith
92813bd3ca Bump matrix-js-sdk (#2897)
So that we get https://github.com/matrix-org/matrix-js-sdk/pull/4575

Full diff: edac6a9983...d1de32ea27
2024-12-13 14:12:29 +00:00
Hugh Nimmo-Smith
e84ecc68b3 Refactor preferences tab strings for consistency (#2888)
* Refactor preferences tab strings for consistency

* Lint
2024-12-13 13:23:32 +00:00
Hugh Nimmo-Smith
7807c44fdc Clean up useMuteStates test (#2891)
We don't need to be mocking React for this test.
2024-12-13 10:09:27 +00:00
fkwp
1cbb6dff81 Merge pull request #2855 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.7.1
2024-12-13 03:24:44 +01:00
Timo
b993c5eb12 fix linter 2024-12-13 03:23:20 +01:00
Robin
53565ddb76 Test that participants adjust order when screen size changes 2024-12-12 19:16:01 -05:00
Robin
00056a7cd9 Determine which tiles are on screen in a more stable manner
Instead of tracking for each individual tile whether it's visible, just track the total number of tiles that appear on screen. This ought to make the whole thing a lot less dynamic, which is crucial given that our UI renders asynchronously and RxJS doesn't really support cyclic dependencies in any rigorous way.

In particular this ought to make the following kind of situation impossible:
1. There 3 tiles, ABC. A and B are on screen.
2. Now C becomes important. The requested order is now CAB.
3. To reduce the size of the layout shift, the algorithm selects to swap just B and C in the original order, giving ACB. However, the UI is blocked and doesn't render this order yet.
4. For whatever reason, a spurious update of the importance algorithm occurs. It once again requests CAB.
5. Now because the UI was blocked, the layout still thinks that A and B are on screen (rather than A and C). It thinks that C is some weird island of "off-screen territory" in the middle of the tile order. This confuses it into swapping A and C rather than keeping the layout stable.

The reality is that whenever we think N tiles are visible on screen, we're always referring to the first N tiles in the grid. It's best if the code reflects this assumption.
2024-12-12 18:00:59 -05:00
renovate[bot]
4d6740cf2c Update dependency livekit-client to v2.7.5 2024-12-12 19:40:55 +00:00
Will Hunt
77facd01e4 Add support for playing a sound when the user exits a call. (#2860)
* Refactor to use AudioContext

* Remove unused audio format.

* Reduce update frequency for volume

* Port to useAudioContext

* Port reactionaudiorenderer to useAudioContext

* Integrate raise hand sound into call event renderer.

* Simplify reaction sounds

* only play one sound per reaction type

* Start to build out tests

* fixup tests / comments

* Fix reaction sound

* remove console line

* Remove another debug line.

* fix lint

* Use testing library click

* lint

* Add support for playing a sound when the user exits a call.

* Port GroupCallView to useAudioContext

* Remove debug bits.

* asyncify

* lint

* lint

* lint

* tidy

* Add test for group call view

* Test widget mode too.

* fix ?.

* Format

* Lint

* Lint

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2024-12-12 07:33:47 +00:00
Hugh Nimmo-Smith
6c81f69590 Rename developerSettingsTab to developerMode for consistency (#2889) 2024-12-11 14:30:16 +00:00
Robin
b834d8f679 Add some quick-and-dirty debug info for TileStore (#2887)
* Add some quick-and-dirty debug info for TileStore

I'm still in need of more detailed data in order to understand why big layout shifts happen in large calls. This adds a developer option to enable logging and a visual indicator for the state of the TileStore. The indicator should be useful for matching up the behavior I'm seeing in my recordings with the right timestamps.

* Reduce performance impact of checking for whether debug mode is enabled

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2024-12-11 10:23:42 +00:00
Hugh Nimmo-Smith
54149a496c Simplify settings tabs (#2875)
* Simplify settings tabs

- Move Analytics to Feedback tab
- Rename Developer Settings to Developer Mode and move to Preferences tab
- Clean up Preferences tab
- Only way to see version number is by enabling Developer Mode

* Remove extra label

* Lint

* Lint

* Update locales/en/app.json

Co-authored-by: Robin <robin@robin.town>

---------

Co-authored-by: Robin <robin@robin.town>
2024-12-11 09:36:59 +00:00
Hugh Nimmo-Smith
0087e37f30 Enable @typescript-eslint/consistent-type-imports lint rule (#2886)
* Enable @typescript-eslint/consistent-type-imports lint rule

This is to help ensure that we get proper vite/rollup lazy loading by not `import`ing more than we need to.

Revert "Enable @typescript-eslint/consistent-type-imports lint rule"

This reverts commit ba385fa00b7e410cc508fd5fb9fe972233ae114f.

Enable @typescript-eslint/consistent-type-imports lint rule

This is to help ensure that we get proper vite/rollup lazy loading by not `import`ing more than we need to.

.

* Format
2024-12-11 09:27:55 +00:00
Hugh Nimmo-Smith
8558f0349f Check for parentUrl when deciding whether a SPA specific url parameter should be ignored (#2881) 2024-12-11 09:26:55 +00:00
Hugh Nimmo-Smith
45564fd629 Ignore URL params where they are not applicable for the mode (widget vs SPA) (#2882) 2024-12-11 09:23:37 +00:00
Hugh Nimmo-Smith
da63db26d6 Add missing full stops from end of settings descriptions (#2883)
For consistency
2024-12-11 09:22:12 +00:00
Robin
f8f054a4f9 Merge pull request #2853 from element-hq/renovate/vite-6.x
Update dependency vite to v6
2024-12-10 13:23:52 -05:00
Robin
22678a7c71 Merge pull request #2880 from element-hq/renovate/all-minor-patch
Update all non-major dependencies
2024-12-10 13:06:36 -05:00
Robin
8b19beae68 Fix lint errors 2024-12-10 13:05:09 -05:00
renovate[bot]
69ed91d6d4 Update all non-major dependencies 2024-12-10 15:15:57 +00:00
Hugh Nimmo-Smith
d698705ffa Configure sentry integration for netlify PR previews (#2884) 2024-12-09 14:01:06 +00:00
Will Hunt
a8a95c3f00 Ensure call sound effects are played over the correct sink (#2863)
* Refactor to use AudioContext

* Remove unused audio format.

* Reduce update frequency for volume

* Port to useAudioContext

* Port reactionaudiorenderer to useAudioContext

* Integrate raise hand sound into call event renderer.

* Simplify reaction sounds

* only play one sound per reaction type

* Start to build out tests

* fixup tests / comments

* Fix reaction sound

* remove console line

* Remove another debug line.

* fix lint

* Use testing library click

* lint

* fix a few things

* Change the way we as unknown the mock RTC session.

* Lint

* Fix types for MockRTCSession

* value change should always be set

* Update volume slider description.

* Only load reaction sound effects if enabled.

* cache improvements

* lowercase soundMap

* lint

* move prefetch sounds to fix hot reload

* correct docs

* add a header

* Wording change

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2024-12-09 11:39:16 +00:00
Will Hunt
9d4cd211ed Authenticate media requests when loading avatars (#2856)
* Load authenicated media

* lint

* Add tests

* Add widget behaviour and test.

* Update src/Avatar.test.tsx

Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
2024-12-06 18:30:05 +00:00
Hugh Nimmo-Smith
4fab1a25b4 Use specific Node.js version (22) instead of latest LTS (#2879)
This way we can manage the upgrade cycle ourselves.
2024-12-06 18:15:49 +00:00
ElementRobot
2fe199de71 Merge pull request #2877 from element-hq/actions/localazy-download
Localazy Download
2024-12-06 15:13:50 +00:00
fkwp
65cc583c8a Translations updates 2024-12-06 15:04:29 +00:00
Timo
43c81a2758 Make video tiles be based on MatrixRTC member not LiveKit participants (#2701)
* make tiles based on rtc member

* display missing lk participant + fix tile multiplier

* add show_non_member_participants config option

* per member tiles

* merge fixes

* linter

* linter and tests

* tests

* adapt tests (wip)

* Remove unused keys

* Fix optionality of nonMemberItemCount

* video is optional

* Mock RTC members

* Lint

* Merge fixes

* Fix user id

* Add explicit types for public fields

* isRTCParticipantAvailable => isLiveKitParticipantAvailable

* isLiveKitParticipantAvailable

* Readonly

* More keys removal

* Make local field based on view model class not observable

* Wording

* Fix RTC members in tes

* Tests again

* Lint

* Disable showing non-member tiles by default

* Duplicate screen sharing tiles like we used to

* Lint

* Revert function reordering

* Remove throttleTime from bad merge

* Cleanup

* Tidy config of show non-member settings

* tidy up handling of local rtc member in tests

* tidy up test init

* Fix mocks

* Cleanup

* Apply local override where participant not yet known

* Handle no visible media id

* Assertions for one-on-one view

* Remove isLiveKitParticipantAvailable and show via encryption status

* Handle no local media (yet)

* Remove unused effect for setting

* Tidy settings

* Avoid case of one-to-one layout with missing local or remote

* Iterate

* Remove option to show non-member tiles to simplify code review

* Remove unused code

* Remove more remnants of show-non-member-tiles

* iterate

* back

* Fix unit test

* Refactor

* Expose TestScheduler as global

* Fix incorrect type assertion

* Simplify speaking observer

* Fix

* Whitespace

* Make it clear that we are mocking MatrixRTC memberships

* Test case for only showing tiles for MatrixRTC session members

* Simplify diff

* Simplify diff

These changes are in https://github.com/element-hq/element-call/pull/2809

* .

* Whitespaces

* Use asObservable when exposing subject

* Show "waiting for media..." when no participant

* Additional test case

* Don't show "waiting for media..." in case of local participant

* Make the loading state more subtle
 - instead of a label we show a animated gradient

* Use correct key for matrix rtc foci in code comment. (#2838)

* Update src/tile/SpotlightTile.tsx

Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>

* Update src/state/CallViewModel.ts

Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>

* Make the purpose of BaseMediaViewModel.local explicit

* Use named object instead of unnamed array for spotlightAndPip

* Refactor spotlightAndPip into spotlight and pip

* Use if statement instead of ternary for readability in spotlight and pip logic

* Review feedback

* Fix tests for CallEventAudioRenderer

* Lint

* Revert "Make the loading state more subtle"

This reverts commit 765f7b4f31.

* Update src/state/CallViewModel.ts

Co-authored-by: Timo <16718859+toger5@users.noreply.github.com>

* Fix spelling

* Remove a non-null assertion that failed at runtime

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
Co-authored-by: Hugh Nimmo-Smith <hughns@users.noreply.github.com>
2024-12-06 11:28:37 +00:00
Hugh Nimmo-Smith
21b62dbd89 Use a consistent background colour for video tiles and avatars (#2868) 2024-12-05 13:26:31 +00:00
fkwp
d09efa3cfe Merge pull request #2872 from element-hq/renovate/github-actions
Update GitHub Actions
2024-12-05 12:34:55 +01:00
renovate[bot]
818abaac0f Update GitHub Actions 2024-12-05 11:32:31 +00:00
renovate[bot]
76ba02584d Update dependency vaul to v1.1.1 (#2656)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-05 12:10:35 +01:00
Hugh Nimmo-Smith
27620b9148 Rename en-GB language to en (#2866)
Fixes https://github.com/element-hq/element-call/issues/2865

If we want to have GB and US specific terms later on we can then add then in as `en-GB` and `en-US`.
2024-12-04 14:51:29 +00:00
fkwp
68867810f7 Merge pull request #2864 from element-hq/fkwp/update_README_state_after
add information about MSC4222 state_after
2024-12-03 17:23:35 +01:00
fkwp
3495f5b472 linting 2024-12-03 16:57:53 +01:00
fkwp
260a1df21b linting 2024-12-03 16:55:30 +01:00
fkwp
44e5d2ea91 add MSC4222 2024-12-03 16:54:37 +01:00
fkwp
5e449bd03f typo 2024-12-03 16:54:28 +01:00
fkwp
cf0bb4676a add information about MSC4222 state_after 2024-12-03 16:51:14 +01:00
renovate[bot]
97fd1f3696 Update dependency @vector-im/compound-design-tokens to v2 (#2671)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 10:08:01 +01:00
renovate[bot]
f4883ac098 Update dependency @types/node to v22 (#2695)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-12-03 10:07:31 +01:00
Will Hunt
cc260811e2 Add a lower limit to duplicate tiles. (#2854)
* Add a limit to duplicate tiles.

* missed a change
2024-12-02 17:15:33 +00:00
Hugh Nimmo-Smith
a37c3bfb48 Show hostname in developer settings (#2857)
Also refactored developer settings labels into own locale section
2024-12-02 15:43:19 +00:00
Will Hunt
ea6f2952af Add sound effect for call joined / left (#2794)
* Add renderer for call joined / left

* lint

* Add new sounds

* Updates sounds in renderer

* lint

* move import

* pad sounds with silence

* lint

* tidy

* Drop autoplay since we now subscribe correctly.

* Comitting test files I am going to be going to lunch so will tidy up in a little while.

* finish up tests

* Add support for multiple channels per sound.

* lint
2024-12-02 15:16:58 +00:00
renovate[bot]
cc58e4d429 Update dependency vite to v6 2024-12-02 11:11:39 +00:00
renovate[bot]
e142493380 Update all non-major dependencies (#2852)
* Update all non-major dependencies

* prettier

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Timo <toger5@hotmail.de>
2024-12-02 12:10:20 +01:00
fkwp
34cc50b84d Merge pull request #2851 from element-hq/toger5/light-raise-hand
Use light background
2024-11-29 18:22:38 +01:00
Timo
84b2dc8680 Use light background
- the icons and the font is dark so the bg should not be darkened. But making it lighter is making it easier to read.
2024-11-29 17:48:18 +01:00
Timo
e12f4fada0 Bump js-sdk (#2850)
-  This fixes, that clients dont resend keys if other join right after someone else just left.
2024-11-29 11:58:36 +01:00
fkwp
8cd681c6cc Merge pull request #2849 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.7.0
2024-11-29 11:51:05 +01:00
renovate[bot]
82360c674c Update dependency livekit-client to v2.7.0 2024-11-29 10:44:54 +00:00
Hugh Nimmo-Smith
32ccfe8813 Fix Cache-Control header for docker images (#2847) 2024-11-28 17:40:06 +00:00
Timo
65e962bf1b Fix wrong hand raise margins in pip tile. (#2840) 2024-11-28 17:24:24 +00:00
Timo
28da8c48da Mute state improvements including muting if skipLobby=true in SPA (Based on #2834) (#2846) 2024-11-28 18:05:12 +01:00
Hugh Nimmo-Smith
f7c7f41afd Upgrade js-sdk to develop with MSC4222 state_after support (#2841)
Diff 2210255d6f...8fc77c595a
2024-11-27 20:43:56 +00:00
Hugh Nimmo-Smith
cf174261c9 Some simple initial tests for MediaView (#2813)
* Some simple tests for MediaView

* Use jest-dom assertions

* Add tests for videoMuted

* Add test case for placeholder video track

* Revert yarn.lock changes

* More revert

* Deduplicate test case logic and improve names

* Use role and label
2024-11-25 20:22:02 +00:00
renovate[bot]
e36029c9c0 Update all non-major dependencies (#2835)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-25 18:46:30 +01:00
Hugh Nimmo-Smith
0469d8ef56 Add explicit code split on matrix-sdk-crypto-wasm to allow caching between deploys (#2823)
* Add explicit code split on matrix-sdk-crypto-wasm to allow caching between deploys

* Comment on removing once https://github.com/matrix-org/matrix-rust-sdk-crypto-wasm/pull/167 lands
2024-11-23 09:00:43 +00:00
Hugh Nimmo-Smith
fc8da6ef58 Use hot marbles for speaker tests (#2815)
* Refactor the speaker detection logic into observeSpeaker and add tests

@robintown the tests pass, but some of the values were off by 1ms from what I was expecting. Please can you sanity check them?

* Extra test cases and clean up

* Make distinctUntilChanged part of the observable itself

* More suggestions from code review

* Use hot marbles for speaker tests

This was originally part of https://github.com/element-hq/element-call/pull/2810

* Only feed speaking mocks to observables that ask for IsSpeakingChanged
2024-11-23 08:59:33 +00:00
Hugh Nimmo-Smith
4e1b4fae19 Refactor the speaker detection logic into observeSpeaker and add tests (#2814)
* Refactor the speaker detection logic into observeSpeaker and add tests

@robintown the tests pass, but some of the values were off by 1ms from what I was expecting. Please can you sanity check them?

* Extra test cases and clean up

* Make distinctUntilChanged part of the observable itself

* More suggestions from code review
2024-11-23 08:59:15 +00:00
Hugh Nimmo-Smith
5c18868aa4 The preload URL param shouldn't be used in SPA mode, so ignore it if not in widget (#2832)
* Refactor URL parameters into table

This is for readability and ahead of some possible changes

* Whitespace

* Lint

* The preload URL param shouldn't be used in SPA mode, so ignore it
2024-11-23 08:55:03 +00:00
Hugh Nimmo-Smith
9ce16b68e9 Refactor URL parameters into table (#2827)
* Refactor URL parameters into table

This is for readability and ahead of some possible changes

* Whitespace

* Lint

* Cleanup and correct fontScale
2024-11-23 08:51:27 +00:00
Robin
ad9114a6e4 Merge pull request #2833 from robintown/depluralize
Fix a singular string using the plural form
2024-11-22 13:58:12 -05:00
Robin
44e1c136df Fix a singular string using the plural form 2024-11-22 13:45:39 -05:00
Robin
1bbbd519c7 Merge pull request #2831 from robintown/shortcut-modifiers
Don't trigger keyboard shortcuts if modifiers are held
2024-11-22 13:25:24 -05:00
Robin
51e4a3b14b Don't trigger keyboard shortcuts if modifiers are held
None of these keyboard shortcuts expect modifier keys, so they should in fact expect the absence of modifiers.
2024-11-22 13:17:05 -05:00
Hugh Nimmo-Smith
8da38d173a Remove .well-known files from build process (#2830)
These don't get included in the docker images anyhow (due to them being excluded by defautl by https://github.com/actions/upload-artifact#uploading-hidden-files).

We need to inject the right values into our managed deployments elsewhere.
2024-11-22 18:12:29 +00:00
Robin
13887a8943 Merge pull request #2817 from element-hq/renovate/compound
Update dependency @vector-im/compound-web to v7.4.0
2024-11-22 09:31:35 -05:00
fkwp
03721f078b Merge pull request #2819 from element-hq/renovate/livekit-components
Update dependency @livekit/components-react to v2.6.9
2024-11-22 12:43:25 +01:00
renovate[bot]
d146bedf05 Update dependency @livekit/components-react to v2.6.9 2024-11-22 11:08:25 +00:00
fkwp
63f595f958 Merge pull request #2820 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.6.3
2024-11-22 12:07:10 +01:00
renovate[bot]
279912d951 Update dependency livekit-client to v2.6.3 2024-11-22 09:14:56 +00:00
renovate[bot]
94e5d032a1 Update dependency @vector-im/compound-web to v7.4.0 2024-11-22 02:01:23 +00:00
Robin
f249b7d463 Create a virtual default audio output
Managing your audio output manually is kind of cumbersome; Chrome creates a default audio output for us, but now that audio outputs are enabled on Firefox as well, I find it necessary for a good user experience that there always be a way to set it to "whatever the default is".
2024-11-21 14:43:30 -05:00
Robin
e5117b962c Enable audio output support on Firefox 2024-11-21 12:53:27 -05:00
Robin
720c400e5f Merge pull request #2802 from robintown/device-fall-back
Don't fall back as eagerly to unselected devices
2024-11-21 11:39:10 -05:00
Robin
0718774cef Clarify how preferred devices work 2024-11-21 11:32:15 -05:00
Robin
a2b452c1d8 Don't override the camera without pressing "switch camera" 2024-11-21 11:24:45 -05:00
Robin
465a784345 Merge branch 'livekit' into device-fall-back 2024-11-21 11:04:36 -05:00
Robin
8de96878c0 Merge pull request #2803 from robintown/device-radio
Replace device dropdowns with radio buttons
2024-11-21 10:47:44 -05:00
Hugh Nimmo-Smith
b7b9771577 Use hot test input marbles instead of cold (#2810)
* Use hot test input marbles instead of cold

These will be needed for https://github.com/element-hq/element-call/pull/2701

* Revert for "spotlight speakers swap places" test
2024-11-21 11:03:16 +00:00
Hugh Nimmo-Smith
3885eefa4c Disambiguate between types of "member" (#2807)
We have Matrix room members and MatrixRTC session memberships. Livekit also has rooms.

So, this attempts to make it more obvious as to what type you are referring to.
2024-11-21 11:02:05 +00:00
Hugh Nimmo-Smith
9176e06195 Some tsdoc and explicit typing (#2809)
* Some tsdoc and explicit typing

Pulled out of https://github.com/element-hq/element-call/pull/2701

* Extra typing
2024-11-21 11:01:43 +00:00
Robin
380fa67f57 Merge pull request #2811 from robintown/revert-memory-store
Revert memory store and update matrix-js-sdk
2024-11-20 10:42:41 -05:00
Robin
8830bd74cb Update matrix-js-sdk
Return matrix-js-sdk to the develop branch.
2024-11-20 10:40:08 -05:00
Robin
3ab9bb72e2 Revert "Init client with a memory store (for MSC4222) (#2764)"
This reverts commit 83fa9661cf. We won't need this hack once we're no longer using a matrix-js-sdk branch with MSC4222 support.
2024-11-20 10:22:42 -05:00
Robin
38085baab8 Replace device dropdowns with radio buttons
This is closer to what the designs actually want device settings to look like, and it avoids the visual glitch in which the dropdown would render underneath the slider.
2024-11-20 09:44:32 -05:00
Hugh Nimmo-Smith
8891a9a70e Make it clearer what are inputs and what are expected outputs in test cases (#2808)
Rationale: try and make the marbles section of each test case more readable
2024-11-20 14:44:23 +00:00
Hugh Nimmo-Smith
826d0ee40d Rxjs subjects should not be exposed (#2805)
This rule will encourage us to do the right thing and better abstract.

See https://github.com/cartant/eslint-plugin-rxjs/blob/main/docs/rules/no-exposed-subjects.md
2024-11-20 10:32:21 +00:00
Hugh Nimmo-Smith
fbc2cd3e97 Remove redundant distinctUntilChanged (#2804)
Because this.scope.state() does this for us
2024-11-20 10:31:36 +00:00
Robin
770730ba6c Don't fall back as eagerly to unselected devices
Somewhere around version 131 or 132, Firefox has started being more paranoid about media device fingerprinting, and will not even give you the IDs of available devices until you've requested a media stream. Instead you only get a single audio input and video input each with the empty string as their device ID, representing the system's default device. We can recognize this case and avoid resetting the device selection.
2024-11-19 13:26:40 -05:00
Will Hunt
b3ceb5300c Add keyboard shortcuts for raised hand / reactions (#2784)
* Add support for reactions / raised-hands via keyboard shortcuts.

* Add tests

* Fixup shortcuts

* update snapshotr

* fix type

* keyshortcuts

* remove mistakenly commited file

* fix label logic

* Add renderer for call joined / left

* Use caption

* lint

* remove unexpected file

* remove other unexpected change

* Remove other other unexpected change.
2024-11-19 16:57:57 +00:00
ElementRobot
ffbc48fe86 Merge pull request #2801 from element-hq/actions/localazy-download
Localazy Download
2024-11-19 16:00:11 +00:00
fkwp
4655da3c35 Translations updates 2024-11-19 15:58:53 +00:00
Robin
585998cb87 Merge pull request #2800 from robintown/reactions-button
Update icon and label of reactions button
2024-11-19 10:44:58 -05:00
Robin
8ec2f9bb31 Update tests 2024-11-19 10:43:42 -05:00
Robin
2ee468ba44 Update icon and label of reactions button
They've been updated in the designs.
2024-11-19 09:56:46 -05:00
fkwp
17eb435a7a Merge pull request #2799 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.6.2
2024-11-19 15:55:19 +01:00
renovate[bot]
1678ca71c1 Update dependency livekit-client to v2.6.2 2024-11-19 14:53:23 +00:00
Robin
90fe8e0529 Merge pull request #2734 from element-hq/renovate/compound
Update Compound
2024-11-19 09:48:17 -05:00
Hugh Nimmo-Smith
64749d0b7a Expose TestScheduler as global (#2796) 2024-11-18 22:39:59 +00:00
fkwp
79cd3047e9 Merge pull request #2798 from element-hq/renovate/livekit-components
Update dependency @livekit/components-react to v2.6.8
2024-11-18 20:40:30 +01:00
renovate[bot]
9078c35e06 Update dependency @livekit/components-react to v2.6.8 2024-11-18 19:39:01 +00:00
renovate[bot]
2833d9a816 Update Compound 2024-11-18 19:37:15 +00:00
fkwp
8598be1d92 Merge pull request #2797 from element-hq/renovate/livekit-client
Update dependency livekit-client to v2.6.1
2024-11-18 20:36:18 +01:00
renovate[bot]
02d2de3831 Update dependency livekit-client to v2.6.1 2024-11-18 19:34:22 +00:00
fkwp
6d1aa0087b Merge pull request #2729 from element-hq/renovate/migrate-config
Migrate renovate config
2024-11-18 13:17:07 +01:00
renovate[bot]
8b4b9f4494 Update all non-major dependencies (#2795)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-18 10:09:21 +01:00
Timo
a551cde47b Make reactions background use the frosted glass look (#2792)
* Make reactions background use the frosted glass look

* fix spacing if there is raise hand + reaction.
2024-11-15 18:58:40 +01:00
ElementRobot
01b9d7a70e Merge pull request #2793 from element-hq/actions/localazy-download
Localazy Download
2024-11-15 16:23:56 +00:00
fkwp
f56d4a32a3 Translations updates 2024-11-15 16:22:27 +00:00
Will Hunt
eed1b98cf9 Update reactions to new design (#2751)
* Replace search strings

* Add expander for reactions view

* lint

* Remove useless list

* Update tests

* lint

* Only shrink buttons on web version, mobile never shrinks

* Revert accidental change.

* Remove border from button

* Tidy up views.

* Finish matching designs.

* Fix height

* Remove a unneeded class

* Remove more cruft

* Remove unnessacery chunk

* Evenly space reactions

* lint

* Disable reaction buttons when busy

* Try to make menu a bit more responsive

* Update test

* further screen size tweaks
2024-11-15 16:02:06 +00:00
Will Hunt
c1208ac7b6 Small improvements to settings tab (#2789)
* align profile tab.

* Fix descriptions
2024-11-15 14:09:52 +00:00
Quentin Gliech
d77e9e8f08 Merge pull request #2790 from element-hq/quenting/preload-config
Pre-fetch the config.json to improve startup time
2024-11-15 13:55:41 +01:00
Quentin Gliech
2e172aa3be Pre-fetch the config.json to improve startup time 2024-11-15 13:36:36 +01:00
fkwp
9650ca9687 Merge pull request #2787 from element-hq/quenting/docker-vary-encoding
Send 'Vary: Content-Encoding' header from nginx
2024-11-15 09:22:25 +01:00
Quentin Gliech
f7e4b79502 Send 'Vary: Content-Encoding' header from nginx 2024-11-15 09:19:45 +01:00
fkwp
20840d901e Merge pull request #2786 from element-hq/quenting/docker-cache-headers
Precompress assets and set the right cache headers
2024-11-15 08:52:12 +01:00
Quentin Gliech
4c1c818ba9 Merge pull request #2776 from element-hq/quenting/locales-as-assets
Handle locales as Vite assets
2024-11-15 08:41:56 +01:00
Quentin Gliech
f022eb09a2 Precompress assets and set the right cache headers 2024-11-15 00:59:26 +01:00
Hugh Nimmo-Smith
50934a53cd Lazy load matrix-js-sdk when running as SPA (#2785) 2024-11-14 21:54:02 +00:00
Quentin Gliech
99d5886e32 Handles locales as Vite assets 2024-11-14 19:12:11 +01:00
Quentin Gliech
137a53dbee Load the Intl.Segmenter and Intl.DurationFormat polyfills only if needed (#2778)
* Load the Intl.Segmenter polyfill only if needed

* Also polyfill Intl.DurationFormat only if needed

* Polyfill Intl.* in tests

* Load the default translations in tests

* Instanciate the Intl.DurationFormat in the component
2024-11-14 18:06:38 +00:00
Hugh Nimmo-Smith
6e5c468780 Use more explicit names and types for LayoutMedia observables (#2781) 2024-11-14 14:23:50 +01:00
Quentin Gliech
1478dbe6a1 Sync the Vaul version with the one used by Compound (#2783) 2024-11-14 13:11:17 +00:00
Quentin Gliech
85d8e036d5 Lazy-load pako when submitting rageshake (#2782) 2024-11-14 13:00:01 +00:00
ElementRobot
84e172a2ba Merge pull request #2779 from element-hq/actions/localazy-download
Localazy Download
2024-11-14 11:42:36 +00:00
fkwp
7fddad02e0 Translations updates 2024-11-14 11:40:09 +00:00
Quentin Gliech
3b3f7762a7 Use optimized font from fontsource (#2775) 2024-11-14 11:23:09 +00:00
Quentin Gliech
2297675b06 Replace lodash with lodash-es (#2777) 2024-11-14 11:18:43 +00:00
Quentin Gliech
8f4b932c3c Enable Codecov bundle analysis plugin (#2774) 2024-11-14 10:07:21 +00:00
Robin
88782a0332 Merge pull request #2772 from robintown/local-mute-icon
Show a different icon for participants that you've muted
2024-11-13 13:34:39 -05:00
Robin
9eae1f4145 Show a different icon for participants that you've muted
As a non-intrusive way to help you remember when you've locally muted a participant (so you're less likely to be confused about not hearing their audio), we can show a different icon on the tile.
2024-11-13 11:10:26 -05:00
Will Hunt
3d096426be Quieten rock sound effect. (#2768) 2024-11-12 15:59:58 +00:00
Will Hunt
83fa9661cf Init client with a memory store (for MSC4222) (#2764)
* Bump matrix-js-sdk for MSC4222 support

* Init client with a memory store.

---------

Co-authored-by: Robin <robin@robin.town>
2024-11-12 12:27:49 +00:00
Robin
6c24763196 Merge pull request #2759 from robintown/msc4222
Bump matrix-js-sdk for MSC4222 support
2024-11-12 07:22:49 -05:00
Will Hunt
c4c266536b Sound effect volume adjustment & tooltip (#2762)
* Set the default sound effect volume to 50%.

* Add a tooltip to describe the current volume level.

* lint import
2024-11-12 10:18:45 +00:00
ElementRobot
3535cbe2e6 Merge pull request #2763 from element-hq/actions/localazy-download
Localazy Download
2024-11-12 09:29:50 +00:00
fkwp
dac89b97ae Translations updates 2024-11-12 09:28:30 +00:00
Robin
854e0ab7ae Decrypt potential reaction events before checking their type (#2761)
By rights, this fix I had made to decrypt reaction events shouldn't have appeared successful, because I was requiring the event to have a certain type before asking matrix-js-sdk to decrypt it, and you can't know an event's type before it's decrypted. Probably what was happening is that another code path was requesting the events to be decrypted so that this mistake didn't matter.
2024-11-12 10:05:01 +01:00
Robin
20976e1ee3 Bump matrix-js-sdk for MSC4222 support 2024-11-11 18:01:28 -05:00
Andrew Ferrazzutti
f12e6601fe Refactor if expression (#2758)
Split the check on a boolean into another branch
2024-11-11 12:51:31 -05:00
Robin
4b2d8403d7 Merge pull request #2748 from element-hq/renovate/all-minor-patch
Update all non-major dependencies
2024-11-11 12:37:41 -05:00
renovate[bot]
03f0fffa57 Update all non-major dependencies 2024-11-11 17:33:23 +00:00
Andrew Ferrazzutti
6486ffe777 Explicitly bump matrix-widget-api (#2757)
Was already present in yarn.lock
2024-11-11 12:32:34 -05:00
Timo
3dad62f9e3 Skip lobby when coming from waitForInvite state. (#2753)
* Skip lobby if when coming from waitForInvite state.

* knock reject wording update (shorter/simpler)

* Automatically enter session also in non widget mode when skipLobby = true

* Update public/locales/en-GB/app.json

Co-authored-by: Robin <robin@robin.town>

* review

* review andrew

---------

Co-authored-by: Robin <robin@robin.town>
2024-11-11 18:30:15 +01:00
Robin
8465bb4c13 Switch back to a normal Compound Web release (#2755)
https://github.com/element-hq/compound-web/pull/272 got merged and released.
2024-11-11 16:56:13 +00:00
Hugh Nimmo-Smith
8be6655d8b Add matrix_rtc_session config options + bump js-sdk (#2756)
* Add matrix_rtc_session config options
* Bump js-sdk

6971e7beba...fcb69b16ad

Also brings in:

- https://github.com/matrix-org/matrix-js-sdk/pull/4342
- https://github.com/matrix-org/matrix-js-sdk/pull/4494
2024-11-11 16:53:37 +00:00
Robin
464cb16409 Merge pull request #2754 from robintown/footer-fix
Fix footer not adapting to narrow windows
2024-11-11 11:11:23 -05:00
Robin
a045cc042b Fix footer not adapting to narrow windows
This CSS block was added last week but seems to have become lost along the way in a merge.
2024-11-11 11:04:49 -05:00
Robin
29469501db Merge pull request #2749 from element-hq/hs/css-fixes-for-reactions
Small improvements for reaction rendering
2024-11-11 09:19:51 -05:00
Robin
a6efdf004f Merge pull request #2752 from robintown/one-on-one-crash
Make one-on-one layout less prone to crashing
2024-11-11 09:06:05 -05:00
Robin
50d380cf37 Make one-on-one layout less prone to crashing
The basic issue here, I think, was that the 'oneOnOne' observable flag and the 'onOnOneLayout' observable could become out of sync, as RxJS does *not* have atomicity guarantees. We can work around this by combining them into one observable.
2024-11-11 08:25:16 -05:00
Will Hunt
6830744096 Don't adjust reaction time.
That was just for testing
2024-11-11 12:53:39 +00:00
Will Hunt
4f9333ca0c lint 2024-11-11 12:11:53 +00:00
Will Hunt
699b69f019 Move reactions to own component. 2024-11-11 12:07:02 +00:00
Will Hunt
67e5abcf31 shrink the reaction buttons on low screen widths 2024-11-11 11:29:59 +00:00
Robin
b22d2dba5f Merge pull request #2747 from robintown/decrypt-reactions
Decrypt reaction events
2024-11-10 13:15:21 -05:00
Robin
97aeb18a24 Decrypt reaction events 2024-11-10 11:20:04 -05:00
Robin
e79cae820f Merge pull request #2744 from robintown/element-call-nov-preview
Bump matrix-js-sdk and matrix-widget-api
2024-11-09 08:31:35 -05:00
Robin
2bf08c8fb3 Merge pull request #2743 from robintown/mobile-tooltips
Use temporary Compound Web release for mobile tooltip improvements
2024-11-09 08:31:31 -05:00
Robin
ca63035dc1 Bump matrix-js-sdk and matrix-widget-api
This bumps matrix-js-sdk to a preview branch that includes https://github.com/matrix-org/matrix-js-sdk/pull/4498 and https://github.com/matrix-org/matrix-js-sdk/pull/4494, and matrix-widget-api to 1.10.0.
2024-11-09 08:11:06 -05:00
Robin
942e07f103 Use temporary Compound Web release for mobile tooltip improvements
I put up a temporary build of https://github.com/element-hq/compound-web/pull/272 for us to use.
2024-11-08 16:39:29 -05:00
ElementRobot
18daf446c8 Merge pull request #2742 from element-hq/actions/localazy-download
Localazy Download
2024-11-08 20:59:37 +00:00
fkwp
8771a06986 Translations updates 2024-11-08 20:58:21 +00:00
ElementRobot
b3da45612e Merge pull request #2741 from element-hq/actions/localazy-download
Localazy Download
2024-11-08 20:29:32 +00:00
fkwp
2d262d27dd Translations updates 2024-11-08 20:28:17 +00:00
Robin
022367ec2e Merge pull request #2737 from robintown/footer-hide-show
Improve interactions to hide/show the footer
2024-11-08 14:31:17 -05:00
Robin
56e736b0ee Merge pull request #2732 from element-hq/hs/add-volume-effect-level
Add sound effect volume slider
2024-11-08 13:19:58 -05:00
Robin
3e1e08c883 Fix type error 2024-11-08 13:18:36 -05:00
Half-Shot
6645a6e5a2 sort 2024-11-08 13:09:28 -05:00
Half-Shot
a6683b230c Ensure hand raised uses the same volume 2024-11-08 13:09:28 -05:00
Half-Shot
06a02b4dd8 Add test 2024-11-08 13:09:28 -05:00
Half-Shot
c560b58811 lint 2024-11-08 13:05:05 -05:00
Half-Shot
7b57fc2942 Add ability to adjust sound effect volume. 2024-11-08 13:05:05 -05:00
Robin
68d71a8329 Improve interactions to hide/show the footer
This fixes a few different usability issues with the footer:

- When tapping one of the footer buttons, the footer would be dismissed rather than activating the button.
- When the footer was hidden, you could still tap the buttons.
- Interacting with controls in the footer would not reset the timer that hides it, leading to a feeling that the footer can disappear out from under you.
2024-11-08 12:52:55 -05:00
Robin
1df2e0c48f Merge pull request #2738 from robintown/narrow-footer
Make the footer display more nicely on narrow screens
2024-11-08 12:46:29 -05:00
Robin
f1233cad20 Merge branch 'livekit' into narrow-footer 2024-11-08 12:45:09 -05:00
Will Hunt
5d88c52e30 Support for generic reactions (#2708)
* Initial support for Hand Raise feature

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Refactored to use reaction and redaction events

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Replacing button svg with raised hand emoji

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* SpotlightTile should not duplicate the raised hand

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Update src/room/useRaisedHands.tsx

Element Call recently changed to AGPL-3.0

* Use relations to load existing reactions when joining the call

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Links to sha commit of matrix-js-sdk that exposes the call membership event id and refactors some async code

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Removing RaiseHand.svg

* Check for reaction & redaction capabilities in widget mode

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Fix failing GridTile test

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Center align hand raise.

* Add support for displaying the duration of a raised hand.

* Add a sound for when a hand is raised.

* Refactor raised hand indicator and add tests.

* lint

* Refactor into own files.

* Redact the right thing.

* Tidy up useEffect

* Lint tests

* Remove extra layer

* Add better sound. (woosh)

* Add a small mode for spotlight

* Fix timestamp calculation on relaod.

* Fix call border resizing video

* lint

* Fix and update tests

* Allow timer to be configurable.

* Add preferences tab for choosing to enable timer.

* Drop border from raised hand icon

* Handle cases when a new member event happens.

* Prevent infinite loop

* Major refactor to support various state problems.

* Tidy up and finish test rewrites

* Add some explanation comments.

* Even more comments.

* Use proper duration formatter

* Remove rerender

* Fix redactions not working because they pick up events in transit.

* More tidying

* Use deferred value

* linting

* Add tests for cases where we got a reaction from someone else.

* Be even less brittle.

* Transpose border to GridTile.

* First PoC for reactions

* hide menu by default

* Add lightbulb.

* Add reaction indicator.

* Add sounds.

* Tidy up + add support for floating emoji.

* Linting and general stability improvements.

* Subscribe to the ecall reaction event type.

* fix import

* Center emoji picker

* Overflow buttons when screen is too narrow

* lint

* Add settings for disabling animations / sounds.

* Make vertical divider more visually distinct.

* Make event listener more resillient.

* lint

* Fix some tests.

* Remove old raised hand component

* Add new icon

* Update text

* Update compound hand raised icon.

* Add deer.

* Fix case where you could send larger strings as emoji

* Const the active time.

* Document time in css.

* Add rock emoji

* Add licence file.

* Add type def for custom reaction type.

* better reaction description

* Factor out reactions test structure to utils file.

* Add tests for ReactionToggleButton

* Add keyboard shortcuts for reaction sending.

* type tidyups

* lint

* Add tests for ReactionAudioRenderer

* lint

* prettier

* i18n sort

* final lint?

* Preload reaction sounds to prevent delays.

* Update rock sounds

* add onclick back

* Fix test

* lint

* simplify

* Tweak line height

* modal impl

* Modal refactor attempts.

* Remove closed menu test since we're using Modal.

* Swap icon, make mobile view better.

* Fix mobile view for emoji picker.

* Use Intl.Segmenter

* Clear timeouts on component close.

* Remove useless useCallback

* Use prefers-reduced-motion

* Add toggle for raise hand.

* Add lower hand text

* Add lower motion mode.

* Decomplicate className system for Modal

* Add error for failured to send reaction.

* i18n

* Spacing for emoji buttons search

* Remove unrequired media query

* Fix generic sound not playing.

* Clear reactions if we're clearing timeouts.

* Fix tests

* Relabel lower hand

* More translations

* Add comments on reaction interface

* Move polyfill.

* lint

* Replace deer sound

* Another attempt to fix the sizing of the reactions

* cleanup

* fix button

* fix

---------

Signed-off-by: Milton Moura <miltonmoura@gmail.com>
Co-authored-by: Milton Moura <miltonmoura@gmail.com>
Co-authored-by: fkwp <fkwp@users.noreply.github.com>
2024-11-08 17:36:40 +00:00
Robin
c7e220e310 Make the footer display more nicely on narrow screens
It needed a bit of tweaking now that we have up to 6 buttons in the footer. I tried to do everything in CSS this time.
2024-11-08 12:16:59 -05:00
Robin
5b94dd6f1a Merge pull request #2736 from robintown/disable-encryption-status
Disable the encryption status indicators
2024-11-08 09:35:15 -05:00
Robin
0ffb4cc23d Disable the encryption status indicators
Currently they're a bit broken and we don't have the time to fix them.
2024-11-08 09:34:02 -05:00
fkwp
f4096a6d43 Merge pull request #2733 from element-hq/fkwp/fix_nginx_conf
fix nginx config
2024-11-07 23:12:01 +01:00
fkwp
c9676f2466 fix nginx config 2024-11-07 23:01:50 +01:00
fkwp
640ba8b79f Merge pull request #2719 from element-hq/fkwp/docker_compose_non_hostnetwork
docker compose non hostnetwork setup
2024-11-07 21:45:36 +01:00
fkwp
34abca0c0b Update dev-backend-docker-compose.yml
Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
2024-11-07 19:16:55 +01:00
fkwp
bea9a24b14 Update dev-backend-docker-compose.yml
Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
2024-11-07 19:16:48 +01:00
fkwp
fd383328e2 Update dev-backend-docker-compose.yml
Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
2024-11-07 19:16:40 +01:00
Will Hunt
938beccb6e Add tests for Modal (#2731)
* Add Modal tests.

* fix type

* apply review feedback

* lint

* remove act
2024-11-07 17:06:49 +00:00
Timo
9bf40eda25 Prohibit .preview to be 0 width (#2730) 2024-11-07 13:15:12 +01:00
fkwp
05eb2a06f4 prettier 2024-11-06 21:18:24 +01:00
fkwp
2961cfa52c update README.md 2024-11-06 20:20:29 +01:00
fkwp
65742db4f2 use less common port for JWT service 2024-11-06 20:07:52 +01:00
fkwp
430337e725 update dev env setup 2024-11-06 20:00:21 +01:00
fkwp
4a71283826 update docker-compose cmd line 2024-11-06 20:00:21 +01:00
fkwp
7440f39fef add base_url 2024-11-06 20:00:21 +01:00
fkwp
69776ba08e add .well-known section including a note that this is not effective for the local dev environment 2024-11-06 20:00:21 +01:00
fkwp
bf4596dfc5 add dedicated config for local development environment 2024-11-06 20:00:21 +01:00
fkwp
4877474b7d remove livekit.livekit_service_url from sample config since SFU foci should be announced by homeserver's well-known 2024-11-06 20:00:21 +01:00
fkwp
4705ab4218 Update dev-backend-docker-compose.yml
Co-authored-by: Andrew Ferrazzutti <andrewf@element.io>
2024-11-06 19:46:59 +01:00
renovate[bot]
e37f36937e Migrate config renovate.json 2024-11-06 18:46:12 +00:00
Timo
bbdb48a7d2 bump js sdk (#2728) 2024-11-06 19:01:14 +01:00
Hugh Nimmo-Smith
bfffddfa92 Fix minature => miniature spelling (#2727) 2024-11-06 15:54:58 +00:00
Timo
a041a7bf7e Bump js-sdk (local echo fix) (#2723) 2024-11-06 16:35:29 +01:00
Hugh Nimmo-Smith
f611554c31 Don't hide video on encryption status error (#2726) 2024-11-06 15:31:31 +00:00
ElementRobot
137c2fad0b Merge pull request #2725 from element-hq/actions/localazy-download
Localazy Download
2024-11-06 15:24:48 +00:00
fkwp
0954188097 Translations updates 2024-11-06 15:23:38 +00:00
Hugh Nimmo-Smith
7fd344385d Add rxjs/recommend eslint rules (#2724)
We will probably want to tweak these as we get more used to them.
2024-11-06 14:33:06 +00:00
Hugh Nimmo-Smith
c45f724279 Show encryption key status from LiveKit (#2700)
* Refactor to make encryption system available in view models

* WIP show encryption errors from LiveKit

* Missing CSS

* Show encryption status based on LK and RTC

* Lint

* Lint

* Fix tests

* Update wording

* Refactor

* Lint
2024-11-06 11:12:46 +00:00
Will Hunt
bc0ab92394 Add feature to release hand raised when the tile indicator is clicked. (#2721)
* Refactor to add support for lowering hand on indicator click.

* Cleanup and lint.

* fix icon being a little off
2024-11-06 11:00:19 +00:00
fkwp
d1774d63ab make dev-backend-docker-compose.yaml work wiht podman compose 2024-11-06 10:55:13 +01:00
Robin
110914a4d6 Replace some custom React hooks with observable-hooks (#2710)
The observable-hooks package provides hooks that do exactly the same thing as these custom React hooks I had written a while back. (even the names are the same, wow)

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2024-11-06 09:43:27 +00:00
Robin
d3f069e763 Keep tiles in a stable order (#2670)
* Keep tiles in a stable order

This introduces a new layer of abstraction on top of MediaViewModel: TileViewModel, which gives us a place to store data relating to tiles rather than their media, and also generally makes it easier to reason about tiles as they move about the call layout. I have created a class called TileStore to keep track of these tiles.

This allows us to swap out the media shown on a tile as the spotlight speaker changes, and avoid moving tiles around unless they really need to jump between the visible/invisible regions of the layout.

* Don't throttle spotlight updates

Since we now assume that the spotlight and grid will be in sync (i.e. an active speaker in one will behave as an active speaker in the other), we don't want the spotlight to ever lag behind due to throttling. If this causes usability issues we should maybe look into making LiveKit's 'speaking' indicators less erratic first.

* Make layout shifts due to a change in speaker less surprising

Although we try now to avoid layout shifts due to the spotlight speaker changing wherever possible, a spotlight speaker coming from off screen can still trigger one. Let's shift the layout a bit more gracefully in this case.

* Improve the tile ordering tests

* Maximize the spotlight tile in portrait layout

* Tell tiles whether they're actually visible in a more timely manner

* Fix test

* Fix speaking indicators logic

* Improve readability of marbles

* Fix test case

---------

Co-authored-by: Hugh Nimmo-Smith <hughns@element.io>
2024-11-06 09:36:48 +00:00
ElementRobot
22cca2874a Merge pull request #2722 from element-hq/actions/localazy-download
Localazy Download
2024-11-05 22:58:33 +00:00
fkwp
a9b15c1ec2 Translations updates 2024-11-05 22:51:22 +00:00
fkwp
88a8277694 Merge pull request #2716 from element-hq/fkwp/enable_feature_use_device_session_member_events
default to flat structre of m.call.member evenst (one event per sessi…
2024-11-05 10:51:38 +01:00
renovate[bot]
b7d7180335 Update all non-major dependencies (#2713)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-05 10:42:02 +01:00
fkwp
c33c703570 adapt config.sample.json to development environment settings 2024-11-05 00:36:18 +01:00
fkwp
82c6db1f94 linting 2024-11-05 00:35:40 +01:00
fkwp
44cb16d0b8 prefix docker-compose with dev to make clear its only for development purposes. In addition added minimum synapse config to it in order to have a fully selfcontained dev setup 2024-11-05 00:25:41 +01:00
fkwp
a672224324 rename livekit.conf to dev_livekit.conf to make clear that its for the development environment 2024-11-05 00:23:02 +01:00
fkwp
c5bd68f7db update gitignore to irgnore temp synapse state 2024-11-05 00:18:33 +01:00
fkwp
2de105c9fd minimum homeserver configuration for development environment 2024-11-05 00:15:26 +01:00
fkwp
275e0bdb00 minimum nginx tls reverse proxy configuration for synapse homeserver 2024-11-05 00:14:02 +01:00
fkwp
377ccf8f45 add localhost tls certificates for dev environment 2024-11-05 00:05:02 +01:00
Robin
98c199d1cf Merge pull request #2690 from robintown/spotlight-speaking
Show speaking indicators in spotlight during screen sharing
2024-11-04 12:36:58 -05:00
Robin
b903e11cfc Fix lint error 2024-11-04 10:56:29 -05:00
fkwp
e95106a431 fix linting 2024-11-04 15:13:32 +01:00
fkwp
16129d8154 fix test to reflect new m.call.member format 2024-11-04 14:35:12 +01:00
fkwp
895c52ed06 default to flat structre of m.call.member evenst (one event per session rather than an array) 2024-11-04 14:24:13 +01:00
Milton Moura
1897210a60 Hand raise feature (#2542)
* Initial support for Hand Raise feature

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Refactored to use reaction and redaction events

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Replacing button svg with raised hand emoji

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* SpotlightTile should not duplicate the raised hand

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Update src/room/useRaisedHands.tsx

Element Call recently changed to AGPL-3.0

* Use relations to load existing reactions when joining the call

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Links to sha commit of matrix-js-sdk that exposes the call membership event id and refactors some async code

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Removing RaiseHand.svg

* Check for reaction & redaction capabilities in widget mode

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Fix failing GridTile test

Signed-off-by: Milton Moura <miltonmoura@gmail.com>

* Center align hand raise.

* Add support for displaying the duration of a raised hand.

* Add a sound for when a hand is raised.

* Refactor raised hand indicator and add tests.

* lint

* Refactor into own files.

* Redact the right thing.

* Tidy up useEffect

* Lint tests

* Remove extra layer

* Add better sound. (woosh)

* Add a small mode for spotlight

* Fix timestamp calculation on relaod.

* Fix call border resizing video

* lint

* Fix and update tests

* Allow timer to be configurable.

* Add preferences tab for choosing to enable timer.

* Drop border from raised hand icon

* Handle cases when a new member event happens.

* Prevent infinite loop

* Major refactor to support various state problems.

* Tidy up and finish test rewrites

* Add some explanation comments.

* Even more comments.

* Use proper duration formatter

* Remove rerender

* Fix redactions not working because they pick up events in transit.

* More tidying

* Use deferred value

* linting

* Add tests for cases where we got a reaction from someone else.

* Be even less brittle.

* Transpose border to GridTile.

* lint

---------

Signed-off-by: Milton Moura <miltonmoura@gmail.com>
Co-authored-by: fkwp <fkwp@users.noreply.github.com>
Co-authored-by: Half-Shot <will@half-shot.uk>
Co-authored-by: Will Hunt <github@half-shot.uk>
2024-11-04 09:54:13 +00:00
Hugh Nimmo-Smith
f2ed07c258 Refactor to make encryption system available in view models (#2702) 2024-11-04 09:11:44 +00:00
Robin
42be187182 Explain why speaking indicators are hidden 2024-11-01 11:25:55 -04:00
Robin
3a706ea3e0 Show speaking indicators in spotlight during screen sharing 2024-10-28 14:45:06 -04:00
403 changed files with 19183 additions and 6459 deletions

View File

@@ -1,19 +1,20 @@
const COPYRIGHT_HEADER = `/*
Copyright %%CURRENT_YEAR%% New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
`;
module.exports = {
plugins: ["matrix-org"],
plugins: ["matrix-org", "rxjs"],
extends: [
"plugin:matrix-org/react",
"plugin:matrix-org/a11y",
"plugin:matrix-org/typescript",
"prettier",
"plugin:rxjs/recommended",
],
parserOptions: {
ecmaVersion: "latest",
@@ -36,6 +37,14 @@ module.exports = {
"@typescript-eslint/promise-function-async": "error",
"@typescript-eslint/require-await": "error",
"@typescript-eslint/await-thenable": "error",
// To help ensure that we get proper vite/rollup lazy loading (e.g. for matrix-js-sdk):
"@typescript-eslint/consistent-type-imports": [
"error",
{ fixStyle: "inline-type-imports" },
],
// To encourage good usage of RxJS:
"rxjs/no-exposed-subjects": "error",
"rxjs/finnish": "error",
},
settings: {
react: {

17
.github/workflows/blocked.yaml vendored Normal file
View File

@@ -0,0 +1,17 @@
name: Prevent blocked
on:
pull_request:
types: [opened, labeled, unlabeled]
jobs:
prevent-blocked:
name: Prevent blocked
runs-on: ubuntu-latest
permissions:
pull-requests: read
steps:
- name: Add notice
uses: actions/github-script@v7
if: contains(github.event.pull_request.labels.*.name, 'X-Blocked')
with:
script: |
core.setFailed("PR has been labeled with X-Blocked; it cannot be merged.");

View File

@@ -1,4 +1,4 @@
name: Docker - Deploy
name: Build and publish docker image
on:
workflow_call:
inputs:
@@ -26,11 +26,11 @@ jobs:
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: 📥 Download artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ inputs.artifact_run_id }}
name: build-output
name: build-output-full
path: dist
- name: Log in to container registry
@@ -42,16 +42,16 @@ jobs:
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5.5.1
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804 # v5.7.0
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: ${{ inputs.docker_tags}}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2 # v3.10.0
- name: Build and push Docker image
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6.9.0
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4 # v6.15.0
with:
context: .
platforms: linux/amd64,linux/arm64

View File

@@ -0,0 +1,66 @@
name: Build Element Call
on:
workflow_call:
inputs:
vite_app_version:
required: true
type: string
package:
type: string # This would ideally be a `choice` type, but that isn't supported yet
description: The package type to be built. Must be one of 'full' or 'embedded'
required: true
secrets:
SENTRY_ORG:
required: true
SENTRY_PROJECT:
required: true
SENTRY_URL:
required: true
SENTRY_AUTH_TOKEN:
required: true
CODECOV_TOKEN:
required: false
jobs:
build:
name: Build Element Call
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Yarn cache
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
with:
cache: "yarn"
node-version-file: ".node-version"
- name: Install dependencies
run: "yarn install --frozen-lockfile"
- name: Build full version
if: ${{ inputs.package == 'full' }}
run: "yarn run build:full"
env:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
VITE_APP_VERSION: ${{ inputs.vite_app_version }}
NODE_OPTIONS: "--max-old-space-size=4096"
- name: Build embedded
if: ${{ inputs.package == 'embedded' }}
run: "yarn run build:embedded"
env:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
VITE_APP_VERSION: ${{ inputs.vite_app_version }}
NODE_OPTIONS: "--max-old-space-size=4096"
- name: Upload Artifact
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4
with:
name: build-output-${{ inputs.package }}
path: dist
# We'll only use this in a triggered job, then we're done with it
retention-days: 1

View File

@@ -6,20 +6,72 @@ on:
- opened
- labeled
paths-ignore:
- ".github/**"
- ".github/ISSUE_TEMPLATE/**"
- ".github/CODEOWNERS"
- "docs/**"
push:
branches: [livekit, full-mesh]
paths-ignore:
- ".github/**"
- ".github/ISSUE_TEMPLATE/**"
- ".github/CODEOWNERS"
- "docs/**"
jobs:
build_element_call:
uses: ./.github/workflows/element-call.yaml
build_full_element_call:
# Use the full package vite build
uses: ./.github/workflows/build-element-call.yaml
with:
package: full
vite_app_version: ${{ github.event.release.tag_name || github.sha }}
secrets:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
deploy_develop:
# Deploy livekit branch to call.element.dev after build completes
if: github.ref == 'refs/heads/livekit'
needs: build_full_element_call
runs-on: ubuntu-latest
steps:
- name: Deploy to call.element.dev
uses: actions/github-script@d7906e4ad0b1822421a7e6a35d5ca353c962f410 # v6
with:
github-token: ${{ secrets.DEVELOP_DEPLOYMENT_TOKEN }}
script: |
await github.rest.actions.createWorkflowDispatch({
owner: 'element-hq',
repo: 'element-call-webapp-deployments',
workflow_id: 'deploy.yml',
ref: 'main',
inputs: {
target: 'call.element.dev',
version: '${{ github.sha }}'
}
})
docker_for_develop:
# Build docker and publish docker for livekit branch after build completes
if: github.ref == 'refs/heads/livekit'
needs: build_full_element_call
permissions:
contents: write
packages: write
uses: ./.github/workflows/build-and-publish-docker.yaml
with:
artifact_run_id: ${{ github.run_id }}
docker_tags: |
type=sha,format=short,event=branch
type=raw,value=latest-ci
type=raw,value=latest-ci_{{date 'X' }}
build_embedded_element_call:
# Use the embedded package vite build
uses: ./.github/workflows/build-element-call.yaml
with:
package: embedded
vite_app_version: ${{ github.event.release.tag_name || github.sha }}
secrets:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}

View File

@@ -1,4 +1,4 @@
name: Netlify - Deploy
name: Deploy to Netlify
on:
workflow_call:
inputs:
@@ -46,11 +46,11 @@ jobs:
Exercise caution. Use test accounts.
- name: 📥 Download artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
with:
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
run-id: ${{ inputs.artifact_run_id }}
name: build-output
name: build-output-full
path: webapp
- name: Add redirects file

View File

@@ -1,24 +0,0 @@
name: Run E2E tests
on:
workflow_run:
workflows: ["deploy"]
types:
- completed
branches-ignore:
- "livekit"
jobs:
e2e:
name: E2E tests runs on Element Call
runs-on: ubuntu-latest
steps:
- name: Check out test private repo
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
with:
repository: element-hq/static-call-participant
ref: refs/heads/main
path: static-call-participant
token: ${{ secrets.GH_E2E_TEST_TOKEN }}
- name: Build E2E Image
run: "cd static-call-participant && docker build --no-cache --tag matrixdotorg/chrome-node-static-call-participant:latest ."
- name: Run E2E tests in container
run: "docker run --rm -v '${{ github.workspace }}/static-call-participant/callemshost-users.txt:/opt/app/callemshost-users.txt' matrixdotorg/chrome-node-static-call-participant:latest ./e2e.sh"

View File

@@ -1,47 +0,0 @@
name: Element Call - Build
on:
workflow_call:
inputs:
vite_app_version:
required: true
type: string
secrets:
SENTRY_ORG:
required: true
SENTRY_PROJECT:
required: true
SENTRY_URL:
required: true
SENTRY_AUTH_TOKEN:
required: true
jobs:
build:
name: Build Element Call
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Yarn cache
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
with:
cache: "yarn"
node-version: "lts/*"
- name: Install dependencies
run: "yarn install"
- name: Build
run: "yarn run build"
env:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }}
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
VITE_APP_VERSION: ${{ inputs.vite_app_version }}
NODE_OPTIONS: "--max-old-space-size=4096"
- name: Upload Artifact
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4
with:
name: build-output
path: dist
# We'll only use this in a triggered job, then we're done with it
retention-days: 1

View File

@@ -9,12 +9,12 @@ jobs:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Yarn cache
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
with:
cache: "yarn"
node-version: "lts/*"
node-version-file: ".node-version"
- name: Install dependencies
run: "yarn install"
run: "yarn install --frozen-lockfile"
- name: Prettier
run: "yarn run prettier:check"
- name: i18n

33
.github/workflows/playwright.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: Playwright Tests
on:
pull_request: {}
push:
branches: [livekit, full-mesh]
jobs:
test:
timeout-minutes: 10
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version-file: ".node-version"
- name: Install dependencies
run: yarn install --frozen-lockfile
- name: Install Playwright Browsers
run: yarn playwright install --with-deps
- name: Run backend components
run: |
docker compose -f playwright-backend-docker-compose.yml up -d
docker ps
- name: Copy config file
run: cp config/config.devenv.json public/config.json
- name: Run Playwright tests
run: yarn playwright test
- uses: actions/upload-artifact@v4
if: ${{ !cancelled() }}
with:
name: playwright-report
path: playwright-report/
retention-days: 3

View File

@@ -1,4 +1,4 @@
name: PR Preview Deployments
name: Deploy previews for PRs
on:
workflow_run:
workflows: ["Build"]
@@ -24,7 +24,7 @@ jobs:
needs: prdetails
permissions:
deployments: write
uses: ./.github/workflows/netlify.yaml
uses: ./.github/workflows/deploy-to-netlify.yaml
with:
artifact_run_id: ${{ github.event.workflow_run.id || github.run_id }}
pr_number: ${{ needs.prdetails.outputs.pr_number }}
@@ -42,7 +42,7 @@ jobs:
permissions:
contents: write
packages: write
uses: ./.github/workflows/docker.yaml
uses: ./.github/workflows/build-and-publish-docker.yaml
with:
artifact_run_id: ${{ github.event.workflow_run.id || github.run_id }}
docker_tags: |

View File

@@ -1,13 +1,8 @@
name: Build & publish images to the package registry for tags
name: Build & publish images to the package registry for releases
on:
release:
types: [published]
workflow_run:
workflows: ["Build"]
branches: [livekit]
types:
- completed
env:
REGISTRY: ghcr.io
@@ -16,8 +11,9 @@ env:
jobs:
build_element_call:
if: ${{ github.event_name == 'release' }}
uses: ./.github/workflows/element-call.yaml
uses: ./.github/workflows/build-element-call.yaml
with:
package: full
vite_app_version: ${{ github.event.release.tag_name || github.sha }}
secrets:
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
@@ -39,11 +35,11 @@ jobs:
id: current-time
run: echo "unix_time=$(date +'%s')" >> $GITHUB_OUTPUT
- name: 📥 Download artifact
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4
uses: actions/download-artifact@cc203385981b70ca67e1cc392babf9cc229d5806 # v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
run-id: ${{ github.event.workflow_run.id || github.run_id }}
name: build-output
name: build-output-full
path: dist
- name: Create Tarball
env:
@@ -51,7 +47,7 @@ jobs:
run: |
tar --numeric-owner --transform "s/dist/element-call-${TARBALL_VERSION}/" -cvzf element-call-${TARBALL_VERSION}.tar.gz dist
- name: Upload
uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4.4.3
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
@@ -62,11 +58,9 @@ jobs:
permissions:
contents: write
packages: write
uses: ./.github/workflows/docker.yaml
uses: ./.github/workflows/build-and-publish-docker.yaml
with:
artifact_run_id: ${{ github.event.workflow_run.id || github.run_id }}
docker_tags: |
type=sha,format=short,event=branch
type=semver,pattern=v{{version}}
type=raw,value=latest-ci,enable={{is_default_branch}}
type=raw,value=latest-ci_${{needs.publish_tarball.outputs.unix_time}},enable={{is_default_branch}}

View File

@@ -11,16 +11,16 @@ jobs:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- name: Yarn cache
uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
with:
cache: "yarn"
node-version: "lts/*"
node-version-file: ".node-version"
- name: Install dependencies
run: "yarn install"
run: "yarn install --frozen-lockfile"
- name: Vitest
run: "yarn run test:coverage"
- name: Upload to codecov
uses: codecov/codecov-action@b9fd7d16f6d7d1b5d2bec1a2887e65ceed900238 # v4
uses: codecov/codecov-action@0565863a31f2c772f9f0395002a31e3f06189574 # v5
env:
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
with:

View File

@@ -15,16 +15,16 @@ jobs:
- name: Checkout the code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4
- uses: actions/setup-node@39370e3970a6d050c480ffad4ff0ed4d3fdee5af # v4
- uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4
with:
cache: "yarn"
node-version: "lts/*"
node-version-file: ".node-version"
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Prune i18n
run: "rm -R public/locales"
run: "rm -R locales"
- name: Download translation files
uses: localazy/download@0a79880fb66150601e3b43606fab69c88123c087 # v1.1.0
@@ -32,14 +32,14 @@ jobs:
groups: "-p includeSourceLang:true"
- name: Fix the owner of the downloaded files
run: "sudo chown runner:docker -R public/locales"
run: "sudo chown runner:docker -R locales"
- name: Prettier
run: yarn prettier:format
- name: Create Pull Request
id: cpr
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f # v7.0.5
uses: peter-evans/create-pull-request@dd2324fc52d5d43c699a5636bcf19fceaa70c284 # v7.0.7
with:
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
branch: actions/localazy-download

8
.gitignore vendored
View File

@@ -4,7 +4,15 @@ node_modules
dist
dist-ssr
*.local
*.bkp
.idea/
public/config.json
backend/synapse_tmp/*
/coverage
yarn-error.log
# Playwright
/test-results/
/playwright-report/
/blob-report/
/playwright/.cache/

1
.node-version Normal file
View File

@@ -0,0 +1 @@
22

View File

@@ -1,10 +1,13 @@
FROM alpine AS builder
COPY ./dist /dist
# Compress assets to work with nginx-gzip-static-module
WORKDIR /dist/assets
RUN gzip -k ../index.html *.js *.map *.css *.wasm *-app-*.json
FROM nginxinc/nginx-unprivileged:alpine
COPY ./dist /app
COPY --from=builder ./dist /app
COPY config/nginx.conf /etc/nginx/conf.d/default.conf
USER root
RUN rm -rf /usr/share/nginx/html
USER 101

6
LICENSE-COMMERCIAL Normal file
View File

@@ -0,0 +1,6 @@
Licensees holding a valid commercial license with Element may use this
software in accordance with the terms contained in a written agreement
between you and Element.
To purchase a commercial license please contact our sales team at
licensing@element.io

301
README.md
View File

@@ -2,72 +2,101 @@
[![Chat](https://img.shields.io/matrix/webrtc:matrix.org)](https://matrix.to/#/#webrtc:matrix.org)
[![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement-call%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element-call)
[![License](https://img.shields.io/github/license/element-hq/element-call)](LICENSE-AGPL-3.0)
Group calls with WebRTC that leverage [Matrix](https://matrix.org) and an open-source WebRTC toolkit from [LiveKit](https://livekit.io/).
[🎬 Live Demo 🎬](https://call.element.io)
For prior version of the Element Call that relied solely on full-mesh logic, check [`full-mesh`](https://github.com/element-hq/element-call/tree/full-mesh) branch.
The world's first 🌐 decentralized and 🤝 federated video conferencing solution
powered by **the Matrix protocol**.
![A demo of Element Call with six people](demo.jpg)
## 📌 Overview
To try it out, visit our hosted version at [call.element.io](https://call.element.io). You can also find the latest development version continuously deployed to [call.element.dev](https://call.element.dev/).
**Element Call** is a native Matrix video conferencing application developed by
[Element](https://element.io/), designed for **secure**, **scalable**,
**privacy-respecting**, and **decentralized** video and voice calls over the
Matrix protocol. Built on **MatrixRTC**
([MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143)), it
utilizes
**[MSC4195](https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md)**
with **[LiveKit](https://livekit.io/)** as its backend.
## Host it yourself
![A demo of Element Call with six people](demo.gif)
Until prebuilt tarballs are available, you'll need to build Element Call from source. First, clone and install the package:
You can find the latest development version continuously deployed to
[call.element.dev](https://call.element.dev/).
```
git clone https://github.com/element-hq/element-call.git
cd element-call
yarn
yarn build
```
> [!NOTE]
> For prior version of the Element Call that relied solely on full-mesh logic,
> check [`full-mesh`](https://github.com/element-hq/element-call/tree/full-mesh)
> branch.
If all went well, you can now find the build output under `dist` as a series of static files. These can be hosted using any web server that can be configured with custom routes (see below).
## ✨ Key Features
You may also wish to add a configuration file (Element Call uses the domain it's hosted on as a Homeserver URL by default,
but you can change this in the config file). This goes in `public/config.json` - you can use the sample as a starting point:
**Decentralized & Federated** No central authority; works across Matrix
homeservers.
**End-to-End Encrypted** Secure and private calls.
**Standalone & Widget Mode** Use as an independent app or embed in Matrix
clients.
**WebRTC-based** No additional software required.
**Scalable with LiveKit** Supports large meetings via SFU
([MSC4195: MatrixRTC using LiveKit backend](https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md)).
**Raise Hand** Participants can signal when they want to speak, helping to
organize the flow of the meeting.
**Emoji Reactions** Users can react with emojis 👍️ 🎉 👏 🤘, adding
engagement and interactivity to the conversation.
```
cp config/config.sample.json public/config.json
# edit public/config.json
```
## 🚀 Deployment Options
Because Element Call uses client-side routing, your server must be able to route any requests to non-existing paths back to `/index.html`. For example, in Nginx you can achieve this with the `try_files` directive:
Element Call can be packaged in two ways:
```
server {
...
location / {
...
try_files $uri /$uri /index.html;
}
}
```
**Full Package** Supports both **Standalone** and **Widget** mode. Hosted as
a static web page and accessed via a URL when used as a widget.
By default, the app expects you to have a Matrix homeserver (such as [Synapse](https://element-hq.github.io/synapse/latest/setup/installation.html)) installed locally and running on port 8008. If you wish to use a homeserver on a different URL or one that is hosted on a different server, you can add a config file as above, and include the homeserver URL that you'd like to use.
**Embedded Package** 🚧 **Coming [Soon](https://github.com/element-hq/element-call/issues/2994):** 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.
Element Call requires a homeserver with registration enabled without any 3pid or token requirements, if you want it to be used by unregistered users. Furthermore, it is not recommended to use it with an existing homeserver where user accounts have joined normal rooms, as it may not be able to handle those yet and it may behave unreliably.
### Standalone mode
Therefore, to use a self-hosted homeserver, this is recommended to be a new server where any user account created has not joined any normal rooms anywhere in the Matrix federated network. The homeserver used can be setup to disable 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.
![Element Call in Standalone Mode](./docs/element_call_standalone.drawio.png)
## Configuration
In Standalone mode Element Call operates as an independent, full-featured video
conferencing web application, allowing users to join or host calls without
requiring a separate Matrix client.
There are currently two different config files. `.env` holds variables that are used at build time, while `public/config.json` holds variables that are used at runtime. Documentation and default values for `public/config.json` can be found in [ConfigOptions.ts](src/config/ConfigOptions.ts).
### Widget mode embedded in Messenger Apps
If you're using [Synapse](https://github.com/element-hq/synapse/), you'll need to additionally add the following to `homeserver.yaml` or Element Call won't work:
![Element Call in Widget Mode](./docs/element_call_widget.drawio.png)
```
experimental_features:
msc3266_enabled: true
```
Element Call can be embedded as a widget inside apps like
[**Element Web**](https://github.com/element-hq/element-web) or **Element X
([iOS](https://github.com/element-hq/element-x-ios),
[Android](https://github.com/element-hq/element-x-android))**, bringing
**MatrixRTC** capabilities to messenger apps for seamless decentralized video
and voice calls within Matrix rooms.
MSC3266 allows to request a room summary of rooms you are not joined.
The summary contains the room join rules. We need that to decide if the user gets prompted with the option to knock ("ask to join"), a cannot join error or the join view.
> [!IMPORTANT]
> Embedded packaging is recommended for Element Call in widget mode!
Element Call requires a Livekit SFU behind a Livekit jwt service to work. The url to the Livekit jwt service can either be configured in the config of Element Call (fallback/legacy configuration) or be configured by your homeserver via the `.well-known`.
This is the recommended method.
## 🛠️ Self-Hosting
The configuration is a list of Foci configs:
For operating and deploying Element Call on your own server, refer to the
[**Self-Hosting Guide**](./docs/self-hosting.md).
## 🧭 MatrixRTC Backend Discovery and Selection
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)
### Backend Discovery
MatrixRTC backend (according to
[MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143))
is announced by the homeserver's `.well-known/matrix/client` file and discovered
via the `org.matrix.msc4143.rtc_foci` key, e.g.:
```json
"org.matrix.msc4143.rtc_foci": [
@@ -75,72 +104,149 @@ The configuration is a list of Foci configs:
"type": "livekit",
"livekit_service_url": "https://someurl.com"
},
{
"type": "livekit",
"livekit_service_url": "https://livekit2.com"
},
{
"type": "another_foci",
"props_for_another_foci": "val"
},
]
```
## Translation
where the format for MatrixRTC using LiveKit backend is defined in
[MSC4195](https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md).
In the example above Matrix clients do discover a focus of type `livekit` which
points them to a Matrix LiveKit JWT Auth Service via `livekit_service_url`.
If you'd like to help translate Element Call, head over to [Localazy](https://localazy.com/p/element-call). You're also encouraged to join the [Element Translators](https://matrix.to/#/#translators:element.io) space to discuss and coordinate translation efforts.
### Backend Selection
## Development
- Each call participant proposes their discovered MatrixRTC backend from
`org.matrix.msc4143.rtc_foci` in their `org.matrix.msc3401.call.member` state event.
- For **LiveKit** MatrixRTC backend
([MSC4195](https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md)),
the **first participant who joined the call** defines via the `foci_preferred`
key in their `org.matrix.msc3401.call.member` which actual MatrixRTC backend
will be used for this call.
- During the actual call join flow, the **LiveKit JWT Auth Service** provides
the client with the **LiveKit SFU WebSocket URL** and an **access JWT token**
in order to exchange media via WebRTC.
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)
## 🌍 Translation
If you'd like to help translate Element Call, head over to
[Localazy](https://localazy.com/p/element-call). You're also encouraged to join
the [Element Translators](https://matrix.to/#/#translators:element.io) space to
discuss and coordinate translation efforts.
## 🛠️ Development
### Frontend
Element Call is built against [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk/pull/2553). To get started, clone, install, and link the package:
To get started clone and set up this project:
```
git clone https://github.com/matrix-org/matrix-js-sdk.git
cd matrix-js-sdk
yarn
yarn link
```
Next, we can set up this project:
```
```sh
git clone https://github.com/element-hq/element-call.git
cd element-call
yarn
yarn link matrix-js-sdk
```
To use it, create a local config by, e.g.,
`cp ./config/config.devenv.json ./public/config.json` and adapt it if necessary.
The `config.devenv.json` config should work with the backend development
environment as outlined in the next section out of box.
> [!NOTE]
> Be aware, that this `config.devenv.json` is exposing a deprecated fallback
> LiveKit config key. If the homeserver advertises SFU backend via
> `.well-known/matrix/client` this has precedence.
You're now ready to launch the development server:
```
```sh
yarn dev
```
### Backend
A docker compose file is provided to start a LiveKit server and auth
service for development. These use a test 'secret' published in this
repository, so this must be used only for local development and
**_never be exposed to the public Internet._**
A docker compose file `dev-backend-docker-compose.yml` is provided to start the
whole stack of components which is required for a local development environment:
To use it, add a SFU parameter in your local config `./public/config.json`:
(Be aware, that this is only the fallback Livekit SFU. If the homeserver
advertises one in the client well-known, this will not be used.)
- Minimum Synapse Setup (servername: `synapse.localhost`)
- LiveKit JWT Service (Note requires Federation API and hence a TLS reverse proxy)
- Minimum TLS reverse proxy (servername: `synapse.localhost`) Note certificates
are valid for at least 10 years from now
- Minimum LiveKit SFU Setup using dev defaults for config
- Redis db for completeness
```json
"livekit": {
"livekit_service_url": "http://localhost:7881"
},
```
These use a test 'secret' published in this repository, so this must be used
only for local development and **_never be exposed to the public Internet._**
Run backend components:
```
```sh
yarn backend
# or for podman-compose
# podman-compose -f dev-backend-docker-compose.yml up
```
### Playwright tests
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
<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.
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:
```shell
yarn run test:playwright
```
This will run the Playwright tests once, non-interactively.
There is a more user-friendly way to run the tests in interactive mode:
```shell
yarn run test:playwright:open
```
The easiest way to develop new test is to use the codegen feature of Playwright:
```shell
npx playwright codegen
```
This will record your action and write the test code for you. Use the tool bar to test visibility, text content,
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:
```
Artifact playwright-report has been successfully uploaded! Final size is 1360358 bytes. Artifact ID is 2746265841
Artifact download URL: https://github.com/element-hq/element-call/actions/runs/13837660687/artifacts/2746265841
```
Unzip the report then use this command to open the report in your browser:
```shell
npx playwright show-report ~/Downloads/playwright-report/
```
Under the failed test there is a small icon looking like "3 columns" (next to test name file name),
click on it to see the live screenshots/console output.
### Test Coverage
<img src="https://codecov.io/github/element-hq/element-call/graphs/tree.svg?token=O6CFVKK6I1"></img>
@@ -149,8 +255,11 @@ yarn backend
To add a new translation key you can do these steps:
1. Add the new key entry to the code where the new key is used: `t("some_new_key")`
1. Run `yarn i18n` to extract the new key and update the translation files. This will add a skeleton entry to the `public/locales/en-GB/app.json` file:
1. Add the new key entry to the code where the new key is used:
`t("some_new_key")`
1. Run `yarn i18n` to extract the new key and update the translation files. This
will add a skeleton entry to the `locales/en/app.json` file:
```jsonc
{
...
@@ -158,7 +267,10 @@ To add a new translation key you can do these steps:
...
}
```
1. Update the skeleton entry in the `public/locales/en-GB/app.json` file with the English translation:
1. Update the skeleton entry in the `locales/en/app.json` file with the English
translation:
```jsonc
{
...
@@ -167,8 +279,27 @@ To add a new translation key you can do these steps:
}
```
## Documentation
## 📖 Documentation
Usage and other technical details about the project can be found here:
[**Docs**](./docs/README.md)
## 📝 Copyright & License
Copyright 2021-2025 New Vector Ltd
This software is dual-licensed by New Vector Ltd (Element). It can be used
either:
(1) for free under the terms of the GNU Affero General Public License (as
published by the Free Software Foundation, either version 3 of the License, or
(at your option) any later version); OR
(2) under the terms of a paid-for Element Commercial License agreement between
you and Element (the terms of which may vary depending on what you and Element
have agreed to). Unless required by applicable law or agreed to in writing,
software distributed under the Licenses is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
Licenses for the specific language governing permissions and limitations under
the Licenses.

View File

@@ -1,52 +0,0 @@
version: "3.9"
networks:
lkbackend:
services:
auth-service:
image: ghcr.io/element-hq/lk-jwt-service:latest-ci
hostname: auth-server
# Use host network in case the configured homeserver runs on localhost
network_mode: host
environment:
- LK_JWT_PORT=8881
- LIVEKIT_URL=ws://localhost:7880
- LIVEKIT_KEY=devkey
- LIVEKIT_SECRET=secret
# If the configured homeserver runs on localhost, it'll probably be using
# a self-signed certificate
- LIVEKIT_INSECURE_SKIP_VERIFY_TLS=YES_I_KNOW_WHAT_I_AM_DOING
deploy:
restart_policy:
condition: on-failure
networks:
- lkbackend
livekit:
image: livekit/livekit-server:latest
command: --dev --config /etc/livekit.yaml
restart: unless-stopped
# The SFU seems to work far more reliably when we let it share the host
# network rather than opening specific ports (but why?? we're not missing
# any…)
network_mode: host
# ports:
# - "7880:7880/tcp"
# - "7881:7881/tcp"
# - "7882:7882/tcp"
# - "50100-50200:50100-50200/udp"
volumes:
- ./backend/livekit.yaml:/etc/livekit.yaml
networks:
- lkbackend
redis:
image: redis:6-alpine
command: redis-server /etc/redis.conf
ports:
- 6379:6379
volumes:
- ./backend/redis.conf:/etc/redis.conf
networks:
- lkbackend

View File

@@ -0,0 +1,54 @@
server_name: "synapse.localhost"
public_baseurl: http://synapse.localhost:8008/
pid_file: /data/homeserver.pid
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
resources:
- names: [client, federation, openid]
compress: false
database:
name: sqlite3
args:
database: /data/homeserver.db
media_store_path: /data/media_store
signing_key_path: "/data/SERVERNAME.signing.key"
trusted_key_servers:
- server_name: "matrix.org"
experimental_features:
# MSC3266: Room summary API. Used for knocking over federation
msc3266_enabled: true
# MSC4222 needed for syncv2 state_after. This allow clients to
# correctly track the state of the room.
msc4222_enabled: true
# The maximum allowed duration by which sent events can be delayed, as
# per MSC4140. Must be a positive value if set. Defaults to no
# duration (null), which disallows sending delayed events.
max_event_delay_duration: 24h
# Ratelimiting settings for client actions (registration, login, messaging).
#
# Each ratelimiting configuration is made of two parameters:
# - per_second: number of requests a client can send per second.
# - burst_count: number of requests a client can send before being throttled.
rc_message:
# 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
per_second: 0.5
burst_count: 30
# Required for Element Call in Single Page Mode due to on-the-fly user registration
enable_registration: true
enable_registration_without_verification: true
report_stats: false
serve_server_wellknown: true

View File

@@ -0,0 +1,67 @@
server_name: "synapse.localhost"
public_baseurl: http://synapse.localhost:8008/
pid_file: /data/homeserver.pid
listeners:
- port: 8008
tls: false
type: http
x_forwarded: true
resources:
- names: [client, federation, openid]
compress: false
database:
name: sqlite3
args:
database: /data/homeserver.db
media_store_path: /data/media_store
signing_key_path: "/data/SERVERNAME.signing.key"
trusted_key_servers:
- server_name: "matrix.org"
experimental_features:
# MSC3266: Room summary API. Used for knocking over federation
msc3266_enabled: true
# MSC4222 needed for syncv2 state_after. This allow clients to
# correctly track the state of the room.
msc4222_enabled: true
# The maximum allowed duration by which sent events can be delayed, as
# per MSC4140. Must be a positive value if set. Defaults to no
# duration (null), which disallows sending delayed events.
max_event_delay_duration: 24h
# Ratelimiting settings for client actions (registration, login, messaging).
#
# Each ratelimiting configuration is made of two parameters:
# - per_second: number of requests a client can send per second.
# - burst_count: number of requests a client can send before being throttled.
rc_message:
per_second: 10000
burst_count: 10000
rc_login:
address:
per_second: 10000
burst_count: 10000
account:
per_second: 10000
burst_count: 10000
failed_attempts:
per_second: 10000
burst_count: 10000
rc_registration:
per_second: 10000
burst_count: 10000
# Required for Element Call in Single Page Mode due to on-the-fly user registration
enable_registration: true
enable_registration_without_verification: true
report_stats: false
serve_server_wellknown: true

View File

@@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDtzCCAp+gAwIBAgIUCmJjl3HAeLmrPwRg+/OzikW6peQwDQYJKoZIhvcNAQEL
BQAwazELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9u
ZG9uMQ4wDAYDVQQKDAVBbHJvczEWMBQGA1UECwwNSVQgRGVwYXJ0bWVudDESMBAG
A1UEAwwJbG9jYWxob3N0MB4XDTI0MTEwNDIxNDcwMFoXDTM0MTEwMjIxNDcwMFow
azELMAkGA1UEBhMCR0IxDzANBgNVBAgMBkxvbmRvbjEPMA0GA1UEBwwGTG9uZG9u
MQ4wDAYDVQQKDAVBbHJvczEWMBQGA1UECwwNSVQgRGVwYXJ0bWVudDESMBAGA1UE
AwwJbG9jYWxob3N0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAs368
ExLSudP8luNoY5UfaPqBSVJUPYBi+JGyd36tyN75p5OI7xSfHTttQxuD4KrExBFP
C8mAhE1eoZPBVBOZJ4FYWBJfMaQnCjeqU+laP36td65kSJYbUYlKYH1WpxEpCdgx
wWOKkP/kPX5YXbYqODx9aBJXgoT3yAJW7AniIoL+eLFnS9Xo86TPqCDBTJU9ocwK
gPIDLhDv60724rhZT1kbGp7ECqRovndoDTQjuws2D3yNMfQ+4rrQGPXHGmP5PcaR
0R7uueB+6APyC7MJbuhbxxg/+DFHrRi3lJsgwxuh2hi/+vWw8zgKlgYIwHFA9X0l
cX0UlQdENMH3bgcGIwIDAQABo1MwUTAdBgNVHQ4EFgQUUFGxw7zoiHXGwRqtagjZ
RPYc85cwHwYDVR0jBBgwFoAUUFGxw7zoiHXGwRqtagjZRPYc85cwDwYDVR0TAQH/
BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEALokb1z2lu3qW141b2wm14ilZQKCZ
reNNuUR95Uom96FXPH4QVEH+mYTXXJ5UrfNhQYKQFpdE+5S4HL/UqEOxtWvbAHpK
nsLQ62J8m+0+uwiJGqeQpWr03KJgXDAVE9X3XwMlp/+buxSLhc+GIHWuXW56itV2
jiZJYjhO5SnhhgTWNoVZk93qXuuWEN0yacw7c3Fr1IvFYYYWufbXTk70dbZihPDK
VD141o8tpp6FerSKHNYDqkVFDyTz3DVOhQQJ59zfMre7bFr+PpTTl4vIuGzXEY+E
HPjUSlOzwkCoh5fu7Fs3qG55rJt8akhTEoKpiBTaLucgAjVWNHeci1+Yxg==
-----END CERTIFICATE-----

View File

@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCzfrwTEtK50/yW
42hjlR9o+oFJUlQ9gGL4kbJ3fq3I3vmnk4jvFJ8dO21DG4PgqsTEEU8LyYCETV6h
k8FUE5kngVhYEl8xpCcKN6pT6Vo/fq13rmRIlhtRiUpgfVanESkJ2DHBY4qQ/+Q9
flhdtio4PH1oEleChPfIAlbsCeIigv54sWdL1ejzpM+oIMFMlT2hzAqA8gMuEO/r
TvbiuFlPWRsansQKpGi+d2gNNCO7CzYPfI0x9D7iutAY9ccaY/k9xpHRHu654H7o
A/ILswlu6FvHGD/4MUetGLeUmyDDG6HaGL/69bDzOAqWBgjAcUD1fSVxfRSVB0Q0
wfduBwYjAgMBAAECggEACTqdSExxzJ+LX5ARFaWyOBSWly2GKqSyR14+aInOklhx
9QgkmfOxJrCf3TvJ8RWhXloW0Aqr8qGDxG0Ixgjn7rG7gskXCey1xn8MNppLS0kj
ztaG+NB3AR89ABm8XdoHsSY45geh3/Ni9I0i1VardGQafUJhgNLTZqjwIodzkBtJ
S/bi4uFk1lGNfuvWQvWqzGXUvd1l1YupV6iA4GfhXlUvrSBZwftLBD6xEvQaSqsA
pHvBxTfMXG4RMAkNPDIElkuQ8++CGi1gIRkJfmrv4OgbbitteMnxqqqGYV0zSNCg
R/5FG6umIV7lDLBHZCSCk7wmfmq2UUvzhHThHy4yMQKBgQDu4TwFJCIcVIj7Wj4r
DUBFvz6Lgbltqb+YAMUBtpiDcAQxDJWmedh6dK04ts5CFAFRlRjjuz2uFn7qlVBm
uye9R7tL+tOv5viqDXU78a4snFywoXub6yzpbxrW8B4W1pdIUvQmhwCcDwvO1V24
7Vj2vxcM5I9dsk1aCQSi3VY5yQKBgQDAW/VoTRwhU6OUc6sji5Z5dnkMjkP6NZK9
CSrTWLAMGaLPY+g6fFS7JMNSvfWm/okypD6rcN7p0cxMK3mfFKmMiyPRde0wdrci
sGFjGxM/2d2D7KTMC9iMYwA0K17UIna+UiYPfhR/muIg/dCyjlkKDFs9Z4jk//r1
91bmznt2iwKBgFdiYXhn/Wprqih4nKFXGZnqGdEixVhObl4GegrkZuo+AeqHdf8O
N5ikMfG7PbyCYPEdH5u/FRMn+4mI0X6jHChroyJqQSHp1jEu9yHUiSicknOyvusM
nsNN932FHRyxp2m3nsSxQhHUlzc0ajKJ8K9iu+XlfmSCIzW6cs25Nh+xAoGBAJro
M0wIdPPdsCj3sUVRvx8XqknTM6kGhaIYBNXoYPWNm5BaC4U15OJEq8sxUOdnqcMP
g6x6m/k+S8C3bh0O/a9Bydl/l0BlCfw0gGjYP/s2ju4Tn272xy/e9iYNGzPIgUmp
TB9D0GwmpZ4d6HgyrD+sTbm4bATGpCp6QhBjDggbAoGBAJVMMtZ4pF8D6mLMRZGR
pQjNPy+MH13XYmDRc/BSF8KJ4yKk3tohr9LSXzxR0SEB43NoL1bHkucZrNjGyL8x
jktnwkoIs96kO2mPrl1TqWkXs5RjGkkSTbAJovIcvkRU31SWap/WzN2kHpmRVcQc
KEFKXT5fUYZCLLWxhgZFlGPp
-----END PRIVATE KEY-----

View File

@@ -0,0 +1,40 @@
server {
listen 80;
listen [::]:80;
listen 443 ssl;
listen 8448 ssl;
listen [::]:443 ssl;
listen [::]:8448 ssl;
server_name synapse.localhost;
ssl_certificate /root/ssl/cert.pem;
ssl_certificate_key /root/ssl/key.pem;
# well-known config adding rtc_foci backend
# Note well-known is currently not effective due to:
# https://spec.matrix.org/v1.12/client-server-api/#well-known-uri the spec
# says it must be at https://$server_name/... (implied port 443) Hence, we
# currently rely for local development environment on deprecated config.json
# setting for livekit_service_url
location /.well-known/matrix/client {
return 200 '{"m.homeserver": {"base_url": "http://synapse.localhost:8008"}, "org.matrix.msc4143.rtc_foci": [{"type": "livekit", "livekit_service_url": "http://localhost:8080"}]}';
default_type application/json;
add_header Access-Control-Allow-Origin *;
}
# Reverse proxy for Matrix Synapse Homeserver
# This is also required for development environment.
# Reason: the lk-jwt-service uses the federation API for the openid token
# verification, which requires TLS
location / {
proxy_pass "http://homeserver:8008";
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
error_page 500 502 503 504 /50x.html;
}

15
config/config.devenv.json Normal file
View File

@@ -0,0 +1,15 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "http://synapse.localhost:8008",
"server_name": "synapse.localhost"
}
},
"livekit": {
"livekit_service_url": "http://localhost:8009"
},
"features": {
"feature_use_device_session_member_events": true
},
"eula": "https://static.element.io/legal/online-EULA.pdf"
}

View File

@@ -1,12 +1,12 @@
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://call.ems.host",
"server_name": "call.ems.host"
"base_url": "https://mydomain.com",
"server_name": "mydomain.com"
}
},
"livekit": {
"livekit_service_url": "http://localhost:7881"
"livekit_service_url": "https://livekit-jwt.mydomain.com"
},
"features": {
"feature_use_device_session_member_events": true

View File

@@ -17,5 +17,9 @@
},
"rageshake": {
"submit_url": "https://element.io/bugreports/submit"
},
"sentry": {
"environment": "netlify-pr-preview",
"DSN": "https://b1e328d49be3402ba96101338989fb35@sentry.tools.element.io/41"
}
}

View File

@@ -5,7 +5,7 @@
<Location "/">
# disable cache entriely by default (apart from Etag which is accurate enough)
Header add Cache-Control "private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"
Header add Cache-Control "private, no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0"
CacheDisable on
ExpiresActive off

View File

@@ -3,23 +3,17 @@ server {
server_name localhost;
root /app;
gzip_static on;
gzip_vary on;
location / {
# disable cache entriely by default (apart from Etag which is accurate enough)
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
# also turn off last-modified since they are just the timestamps of the file in the docker image
# and may or may not bear any resemblance to when the resource changed
add_header Last-Modified "";
try_files $uri /$uri /index.html;
try_files $uri $uri/ /index.html;
add_header Cache-Control "public, max-age=30, stale-while-revalidate=30";
}
# assets can be cached because they have hashed filenames
location /assets {
expires 1w;
add_header Cache-Control "public, no-transform";
add_header Cache-Control "public, immutable, max-age=31536000";
}
location /apple-app-site-association {

BIN
demo.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -0,0 +1,86 @@
networks:
ecbackend:
services:
auth-service:
image: ghcr.io/element-hq/lk-jwt-service:latest-ci
hostname: auth-server
environment:
- LK_JWT_PORT=8080
- LIVEKIT_URL=ws://localhost:7880
- LIVEKIT_KEY=devkey
- LIVEKIT_SECRET=secret
# If the configured homeserver runs on localhost, it'll probably be using
# a self-signed certificate
- LIVEKIT_INSECURE_SKIP_VERIFY_TLS=YES_I_KNOW_WHAT_I_AM_DOING
deploy:
restart_policy:
condition: on-failure
ports:
# HOST_PORT:CONTAINER_PORT
- 8009:8080
networks:
- ecbackend
livekit:
image: livekit/livekit-server:latest
command: --dev --config /etc/livekit.yaml
restart: unless-stopped
# The SFU seems to work far more reliably when we let it share the host
# network rather than opening specific ports (but why?? we're not missing
# any…)
ports:
# HOST_PORT:CONTAINER_PORT
- 7880:7880/tcp
- 7881:7881/tcp
- 7882:7882/tcp
- 50100-50200:50100-50200/udp
volumes:
- ./backend/dev_livekit.yaml:/etc/livekit.yaml:Z
networks:
- ecbackend
redis:
image: redis:6-alpine
command: redis-server /etc/redis.conf
ports:
# HOST_PORT:CONTAINER_PORT
- 6379:6379
volumes:
- ./backend/redis.conf:/etc/redis.conf:Z
networks:
- ecbackend
synapse:
hostname: homeserver
image: docker.io/matrixdotorg/synapse:latest
environment:
- SYNAPSE_CONFIG_PATH=/data/cfg/homeserver.yaml
# Needed for rootless podman-compose such that the uid/gid mapping does
# fit local user uid. If the container runs as root (uid 0) it is fine as
# it actually maps to your non-root user on the host (e.g. 1000).
# Otherwise uid mapping will not match your non-root user.
- UID=0
- GID=0
volumes:
- ./backend/synapse_tmp:/data:Z
- ./backend/dev_homeserver.yaml:/data/cfg/homeserver.yaml:Z
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
image: nginx:latest
volumes:
- ./backend/tls_localhost_nginx.conf:/etc/nginx/conf.d/default.conf:Z
- ./backend/tls_localhost_key.pem:/root/ssl/key.pem:Z
- ./backend/tls_localhost_cert.pem:/root/ssl/cert.pem:Z
ports:
# HOST_PORT:CONTAINER_PORT
- "8008:80"
- "4443:443"
depends_on:
- synapse
networks:
- ecbackend

Binary file not shown.

After

Width:  |  Height:  |  Size: 86 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -5,3 +5,4 @@ This folder contains documentation for Element Call setup and usage.
- [Embedded vs standalone mode](./embedded-standalone.md)
- [Url format and parameters](./url-params.md)
- [Global JS controls](./controls.md)
- [Self-Hosting](./self-hosting.md)

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 909 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 868 KiB

View File

@@ -2,7 +2,7 @@
Element call is developed using the js-sdk with matroska mode. This means the app can run either as a standalone app directly connected to a homeserver providing login interfaces or it can be used as a widget.
As a widget the app only uses the core calling (matrixRTC) parts. The rest (authentication, sending events, getting room state updates about calls) is done by the hosting client.
As a widget the app only uses the core calling (MatrixRTC) parts. The rest (authentication, sending events, getting room state updates about calls) is done by the hosting client.
Element Call and the hosting client are connected via the widget api.
Element call detects that it is run as a widget if a widgetId is defined in the url parameters. If `widgetId` is present element call will try to connect to the client via the widget postMessage api using the parameters provided in [Url Format and parameters

166
docs/self-hosting.md Normal file
View File

@@ -0,0 +1,166 @@
# Self-Hosting Element Call
## Prerequisites
> [!IMPORTANT]
> This section covers the requirements for deploying a **Matrix site**
> compatible with MatrixRTC, the foundation of Element Call. These requirements
> apply to both Standalone as well as Widget mode operation of Element Call.
### A Matrix Homeserver
The following [MSCs](https://github.com/matrix-org/matrix-spec-proposals) are
required for Element Call to work properly:
- **[MSC3266](https://github.com/deepbluev7/matrix-doc/blob/room-summaries/proposals/3266-room-summary.md):
Room Summary API**: In Standalone mode Element Call is able to join rooms
over federation using knocking. In this context MSC3266 is required as it
allows to request a room summary of rooms you are not joined. The summary
contains the room join rules. We need that information to decide if the user
gets prompted with the option to knock ("Request to join call"), a "cannot
join error" or "the join view".
- **[MSC4140](https://github.com/matrix-org/matrix-spec-proposals/blob/toger5/expiring-events-keep-alive/proposals/4140-delayed-events-futures.md)
Delayed Events**: Delayed events are required for proper call participation
signalling. If disabled it is very likely that you end up with stuck calls in
Matrix rooms.
- **[MSC4222](https://github.com/matrix-org/matrix-spec-proposals/blob/erikj/sync_v2_state_after/proposals/4222-sync-v2-state-after.md)
Adding `state_after` to sync v2**: Allow clients to opt-in to a change of the
sync v2 API that allows them to correctly track the state of the room. This is
required by Element Call to track room state reliably.
If you're using [Synapse](https://github.com/element-hq/synapse/) as your homeserver, you'll need
to additionally add the following config items to `homeserver.yaml` to comply with Element Call:
```yaml
experimental_features:
# MSC3266: Room summary API. Used for knocking over federation
msc3266_enabled: true
# MSC4222 needed for syncv2 state_after. This allow clients to
# correctly track the state of the room.
msc4222_enabled: true
# The maximum allowed duration by which sent events can be delayed, as
# per MSC4140.
max_event_delay_duration: 24h
rc_message:
# This needs to match at least e2ee key sharing frequency plus a bit of headroom
# Note key sharing events are bursty
per_second: 0.5
burst_count: 30
# 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
```
### MatrixRTC Backend
In order to **guarantee smooth operation** of Element Call MatrixRTC backend is
required for each site deployment.
![MSC4195 compatible setup](MSC4195_setup.drawio.png)
As depicted above, Element Call requires a
[Livekit SFU](https://github.com/livekit/livekit) alongside a
[Matrix Livekit JWT auth service](https://github.com/element-hq/lk-jwt-service)
to implement
[MSC4195: MatrixRTC using LiveKit backend](https://github.com/hughns/matrix-spec-proposals/blob/hughns/matrixrtc-livekit/proposals/4195-matrixrtc-livekit.md).
> [!IMPORTANT]
> As defined in
> [MSC4143](https://github.com/matrix-org/matrix-spec-proposals/pull/4143)
> MatrixRTC backend must be announced to the client via your **homeserver's
> `.well-known/matrix/client`**. The configuration is a list of Foci configs:
```json
"org.matrix.msc4143.rtc_foci": [
{
"type": "livekit",
"livekit_service_url": "https://someurl.com"
},
{
"type": "livekit",
"livekit_service_url": "https://livekit2.com"
},
{
"type": "another_foci",
"props_for_another_foci": "val"
}
]
```
## Building Element Call
> [!NOTE]
> This step is only required if you want to deploy Element Call in Standalone
> mode.
Until prebuilt tarballs are available, you'll need to build Element Call from
source. First, clone and install the package:
```sh
git clone https://github.com/element-hq/element-call.git
cd element-call
yarn
yarn build
```
If all went well, you can now find the build output under `dist` as a series of
static files. These can be hosted using any web server that can be configured
with custom routes (see below).
You also need to add a configuration file which goes in `public/config.json` -
you can use the sample as a starting point:
```sh
cp config/config.sample.json public/config.json
# edit public/config.json
```
The sample needs editing to contain the homeserver that you are using.
Because Element Call uses client-side routing, your server must be able to route
any requests to non-existing paths back to `/index.html`. For example, in Nginx
you can achieve this with the `try_files` directive:
```jsonc
server {
...
location / {
...
try_files $uri /$uri /index.html;
}
}
```
## Configuration
There are currently two different config files. `.env` holds variables that are
used at build time, while `public/config.json` holds variables that are used at
runtime. Documentation and default values for `public/config.json` can be found
in [ConfigOptions.ts](src/config/ConfigOptions.ts).
> [!CAUTION]
> Please note configuring MatrixRTC backend via `config.json` of
> Element Call is only available for developing and debug purposes. Relying on
> it might break Element Call going forward!
## A Note on Standalone Mode of Element Call
Element Call in Standalone mode requires a homeserver with registration enabled
without any 3pid or token requirements, if you want it to be used by
unregistered users. Furthermore, it is not recommended to use it with an
existing homeserver where user accounts have joined normal rooms, as it may not
be able to handle those yet and it may behave unreliably.
Therefore, to use a self-hosted homeserver, this is recommended to be a new
server where any user account created has not joined any normal rooms anywhere
in the Matrix federated network. The homeserver used can be setup to disable
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.

View File

@@ -25,230 +25,50 @@ There are two formats for Element Call urls.
```
With this format the livekit alias that will be used is the `<room_name>`.
All ppl connecting to this url will end up in the same unencrypted room.
All people connecting to this URL will end up in the same unencrypted room.
This does not scale, is super unsecure
(ppl could end up in the same room by accident) and it also is not really
(people could end up in the same room by accident) and it also is not really
possible to support encryption.
The url parameters are spit into two categories: **general** and **widget related**.
## Widget related params
## Parameters
**widgetId**
The id used by the widget. The presence of this parameter implies that element
call will not connect to a homeserver directly and instead tries to establish
postMessage communication via the `parentUrl`.
### Common Parameters
```ts
widgetId: string | null;
```
These parameters are relevant to both widget and standalone modes:
**parentUrl**
The url used to send widget action postMessages. This should be the domain of
the client or the webview the widget is hosted in. (in case the widget is not
in an Iframe but in a dedicated webview we send the postMessages same webview
the widget lives in. Filtering is done in the widget so it ignores the messages
it receives from itself)
| Name | Values | Required for widget | Required for SPA | Description |
| ---------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `allowIceFallback` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Allows use of fallback STUN servers for ICE if the user's homeserver doesnt provide any. |
| `analyticsID` | Posthog analytics ID | No | No | Available only with user's consent for sharing telemetry in Element Web. |
| `appPrompt` | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Prompts the user to launch the native mobile app upon entering a room, applicable only on Android and iOS, and must be enabled in config. |
| `confineToRoom` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Keeps the user confined to the current call/room. |
| `displayName` | | No | No | Display name used for auto-registration. |
| `enableE2EE` (deprecated) | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Legacy flag to enable end-to-end encryption, not used in the `livekit` branch. |
| `fontScale` | A decimal number such as `0.9` | No, defaults to `1.0` | No, defaults to `1.0` | Factor by which to scale the interface's font size. |
| `fonts` | | No | No | Defines the font(s) used by the interface. Multiple font parameters can be specified: `?font=font-one&font=font-two...`. |
| `hideHeader` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Hides the room header when in a call. |
| `hideScreensharing` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Hides the screen-sharing button. |
| `homeserver` | | Not applicable | No | Homeserver for registering a new (guest) user, configures non-default guest user server when creating a spa link. |
| `intent` | `start_call` or `join_existing` | No, defaults to `start_call` | No, defaults to `start_call` | The intent of the user with respect to the call. e.g. if they clicked a Start Call button, this would be `start_call`. If it was a Join Call button, it would be `join_existing`. |
| `lang` | [BCP 47](https://www.rfc-editor.org/info/bcp47) code | No | No | The language the app should use. |
| `password` | | No | No | E2EE password when using a shared secret. (For individual sender keys in embedded mode this is not required.) |
| `perParticipantE2EE` | `true` or `false` | No, defaults to `false` | No, defaults to `false` | Enables per participant encryption with Keys exchanged over encrypted matrix room messages. |
| `roomId` | [Matrix Room ID](https://spec.matrix.org/v1.12/appendices/#room-ids) | Yes | No | Anything about what room we're pointed to should be from useRoomIdentifier which parses the path and resolves alias with respect to the default server name, however roomId is an exception as we need the room ID in embedded widget mode, and not the room alias (or even the via params because we are not trying to join it). This is also not validated, where it is in `useRoomIdentifier()`. |
| `showControls` | `true` or `false` | No, defaults to `true` | No, defaults to `true` | Displays controls like mute, screen-share, invite, and hangup buttons during a call. |
| `skipLobby` (deprecated: use `intent` instead) | `true` or `false` | No. If `intent` is explicitly `start_call` then defaults to `true`. Otherwise defaults to `false` | No, defaults to `false` | Skips the lobby to join a call directly, can be combined with preload in widget. When `true` the audio and video inputs will be muted by default. (This means there currently is no way to start without muted video if one wants to skip the lobby. Also not in widget mode.) |
| `theme` | One of: `light`, `dark`, `light-high-contrast`, `dark-high-contrast` | No, defaults to `dark` | No, defaults to `dark` | UI theme to use. |
| `viaServers` | Comma separated list of [Matrix Server Names](https://spec.matrix.org/v1.12/appendices/#server-name) | Not applicable | No | Homeserver for joining a room, non-empty value required for rooms not on the users default homeserver. |
```ts
parentUrl: string | null;
```
### Widget-only parameters
**userId**
The user's ID (only used in matryoshka mode).
These parameters are only available in widget mode.
```ts
userId: string | null;
```
**deviceId**
The device's ID (only used in matryoshka mode).
```ts
deviceId: string | null;
```
**baseUrl**
The base URL of the homeserver to use for media lookups in matryoshka mode.
```ts
baseUrl: string | null;
```
### General url parameters
**roomId**
Anything about what room we're pointed to should be from useRoomIdentifier which
parses the path and resolves alias with respect to the default server name, however
roomId is an exception as we need the room ID in embedded (matroyska) mode, and not
the room alias (or even the via params because we are not trying to join it). This
is also not validated, where it is in useRoomIdentifier().
```ts
roomId: string | null;
```
**confineToRoom**
Whether the app should keep the user confined to the current call/room.
```ts
confineToRoom: boolean; (default: false)
```
**appPrompt**
Whether upon entering a room, the user should be prompted to launch the
native mobile app. (Affects only Android and iOS.)
The app prompt must also be enabled in the config for this to take effect.
```ts
appPrompt: boolean; (default: true)
```
**preload**
Whether the app should pause before joining the call until it sees an
io.element.join widget action, allowing it to be preloaded.
```ts
preload: boolean; (default: false)
```
**hideHeader**
Whether to hide the room header when in a call.
```ts
hideHeader: boolean; (default: false)
```
**showControls**
Whether to show the buttons to mute, screen-share, invite, hangup are shown
when in a call.
```ts
showControls: boolean; (default: true)
```
**hideScreensharing**
Whether to hide the screen-sharing button.
```ts
hideScreensharing: boolean; (default: false)
```
**enableE2EE** (Deprecated)
Whether to use end-to-end encryption. This is a legacy flag for the full mesh branch.
It is not used on the livekit branch and has no impact there!
```ts
enableE2EE: boolean; (default: true)
```
**perParticipantE2EE**
Whether to use per participant encryption.
Keys will be exchanged over encrypted matrix room messages.
```ts
perParticipantE2EE: boolean; (default: false)
```
**password**
E2EE password when using a shared secret.
(For individual sender keys in embedded mode this is not required.)
```ts
password: string | null;
```
**displayName**
The display name to use for auto-registration.
```ts
displayName: string | null;
```
**lang**
The BCP 47 code of the language the app should use.
```ts
lang: string | null;
```
**fonts**
The font/fonts which the interface should use.
There can be multiple font url parameters: `?font=font-one&font=font-two...`
```ts
font: string;
font: string;
...
```
**fontScale**
The factor by which to scale the interface's font size.
```ts
fontScale: number | null;
```
**analyticsID**
The Posthog analytics ID. It is only available if the user has given consent for
sharing telemetry in element web.
```ts
analyticsID: string | null;
```
**allowIceFallback**
Whether the app is allowed to use fallback STUN servers for ICE in case the
user's homeserver doesn't provide any.
```ts
allowIceFallback: boolean; (default: false)
```
**skipLobby**
Setting this flag skips the lobby and brings you in the call directly.
In the widget this can be combined with preload to pass the device settings
with the join widget action.
```ts
skipLobby: boolean; (default: false)
```
**returnToLobby**
Setting this flag makes element call show the lobby in widget mode after leaving
a call.
This is useful for video rooms.
If set to false, the widget will show a blank page after leaving the call.
```ts
returnToLobby: boolean; (default: false)
```
**theme**
The theme to use for element call.
can be "light", "dark", "light-high-contrast" or "dark-high-contrast".
If not set element call will use the dark theme.
```ts
theme: string | null;
```
**viaServers**
This defines the homeserver that is going to be used when joining a room.
It has to be set to a non default value for links to rooms
that are not on the default homeserver,
that is in use for the current user.
```ts
viaServers: string; (default: undefined)
```
**homeserver**
This defines the homeserver that is going to be used when registering
a new (guest) user.
This can be user to configure a non default guest user server when
creating a spa link.
```ts
homeserver: string; (default: undefined)
```
| Name | Values | Required | Description |
| --------------- | ----------------------------------------------------------------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `baseUrl` | | Yes | The base URL of the homeserver to use for media lookups. |
| `deviceId` | Matrix device ID | Yes | The Matrix device ID for the widget host. |
| `parentUrl` | | Yes | The url used to send widget action postMessages. This should be the domain of the client or the webview the widget is hosted in. (in case the widget is not in an Iframe but in a dedicated webview we send the postMessages same WebView the widget lives in. Filtering is done in the widget so it ignores the messages it receives from itself) |
| `preload` | `true` or `false` | No, defaults to `false` | Pauses app before joining a call until an `io.element.join` widget action is seen, allowing preloading. |
| `returnToLobby` | `true` or `false` | No, defaults to `false` | Displays the lobby in widget mode after leaving a call; shows a blank page if set to `false`. Useful for video rooms. |
| `userId` | [Matrix User Identifier](https://spec.matrix.org/v1.12/appendices/#user-identifiers) | Yes | The Matrix user ID. |
| `widgetId` | [MSC2774](https://github.com/matrix-org/matrix-spec-proposals/pull/2774) format widget ID | Yes | The id used by the widget. The presence of this parameter implies that element call will not connect to a homeserver directly and instead tries to establish postMessage communication via the `parentUrl`. |

View File

@@ -21,8 +21,8 @@ export default {
},
],
},
locales: ["en-GB"],
output: "public/locales/$LOCALE/$NAMESPACE.json",
locales: ["en"],
output: "locales/$LOCALE/$NAMESPACE.json",
input: ["src/**/*.{ts,tsx}"],
sort: true,
};

45
index.html Normal file
View File

@@ -0,0 +1,45 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<% if (packageType === "full") { %>
<link rel="icon" type="image/svg+xml" href="favicon.png" />
<link rel="preload" href="/config.json" as="fetch" />
<% } %>
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
/>
<title><%- brand %></title>
<script>
window.global = window;
</script>
<% if (packageType === "full") { %>
<!-- Open graph meta tags -->
<meta property="og:title" content="<%- brand %>" />
<meta
property="og:description"
content="You're invited to join a call on <%- brand %>"
/>
<meta property="og:type" content="website" />
<meta property="og:image" content="favicon.png" />
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="<%- brand %>" />
<meta
name="twitter:description"
content="You're invited to join a call on <%- brand %>"
/>
<meta name="twitter:image" content="favicon.png" />
<% } %>
</head>
<!-- The default class is: .no-theme {display: none}. It will be overwritten once the app is loaded. -->
<body class="no-theme">
<div id="root"></div>
</body>
</html>

View File

@@ -1,6 +1,9 @@
import { KnipConfig } from "knip";
export default {
vite: {
config: ["vite.config.js", "vite-embedded.config.js"],
},
entry: ["src/main.tsx", "i18next-parser.config.ts"],
ignoreBinaries: [
// This is deprecated, so Knip doesn't actually recognize it as a globally

View File

@@ -7,13 +7,13 @@
"features": ["plural_postfix_us", "filter_untranslated"],
"files": [
{
"pattern": "public/locales/en-GB/*.json",
"pattern": "locales/en/*.json",
"lang": "inherited"
},
{
"group": "existing",
"pattern": "public/locales/*/*.json",
"excludes": ["public/locales/en-GB/*.json"],
"pattern": "locales/*/*.json",
"excludes": ["locales/en/*.json"],
"lang": "${autodetectLang}"
}
]
@@ -22,12 +22,9 @@
"download": {
"files": [
{
"output": "public/locales/${langLsrDash}/${file}"
"output": "locales/${langLsrDash}/${file}"
}
],
"includeSourceLang": "${includeSourceLang|false}",
"langAliases": {
"en": "en_GB"
}
"includeSourceLang": "${includeSourceLang|false}"
}
}

View File

@@ -19,12 +19,9 @@
"common": {
"audio": "Звук",
"avatar": "Аватар",
"camera": "Камера",
"copied": "Копирано!",
"display_name": "Име/псевдоним",
"home": "Начало",
"loading": "Зареждане…",
"microphone": "Микрофон",
"password": "Парола",
"profile": "Профил",
"settings": "Настройки",
@@ -58,18 +55,13 @@
"register_auth_links": "<0>Вече имате акаунт?</0><1><0>Влезте с него</0> или <2>Влезте като гост</2></1>",
"register_confirm_password_label": "Потвърди паролата",
"return_home_button": "Връщане на началния екран",
"room_auth_view_join_button": "Влез в разговора сега",
"screenshare_button_label": "Сподели екрана",
"select_input_unset_button": "Изберете опция",
"settings": {
"developer_tab_title": "Разработчик",
"feedback_tab_h4": "Изпрати обратна връзка",
"feedback_tab_send_logs_label": "Включи debug логове",
"more_tab_title": "Още",
"speaker_device_selection_label": "Говорител"
"feedback_tab_send_logs_label": "Включи debug логове"
},
"unauthenticated_view_body": "Все още не сте регистрирани? <2>Създайте акаунт</2>",
"unauthenticated_view_login_button": "Влезте в акаунта си",
"version": "Версия: {{version}}",
"waiting_for_participants": "Изчакване на други участници…"
"version": "Версия: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Zavřít",
"copy": "Kopírovat",
"go": "Pokračovat",
"no": "Ne",
"register": "Registrace",
@@ -18,19 +17,14 @@
"not_now_button": "Teď ne, vrátit se na domovskou obrazovku"
},
"common": {
"camera": "Kamera",
"copied": "Zkopírováno!",
"display_name": "Zobrazované jméno",
"home": "Domov",
"loading": "Načítání…",
"microphone": "Mikrofon",
"password": "Heslo",
"profile": "Profil",
"settings": "Nastavení",
"username": "Uživatelské jméno"
},
"full_screen_view_description": "<0>Odeslání ladících záznamů nám pomůže diagnostikovat problém.</0>",
"full_screen_view_h1": "<0>Oops, něco se pokazilo.</0>",
"header_label": "Domov Element Call",
"join_existing_call_modal": {
"join_button": "Ano, připojit se",
@@ -60,20 +54,13 @@
"register_auth_links": "<0>Už máte účet?</0><1><0>Přihlásit se</0> Or <2>Jako host</2></1>",
"register_confirm_password_label": "Potvrdit heslo",
"return_home_button": "Vrátit se na domácí obrazovku",
"room_auth_view_join_button": "Připojit se k hovoru",
"screenshare_button_label": "Sdílet obrazovku",
"select_input_unset_button": "Vyberte možnost",
"settings": {
"developer_settings_label": "Vývojářské nastavení",
"developer_settings_label_description": "Zobrazit vývojářské nastavení.",
"developer_tab_title": "Vývojář",
"feedback_tab_h4": "Dát feedback",
"feedback_tab_send_logs_label": "Zahrnout ladící záznamy",
"more_tab_title": "Více",
"speaker_device_selection_label": "Reproduktor"
"feedback_tab_send_logs_label": "Zahrnout ladící záznamy"
},
"unauthenticated_view_body": "Nejste registrovaní? <2>Vytvořit účet</2>",
"unauthenticated_view_login_button": "Přihlásit se ke svému účtu",
"version": "Verze: {{version}}",
"waiting_for_participants": "Čekání na další účastníky…"
"version": "Verze: {{version}}"
}

218
locales/de/app.json Normal file
View File

@@ -0,0 +1,218 @@
{
"a11y": {
"user_menu": "Benutzermenü"
},
"action": {
"close": "Schließen",
"copy_link": "Link kopieren",
"edit": "Bearbeiten",
"go": "Los gehts",
"invite": "Einladen",
"lower_hand": "Handmeldung zurücknehmen",
"no": "Nein",
"pick_reaction": "Reaktion auswählen",
"raise_hand": "Handmeldung",
"register": "Registrieren",
"remove": "Entfernen",
"show_less": "Weniger anzeigen",
"show_more": "Mehr anzeigen",
"sign_in": "Anmelden",
"sign_out": "Abmelden",
"submit": "Absenden",
"upload_file": "Datei hochladen"
},
"analytics_notice": "Mit der Teilnahme an der Beta akzeptierst du die Sammlung von anonymen Daten, die wir zur Verbesserung des Produkts verwenden. Weitere Informationen zu den von uns erhobenen Daten findest du in unserer <2>Datenschutzerklärung</2> und unseren <6>Cookie-Richtlinien</6>.",
"app_selection_modal": {
"continue_in_browser": "Weiter im Browser",
"open_in_app": "In der App öffnen",
"text": "Bereit, beizutreten?",
"title": "App auswählen"
},
"call_ended_view": {
"create_account_button": "Konto erstellen",
"create_account_prompt": "<0>Warum vergibst du nicht abschließend ein Passwort, um dein Konto zu erhalten?</0><1>Du kannst deinen Namen behalten und ein Profilbild für zukünftige Anrufe festlegen.</1>",
"feedback_done": "<0>Danke für deine Rückmeldung!</0>",
"feedback_prompt": "<0>Wir würden uns freuen, deine Rückmeldung zu hören, um deine Erfahrung verbessern zu können.</0>",
"headline": "{{displayName}}, dein Anruf wurde beendet.",
"not_now_button": "Nicht jetzt, zurück zur Startseite",
"reconnect_button": "Erneut verbinden",
"survey_prompt": "Wie ist es gelaufen?"
},
"call_name": "Name des Anrufs",
"common": {
"analytics": "Analyse",
"audio": "Audio",
"avatar": "Profilbild",
"back": "Zurück",
"display_name": "Anzeigename",
"encrypted": "Verschlüsselt",
"home": "Startseite",
"loading": "Lade …",
"next": "Weiter",
"options": "Optionen",
"password": "Passwort",
"preferences": "Einstellungen",
"profile": "Profil",
"reaction": "Reaktion",
"reactions": "Reaktionen",
"settings": "Einstellungen",
"unencrypted": "Nicht verschlüsselt",
"username": "Benutzername",
"video": "Video"
},
"developer_mode": {
"crypto_version": "Krypto-Version: {{version}}",
"debug_tile_layout_label": "Kachel-Layout debuggen",
"device_id": "Geräte-ID: {{id}}",
"duplicate_tiles_label": "Anzahl zusätzlicher Kachelkopien pro Teilnehmer",
"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",
"use_new_membership_manager": "Neuen MembershipManager verwenden"
},
"disconnected_banner": "Die Verbindung zum Server wurde getrennt.",
"error": {
"call_is_not_supported": "Anrufe werden nicht unterstützt",
"call_not_found": "Anruf nicht gefunden",
"call_not_found_description": "<0>Dieser Link scheint zu keinem bestehenden Anruf zu gehören. Vergewissern Sie sich, dass Sie den richtigen Link haben, oder <1> erstellen Sie einen neuen</1>. </0>",
"connection_lost": "Verbindung verloren",
"connection_lost_description": "Ihre Verbindung zum Anruf wurde unterbrochen.",
"e2ee_unsupported": "Inkompatibler Browser",
"e2ee_unsupported_description": "Ihr Webbrowser unterstützt keine verschlüsselten Anrufe. Zu den unterstützten Browsern gehören Chrome, Safari und Firefox 117+.",
"generic": "Etwas ist schief gelaufen",
"generic_description": "Durch das Senden von Debugprotokollen können wir das Problem leichter eingrenzen.",
"insufficient_capacity": "Unzureichende Kapazität",
"insufficient_capacity_description": "Der Server hat seine maximale Kapazität erreicht, daher ist ein Beitritt zum Anruf derzeit nicht möglich. Bitte später erneut versuchen oder den Serveradministrator kontaktieren, falls das Problem weiterhin besteht.",
"matrix_rtc_focus_missing": "Der Server ist nicht für die Verwendung mit {{brand}} konfiguriert. Bitte den Serveradministrator kontaktieren (Domain: {{domain}}, Fehlercode: {{ errorCode }}).",
"open_elsewhere": "In einem anderen Tab geöffnet",
"open_elsewhere_description": "{{brand}} wurde in einem anderen Tab geöffnet. Wenn das nicht richtig klingt, versuchen Sie, die Seite neu zu laden.",
"unexpected_ec_error": "Ein unerwarteter Fehler ist aufgetreten (<0>Fehlercode: </0> <1>{{ errorCode }}</1>). Bitte den Serveradministrator kontaktieren."
},
"group_call_loader": {
"banned_body": "Du wurdest aus dem Raum verbannt.",
"banned_heading": "Verbannt",
"call_ended_body": "Du wurdest aus dem Anruf entfernt.",
"call_ended_heading": "Anruf beendet",
"knock_reject_body": "Die Teilnahmeanfrage wurde abgelehnt.",
"knock_reject_heading": "Zugriff verweigert",
"reason": "Grund: {{reason}}"
},
"hangup_button_label": "Anruf beenden",
"header_label": "Element Call-Startseite",
"header_participants_label": "Teilnehmende",
"invite_modal": {
"link_copied_toast": "Link in Zwischenablage kopiert",
"title": "Zu diesem Anruf einladen"
},
"join_existing_call_modal": {
"join_button": "Ja, Anruf beitreten",
"text": "Dieser Aufruf existiert bereits, möchtest Du teilnehmen?",
"title": "An bestehendem Anruf teilnehmen?"
},
"layout_grid_label": "Raster",
"layout_spotlight_label": "Fokus",
"lobby": {
"ask_to_join": "Teilnahmeanfrage senden",
"join_as_guest": "Als Gast beitreten",
"join_button": "Anruf beitreten",
"leave_button": "Zurück zu kürzlichen Anrufen",
"waiting_for_invite": "Anfrage gesendet! Warten auf Teilnahmefreigabe …"
},
"log_in": "Anmelden",
"logging_in": "Anmelden …",
"login_auth_links": "<0>Konto erstellen</0> Oder <2>Als Gast betreten</2>",
"login_auth_links_prompt": "Noch nicht registriert?",
"login_subheading": "Weiter zu Element",
"login_title": "Anmelden",
"microphone_off": "Mikrofon aus",
"microphone_on": "Mikrofon an",
"mute_microphone_button_label": "Mikrofon stumm schalten",
"participant_count_one": "{{count, number}}",
"participant_count_other": "{{count, number}}",
"qr_code": "QR-Code",
"rageshake_button_error_caption": "Protokolle erneut senden",
"rageshake_request_modal": {
"body": "Ein anderer Benutzer dieses Anrufs hat ein Problem. Um es besser diagnostizieren zu können, würden wir gerne ein Debug-Protokoll erstellen.",
"title": "Debug-Log Anfrage"
},
"rageshake_send_logs": "Debug-Logs senden",
"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",
"register": {
"passwords_must_match": "Passwörter müssen übereinstimmen",
"registering": "Registrierung …"
},
"register_auth_links": "<0>Du hast bereits ein Konto?</0><1><0>Anmelden</0> Oder <2>Als Gast betreten</2></1>",
"register_confirm_password_label": "Passwort bestätigen",
"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>",
"screenshare_button_label": "Bildschirm teilen",
"settings": {
"audio_tab": {
"effect_volume_description": "Lautstärke anpassen, mit der Reaktionen und Handmeldungen abgespielt werden.",
"effect_volume_label": "Lautstärke der Soundeffekte"
},
"developer_tab_title": "Entwickler",
"devices": {
"camera": "Kamera",
"camera_numbered": "Kamera {{n}}",
"default": "Standard",
"default_named": "Standard<2> ({{name}} )</2>",
"microphone": "Mikrofon",
"microphone_numbered": "Mikrofon{{n}}",
"speaker": "Lautsprecher",
"speaker_numbered": "Lautsprecher{{n}}"
},
"feedback_tab_body": "Falls du auf Probleme stößt oder einfach nur eine Rückmeldung geben möchtest, sende uns bitte eine kurze Beschreibung.",
"feedback_tab_description_label": "Deine Rückmeldung",
"feedback_tab_h4": "Rückmeldung geben",
"feedback_tab_send_logs_label": "Debug-Protokolle anhängen",
"feedback_tab_thank_you": "Danke, wir haben deine Rückmeldung erhalten!",
"feedback_tab_title": "Rückmeldung",
"opt_in_description": "<0></0><1></1>Du kannst deine Zustimmung durch Abwählen dieses Kästchens zurückziehen. Falls du dich aktuell in einem Anruf befindest, wird diese Einstellung nach dem Ende des Anrufs wirksam.",
"preferences_tab": {
"developer_mode_label": "Entwickler-Modus",
"developer_mode_label_description": "Aktivieren Sie den Entwicklermodus und zeigen Sie die Registerkarte mit den Entwicklereinstellungen an.",
"introduction": "Hier können zusätzliche Optionen für individuelle Anforderungen eingestellt werden.",
"reactions_play_sound_description": "Spielen Sie einen Soundeffekt ab, wenn jemand eine Reaktion auf einen Anruf sendet.",
"reactions_play_sound_label": "Reaktionstöne abspielen",
"reactions_show_description": "Zeige eine Animation, wenn jemand eine Reaktion sendet.",
"reactions_show_label": "Reaktionen anzeigen",
"show_hand_raised_timer_description": "Einen Timer zur Handmeldung anzeigen",
"show_hand_raised_timer_label": "Dauer der Handmeldung anzeigen"
}
},
"star_rating_input_label_one": "{{count}} Stern",
"star_rating_input_label_other": "{{count}} Sterne",
"start_new_call": "Neuen Anruf beginnen",
"start_video_button_label": "Video aktivieren",
"stop_screenshare_button_label": "Bildschirm wird geteilt",
"stop_video_button_label": "Video deaktivieren",
"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",
"unmute_microphone_button_label": "Mikrofon einschalten",
"version": "{{productName}} Version: {{version}}",
"video_tile": {
"always_show": "Immer anzeigen",
"camera_starting": "Video wird geladen...",
"change_fit_contain": "An Fenster anpassen",
"collapse": "Minimieren",
"expand": "Erweitern",
"mute_for_me": "Für mich stumm schalten",
"muted_for_me": "Für mich stumm geschaltet",
"volume": "Lautstärke",
"waiting_for_media": "Warten auf Medien..."
}
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Κλείσιμο",
"copy": "Αντιγραφή",
"go": "Μετάβαση",
"no": "Όχι",
"register": "Εγγραφή",
@@ -13,7 +12,7 @@
"sign_out": "Αποσύνδεση",
"submit": "Υποβολή"
},
"analytics_notice": "Συμμετέχοντας σε αυτή τη δοκιμαστική έκδοση, συναινείτε στη συλλογή ανώνυμων δεδομένων, τα οποία χρησιμοποιούμε για τη βελτίωση του προϊόντος. Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με το ποια δεδομένα καταγράφουμε στην <2>Πολιτική απορρήτου</2> και στην <6>Πολιτική cookies</6>.",
"analytics_notice": "Συμμετέχοντας σε αυτή τη δοκιμαστική έκδοση, συναινείτε στη συλλογή ανώνυμων δεδομένων, τα οποία χρησιμοποιούμε για τη βελτίωση του προϊόντος. Μπορείτε να βρείτε περισσότερες πληροφορίες σχετικά με το ποια δεδομένα καταγράφουμε στην <2>Πολιτική απορρήτου</2> και στην <5>Πολιτική cookies</5>.",
"call_ended_view": {
"create_account_button": "Δημιουργία λογαριασμού",
"create_account_prompt": "<0>Γιατί να μην ολοκληρώσετε με τη δημιουργία ενός κωδικού πρόσβασης για τη διατήρηση του λογαριασμού σας;</0><1>Θα μπορείτε να διατηρήσετε το όνομά σας και να ορίσετε ένα avatar για χρήση σε μελλοντικές κλήσεις.</1>",
@@ -25,20 +24,15 @@
},
"common": {
"audio": "Ήχος",
"camera": "Κάμερα",
"copied": "Αντιγράφηκε!",
"display_name": "Εμφανιζόμενο όνομα",
"home": "Αρχική",
"loading": "Φόρτωση…",
"microphone": "Μικρόφωνο",
"password": "Κωδικός",
"profile": "Προφίλ",
"settings": "Ρυθμίσεις",
"username": "Όνομα χρήστη",
"video": "Βίντεο"
},
"full_screen_view_description": "<0>Η υποβολή αρχείων καταγραφής σφαλμάτων θα μας βοηθήσει να εντοπίσουμε το πρόβλημα.</0>",
"full_screen_view_h1": "<0>Ωχ, κάτι πήγε στραβά.</0>",
"header_label": "Element Κεντρική Οθόνη Κλήσεων",
"join_existing_call_modal": {
"join_button": "Ναι, συμμετοχή στην κλήση",
@@ -67,12 +61,8 @@
"register_auth_links": "<0>Έχετε ήδη λογαριασμό;</0><1><0>Συνδεθείτε</0> Ή <2>Συμμετέχετε ως επισκέπτης</2></1>",
"register_confirm_password_label": "Επιβεβαίωση κωδικού",
"return_home_button": "Επιστροφή στην αρχική οθόνη",
"room_auth_view_join_button": "Συμμετοχή στην κλήση τώρα",
"screenshare_button_label": "Κοινή χρήση οθόνης",
"select_input_unset_button": "Επιλέξτε μια επιλογή",
"settings": {
"developer_settings_label": "Ρυθμίσεις προγραμματιστή",
"developer_settings_label_description": "Εμφάνιση ρυθμίσεων προγραμματιστή στο παράθυρο ρυθμίσεων.",
"developer_tab_title": "Προγραμματιστής",
"feedback_tab_body": "Εάν αντιμετωπίζετε προβλήματα ή απλά θέλετε να μας δώσετε κάποια σχόλια, παρακαλούμε στείλτε μας μια σύντομη περιγραφή παρακάτω.",
"feedback_tab_description_label": "Τα σχόλιά σας",
@@ -80,16 +70,12 @@
"feedback_tab_send_logs_label": "Να συμπεριληφθούν αρχεία καταγραφής",
"feedback_tab_thank_you": "Ευχαριστούμε, λάβαμε τα σχόλιά σας!",
"feedback_tab_title": "Ανατροφοδότηση",
"more_tab_title": "Περισσότερα",
"opt_in_description": "<0></0><1></1>Μπορείτε να ανακαλέσετε τη συγκατάθεσή σας αποεπιλέγοντας αυτό το πλαίσιο. Εάν βρίσκεστε σε κλήση, η ρύθμιση αυτή θα τεθεί σε ισχύ στο τέλος της.",
"show_connection_stats_label": "Εμφάνιση στατιστικών σύνδεσης",
"speaker_device_selection_label": "Ηχείο"
"opt_in_description": "<0></0><1></1>Μπορείτε να ανακαλέσετε τη συγκατάθεσή σας αποεπιλέγοντας αυτό το πλαίσιο. Εάν βρίσκεστε σε κλήση, η ρύθμιση αυτή θα τεθεί σε ισχύ στο τέλος της."
},
"star_rating_input_label_one": "{{count}} αστέρι",
"star_rating_input_label_other": "{{count}} αστέρια",
"submitting": "Υποβολή…",
"unauthenticated_view_body": "Δεν έχετε εγγραφεί ακόμα; <2>Δημιουργήστε λογαριασμό</2>",
"unauthenticated_view_login_button": "Συνδεθείτε στον λογαριασμό σας",
"version": "Έκδοση: {{version}}",
"waiting_for_participants": "Αναμονή για άλλους συμμετέχοντες…"
"version": "Έκδοση: {{version}}"
}

View File

@@ -8,9 +8,14 @@
"edit": "Edit",
"go": "Go",
"invite": "Invite",
"lower_hand": "Lower hand",
"no": "No",
"pick_reaction": "Pick reaction",
"raise_hand": "Raise hand",
"register": "Register",
"remove": "Remove",
"show_less": "Show less",
"show_more": "Show more",
"sign_in": "Sign in",
"sign_out": "Sign out",
"submit": "Submit",
@@ -23,11 +28,7 @@
"text": "Ready to join?",
"title": "Select app"
},
"application_opened_another_tab": "This application has been opened in another tab.",
"browser_media_e2ee_unsupported": "Your web browser does not support media end-to-end encryption. Supported Browsers are Chrome, Safari, Firefox >=117",
"browser_media_e2ee_unsupported_heading": "Incompatible Browser",
"call_ended_view": {
"body": "You were disconnected from the call",
"create_account_button": "Create account",
"create_account_prompt": "<0>Why not finish by setting up a password to keep your account?</0><1>You'll be able to keep your name and set an avatar for use on future calls</1>",
"feedback_done": "<0>Thanks for your feedback!</0>",
@@ -43,37 +44,61 @@
"audio": "Audio",
"avatar": "Avatar",
"back": "Back",
"camera": "Camera",
"display_name": "Display name",
"encrypted": "Encrypted",
"error": "Error",
"home": "Home",
"loading": "Loading…",
"microphone": "Microphone",
"next": "Next",
"options": "Options",
"password": "Password",
"preferences": "Preferences",
"profile": "Profile",
"reaction": "Reaction",
"reactions": "Reactions",
"settings": "Settings",
"unencrypted": "Not encrypted",
"username": "Username",
"video": "Video"
},
"crypto_version": "Crypto version: {{version}}",
"device_id": "Device ID: {{id}}",
"developer_mode": {
"crypto_version": "Crypto version: {{version}}",
"debug_tile_layout_label": "Debug tile layout",
"device_id": "Device ID: {{id}}",
"duplicate_tiles_label": "Number of additional tile copies per participant",
"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",
"use_new_membership_manager": "Use the new implementation of the call MembershipManager"
},
"disconnected_banner": "Connectivity to the server has been lost.",
"full_screen_view_description": "<0>Submitting debug logs will help us track down the problem.</0>",
"full_screen_view_h1": "<0>Oops, something's gone wrong.</0>",
"error": {
"call_is_not_supported": "Call is not supported",
"call_not_found": "Call not found",
"call_not_found_description": "<0>That link doesn't appear to belong to any existing call. Check that you have the right link, or <1>create a new one</1>.</0>",
"connection_lost": "Connection lost",
"connection_lost_description": "You were disconnected from the call.",
"e2ee_unsupported": "Incompatible browser",
"e2ee_unsupported_description": "Your web browser does not support encrypted calls. Supported browsers include Chrome, Safari, and Firefox 117+.",
"generic": "Something went wrong",
"generic_description": "Submitting debug logs will help us track down the problem.",
"insufficient_capacity": "Insufficient capacity",
"insufficient_capacity_description": "The server has reached its maximum capacity and you cannot join the call at this time. Try again later, or contact your server admin if the problem persists.",
"matrix_rtc_focus_missing": "The server is not configured to work with {{brand}}. Please contact your server admin (Domain: {{domain}}, Error Code: {{ errorCode }}).",
"open_elsewhere": "Opened in another tab",
"open_elsewhere_description": "{{brand}} has been opened in another tab. If that doesn't sound right, try reloading the page.",
"unexpected_ec_error": "An unexpected error occurred (<0>Error Code:</0> <1>{{ errorCode }}</1>). Please contact your server admin."
},
"group_call_loader": {
"banned_body": "You have been banned from the room.",
"banned_heading": "Banned",
"call_ended_body": "You have been removed from the call.",
"call_ended_heading": "Call ended",
"failed_heading": "Failed to join",
"failed_text": "Call not found or is not accessible.",
"knock_reject_body": "The room members declined your request to join.",
"knock_reject_heading": "Not allowed to join",
"reason": "Reason"
"knock_reject_body": "Your request to join was declined.",
"knock_reject_heading": "Access denied",
"reason": "Reason: {{reason}}"
},
"hangup_button_label": "End call",
"header_label": "Element Call Home",
@@ -90,11 +115,11 @@
"layout_grid_label": "Grid",
"layout_spotlight_label": "Spotlight",
"lobby": {
"ask_to_join": "Ask to join call",
"ask_to_join": "Request to join call",
"join_as_guest": "Join as guest",
"join_button": "Join call",
"leave_button": "Back to recents",
"waiting_for_invite": "Request sent"
"waiting_for_invite": "Request sent! Waiting for permission to join…"
},
"log_in": "Log In",
"logging_in": "Logging in…",
@@ -102,7 +127,6 @@
"login_auth_links_prompt": "Not registered yet?",
"login_subheading": "To continue to Element",
"login_title": "Login",
"matrix_id": "Matrix ID: {{id}}",
"microphone_off": "Microphone off",
"microphone_on": "Microphone on",
"mute_microphone_button_label": "Mute microphone",
@@ -133,21 +157,41 @@
"room_auth_view_eula_caption": "By clicking \"Continue\", you agree to our <2>End User Licensing Agreement (EULA)</2>",
"screenshare_button_label": "Share screen",
"settings": {
"developer_settings_label": "Developer Settings",
"developer_settings_label_description": "Expose developer settings in the settings window.",
"audio_tab": {
"effect_volume_description": "Adjust the volume at which reactions and hand raised effects play.",
"effect_volume_label": "Sound effect volume"
},
"developer_tab_title": "Developer",
"duplicate_tiles_label": "Number of additional tile copies per participant",
"devices": {
"camera": "Camera",
"camera_numbered": "Camera {{n}}",
"default": "Default",
"default_named": "Default <2>({{name}})</2>",
"microphone": "Microphone",
"microphone_numbered": "Microphone {{n}}",
"speaker": "Speaker",
"speaker_numbered": "Speaker {{n}}"
},
"feedback_tab_body": "If you are experiencing issues or simply would like to provide some feedback, please send us a short description below.",
"feedback_tab_description_label": "Your feedback",
"feedback_tab_h4": "Submit feedback",
"feedback_tab_send_logs_label": "Include debug logs",
"feedback_tab_thank_you": "Thanks, we received your feedback!",
"feedback_tab_title": "Feedback",
"more_tab_title": "More",
"opt_in_description": "<0></0><1></1>You may withdraw consent by unchecking this box. If you are currently in a call, this setting will take effect at the end of the call.",
"speaker_device_selection_label": "Speaker"
"preferences_tab": {
"developer_mode_label": "Developer mode",
"developer_mode_label_description": "Enable developer mode and show developer settings tab.",
"introduction": "Here you can configure extra options for an improved experience.",
"reactions_play_sound_description": "Play a sound effect when anyone sends a reaction into a call.",
"reactions_play_sound_label": "Play reaction sounds",
"reactions_show_description": "Show an animation when anyone sends a reaction.",
"reactions_show_label": "Show reactions",
"show_hand_raised_timer_description": "Show a timer when a participant raises their hand",
"show_hand_raised_timer_label": "Show hand raise duration"
}
},
"star_rating_input_label_one": "{{count}} stars",
"star_rating_input_label_one": "{{count}} star",
"star_rating_input_label_other": "{{count}} stars",
"start_new_call": "Start new call",
"start_video_button_label": "Start video",
@@ -162,10 +206,13 @@
"version": "{{productName}} version: {{version}}",
"video_tile": {
"always_show": "Always show",
"camera_starting": "Video loading...",
"change_fit_contain": "Fit to frame",
"collapse": "Collapse",
"expand": "Expand",
"mute_for_me": "Mute for me",
"volume": "Volume"
"muted_for_me": "Muted for me",
"volume": "Volume",
"waiting_for_media": "Waiting for media..."
}
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Cerrar",
"copy": "Copiar",
"go": "Comenzar",
"register": "Registrarse",
"remove": "Eliminar",
@@ -12,7 +11,7 @@
"sign_out": "Cerrar sesión",
"submit": "Enviar"
},
"analytics_notice": "Al participar en esta beta, consientes a la recogida de datos anónimos, los cuales usaremos para mejorar el producto. Puedes encontrar más información sobre que datos recogemos en nuestra <2>Política de privacidad</2> y en nuestra <6>Política sobre Cookies</6>.",
"analytics_notice": "Al participar en esta beta, consientes a la recogida de datos anónimos, los cuales usaremos para mejorar el producto. Puedes encontrar más información sobre que datos recogemos en nuestra <2>Política de privacidad</2> y en nuestra <5>Política sobre Cookies</5>.",
"call_ended_view": {
"create_account_button": "Crear cuenta",
"create_account_prompt": "<0>¿Por qué no mantienes tu cuenta estableciendo una contraseña?</0><1>Podrás mantener tu nombre y establecer un avatar para usarlo en futuras llamadas</1>",
@@ -23,19 +22,14 @@
"survey_prompt": "¿Cómo ha ido?"
},
"common": {
"camera": "Cámara",
"copied": "¡Copiado!",
"display_name": "Nombre a mostrar",
"home": "Inicio",
"loading": "Cargando…",
"microphone": "Micrófono",
"password": "Contraseña",
"profile": "Perfil",
"settings": "Ajustes",
"username": "Nombre de usuario"
},
"full_screen_view_description": "<0>Subir los registros de depuración nos ayudará a encontrar el problema.</0>",
"full_screen_view_h1": "<0>Ups, algo ha salido mal.</0>",
"header_label": "Inicio de Element Call",
"join_existing_call_modal": {
"join_button": "Si, unirse a la llamada",
@@ -67,12 +61,8 @@
"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>",
"room_auth_view_join_button": "Unirse a la llamada ahora",
"screenshare_button_label": "Compartir pantalla",
"select_input_unset_button": "Selecciona una opción",
"settings": {
"developer_settings_label": "Ajustes de desarrollador",
"developer_settings_label_description": "Muestra los ajustes de desarrollador en la ventana de ajustes.",
"developer_tab_title": "Desarrollador",
"feedback_tab_body": "Si tienes algún problema o simplemente quieres darnos tu opinión, por favor envíanos una breve descripción.",
"feedback_tab_description_label": "Tus comentarios",
@@ -80,10 +70,7 @@
"feedback_tab_send_logs_label": "Incluir registros de depuración",
"feedback_tab_thank_you": "¡Gracias, hemos recibido tus comentarios!",
"feedback_tab_title": "Danos tu opinión",
"more_tab_title": "Más",
"opt_in_description": "<0></0><1></1>Puedes retirar tu consentimiento desmarcando esta casilla. Si estás en una llamada, este ajuste se aplicará al final de esta.",
"show_connection_stats_label": "Mostrar estadísticas de conexión",
"speaker_device_selection_label": "Altavoz"
"opt_in_description": "<0></0><1></1>Puedes retirar tu consentimiento desmarcando esta casilla. Si estás en una llamada, este ajuste se aplicará al final de esta."
},
"star_rating_input_label_one": "{{count}} estrella",
"star_rating_input_label_other": "{{count}} estrellas",
@@ -91,6 +78,5 @@
"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}}",
"waiting_for_participants": "Esperando a los otros participantes…"
"version": "Versión: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Sulge",
"copy": "Kopeeri",
"copy_link": "Kopeeri link",
"go": "Jätka",
"invite": "Kutsu",
@@ -15,16 +14,14 @@
"sign_out": "Logi välja",
"submit": "Saada"
},
"analytics_notice": "Nõustudes selle beetaversiooni kasutamisega sa nõustud ka toote arendamiseks kasutatavate anonüümsete andmete kogumisega. Täpsemat teavet kogutavate andmete kohta leiad meie <2>Privaatsuspoliitikast</2> ja meie <6>Küpsiste kasutamise reeglitest</6>.",
"analytics_notice": "Nõustudes selle beetaversiooni kasutamisega sa nõustud ka toote arendamiseks kasutatavate anonüümsete andmete kogumisega. Täpsemat teavet kogutavate andmete kohta leiad meie <2>Privaatsuspoliitikast</2> ja meie <5>Küpsiste kasutamise reeglitest</5>.",
"app_selection_modal": {
"continue_in_browser": "Jätka veebibrauseris",
"open_in_app": "Ava rakenduses",
"text": "Oled valmis liituma?",
"title": "Vali rakendus"
},
"browser_media_e2ee_unsupported": "Sinu veebibrauser ei toeta meedia läbivat krüptimist. Toetatud brauserid on Chrome, Chromium, Safari ja Firefox >=117",
"call_ended_view": {
"body": "Sinu ühendus kõnega katkes",
"create_account_button": "Loo konto",
"create_account_prompt": "<0>Kas soovid salasõna seadistada ja sellega oma kasutajakonto alles jätta?</0><1>Nii saad säilitada oma nime ja määrata profiilipildi, mida saad kasutada tulevastes kõnedes</1>",
"feedback_done": "<0>Täname Sind tagasiside eest!</0>",
@@ -38,13 +35,10 @@
"common": {
"audio": "Heli",
"avatar": "Tunnuspilt",
"camera": "Kaamera",
"copied": "Kopeeritud!",
"display_name": "Kuvatav nimi",
"encrypted": "Krüptitud",
"home": "Avavaatesse",
"loading": "Laadimine …",
"microphone": "Mikrofon",
"password": "Salasõna",
"profile": "Profiil",
"settings": "Seadistused",
@@ -52,8 +46,6 @@
"username": "Kasutajanimi"
},
"disconnected_banner": "Võrguühendus serveriga on katkenud.",
"full_screen_view_description": "<0>Kui saadad meile vealogid, siis on lihtsam vea põhjust otsida.</0>",
"full_screen_view_h1": "<0>Ohoo, midagi on nüüd katki.</0>",
"hangup_button_label": "Lõpeta kõne",
"header_participants_label": "Osalejad",
"invite_modal": {
@@ -97,12 +89,8 @@
"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>",
"room_auth_view_join_button": "Liitu kõnega kohe",
"screenshare_button_label": "Jaga ekraani",
"select_input_unset_button": "Vali oma eelistus",
"settings": {
"developer_settings_label": "Arendaja seadistused",
"developer_settings_label_description": "Näita seadistuste aknas arendajale vajalikke seadeid.",
"developer_tab_title": "Arendaja",
"feedback_tab_body": "Kui selle rakenduse kasutamisel tekib sul probleeme või lihtsalt soovid oma arvamust avaldada, siis palun täida alljärgnev lühike kirjeldus.",
"feedback_tab_description_label": "Sinu tagasiside",
@@ -110,10 +98,7 @@
"feedback_tab_send_logs_label": "Lisa veatuvastuslogid",
"feedback_tab_thank_you": "Tänud, me oleme sinu tagasiside kätte saanud!",
"feedback_tab_title": "Tagasiside",
"more_tab_title": "Rohkem",
"opt_in_description": "<0></0><1></1>Sa võid selle valiku eelmaldamisega alati oma nõusoleku tagasi võtta. Kui sul parasjagu on kõne pooleli, siis seadistuste muudatus jõustub pärast kõne lõppu.",
"show_connection_stats_label": "Näita ühenduse statistikat",
"speaker_device_selection_label": "Kõlar"
"opt_in_description": "<0></0><1></1>Sa võid selle valiku eelmaldamisega alati oma nõusoleku tagasi võtta. Kui sul parasjagu on kõne pooleli, siis seadistuste muudatus jõustub pärast kõne lõppu."
},
"star_rating_input_label_one": "{{count}} tärni",
"star_rating_input_label_other": "{{count}} tärni",
@@ -126,9 +111,5 @@
"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}}",
"video_tile": {
"sfu_participant_local": "Sina"
},
"waiting_for_participants": "Ootame teiste osalejate lisandumist…"
"version": "Versioon: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "بستن",
"copy": "رونوشت",
"go": "رفتن",
"no": "خیر",
"register": "ثبت‌نام",
@@ -20,12 +19,9 @@
"common": {
"audio": "صدا",
"avatar": "آواتار",
"camera": "دوربین",
"copied": "کپی شد!",
"display_name": "نام نمایشی",
"home": "خانه",
"loading": "بارگزاری…",
"microphone": "میکروفون",
"password": "رمز عبور",
"profile": "پروفایل",
"settings": "تنظیمات",
@@ -61,18 +57,13 @@
"register_auth_links": "<0>از قبل حساب کاربری دارید؟</0><1><0>ورود</0> Or <2>به عنوان یک میهمان وارد شوید</2></1>",
"register_confirm_password_label": "تایید رمزعبور",
"return_home_button": "برگشت به صفحه اصلی",
"room_auth_view_join_button": "الان به تماس بپیوند",
"screenshare_button_label": "اشتراک گذاری صفحه نمایش",
"select_input_unset_button": "یک گزینه را انتخاب کنید",
"settings": {
"developer_tab_title": "توسعه دهنده",
"feedback_tab_h4": "بازخورد ارائه دهید",
"feedback_tab_send_logs_label": "شامل لاگ‌های عیب‌یابی",
"more_tab_title": "بیشتر",
"speaker_device_selection_label": "بلندگو"
"feedback_tab_send_logs_label": "شامل لاگ‌های عیب‌یابی"
},
"unauthenticated_view_body": "هنوز ثبت‌نام نکرده‌اید؟ <2>ساخت حساب کاربری</2>",
"unauthenticated_view_login_button": "به حساب کاربری خود وارد شوید",
"version": "نسخه: {{نسخه}}",
"waiting_for_participants": "در انتظار برای دیگر شرکت‌کنندگان…"
"version": "نسخه: {{نسخه}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Fermer",
"copy": "Copier",
"copy_link": "Copier le lien",
"go": "Commencer",
"invite": "Inviter",
@@ -15,16 +14,14 @@
"sign_out": "Déconnexion",
"submit": "Envoyer"
},
"analytics_notice": "En participant à cette beta, vous consentez à la collecte de données anonymes, qui seront utilisées pour améliorer le produit. Vous trouverez plus dinformations sur les données collectées dans notre <2>Politique de vie privée</2> et notre <6>Politique de cookies</6>.",
"analytics_notice": "En participant à cette beta, vous consentez à la collecte de données anonymes, qui seront utilisées pour améliorer le produit. Vous trouverez plus dinformations sur les données collectées dans notre <2>Politique de vie privée</2> et notre <5>Politique de cookies</5>.",
"app_selection_modal": {
"continue_in_browser": "Continuer dans le navigateur",
"open_in_app": "Ouvrir dans lapplication",
"text": "Prêt à rejoindre ?",
"title": "Choisissez lapplication"
},
"browser_media_e2ee_unsupported": "Votre navigateur web ne prend pas en charge le chiffrement de bout-en-bout des médias. Les navigateurs pris en charge sont Chrome, Safari, Firefox >= 117",
"call_ended_view": {
"body": "Vous avez été déconnecté de lappel",
"create_account_button": "Créer un compte",
"create_account_prompt": "<0>Pourquoi ne pas créer un mot de passe pour conserver votre compte ?</0><1>Vous pourrez garder votre nom et définir un avatar pour vos futurs appels</1>",
"feedback_done": "<0>Merci pour votre commentaire !</0>",
@@ -36,8 +33,6 @@
},
"call_name": "Nom de lappel",
"common": {
"camera": "Caméra",
"copied": "Copié !",
"display_name": "Nom daffichage",
"encrypted": "Chiffré",
"home": "Accueil",
@@ -50,8 +45,6 @@
"video": "Vidéo"
},
"disconnected_banner": "La connexion avec le serveur a été perdue.",
"full_screen_view_description": "<0>Soumettre les journaux de débogage nous aidera à déterminer le problème.</0>",
"full_screen_view_h1": "<0>Oups, quelque chose sest mal passé.</0>",
"hangup_button_label": "Terminer lappel",
"header_label": "Accueil Element Call",
"invite_modal": {
@@ -95,12 +88,8 @@
"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>",
"room_auth_view_join_button": "Rejoindre lappel maintenant",
"screenshare_button_label": "Partage décran",
"select_input_unset_button": "Sélectionnez une option",
"settings": {
"developer_settings_label": "Paramètres développeurs",
"developer_settings_label_description": "Affiche les paramètres développeurs dans la fenêtre des paramètres.",
"developer_tab_title": "Développeur",
"feedback_tab_body": "Si vous rencontrez des problèmes, ou vous voulez simplement faire un commentaire, faites-en une courte description ci-dessous.",
"feedback_tab_description_label": "Votre commentaire",
@@ -108,10 +97,7 @@
"feedback_tab_send_logs_label": "Inclure les journaux de débogage",
"feedback_tab_thank_you": "Merci, nous avons reçu vos commentaires !",
"feedback_tab_title": "Commentaires",
"more_tab_title": "Plus",
"opt_in_description": "<0></0><1></1>Vous pouvez retirer votre consentement en décochant cette case. Si vous êtes actuellement en communication, ce paramètre prendra effet à la fin de lappel.",
"show_connection_stats_label": "Afficher les statistiques de la connexion",
"speaker_device_selection_label": "Intervenant"
"opt_in_description": "<0></0><1></1>Vous pouvez retirer votre consentement en décochant cette case. Si vous êtes actuellement en communication, ce paramètre prendra effet à la fin de lappel."
},
"star_rating_input_label_one": "{{count}} favori",
"star_rating_input_label_other": "{{count}} favoris",
@@ -124,9 +110,5 @@
"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}}",
"video_tile": {
"sfu_participant_local": "Vous"
},
"waiting_for_participants": "En attente dautres participants…"
"version": "Version : {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Tutup",
"copy": "Salin",
"copy_link": "Salin tautan",
"go": "Bergabung",
"invite": "Undang",
@@ -15,16 +14,14 @@
"sign_out": "Keluar",
"submit": "Kirim"
},
"analytics_notice": "Dengan bergabung dalam beta ini, Anda mengizinkan kami untuk mengumpulkan data anonim, yang kami gunakan untuk meningkatkan produk ini. Anda dapat mempelajari lebih lanjut tentang data apa yang kami lacak dalam <2>Kebijakan Privasi</2> dan <6>Kebijakan Kuki</6> kami.",
"analytics_notice": "Dengan bergabung dalam beta ini, Anda mengizinkan kami untuk mengumpulkan data anonim, yang kami gunakan untuk meningkatkan produk ini. Anda dapat mempelajari lebih lanjut tentang data apa yang kami lacak dalam <2>Kebijakan Privasi</2> dan <5>Kebijakan Kuki</5> kami.",
"app_selection_modal": {
"continue_in_browser": "Lanjutkan dalam peramban",
"open_in_app": "Buka dalam aplikasi",
"text": "Siap untuk bergabung?",
"title": "Pilih plikasi"
},
"browser_media_e2ee_unsupported": "Peramban web Anda tidak mendukung enkripsi media ujung ke ujung. Peramban yang didukung adalah Chrome, Safari, dan Firefox >=117",
"call_ended_view": {
"body": "Anda terputus dari panggilan",
"create_account_button": "Buat akun",
"create_account_prompt": "<0>Kenapa tidak selesaikan dengan mengatur sebuah kata sandi untuk menjaga akun Anda?</0><1>Anda akan dapat tetap menggunakan nama Anda dan atur sebuah avatar untuk digunakan dalam panggilan di masa mendatang</1>",
"feedback_done": "<0>Terima kasih atas masukan Anda!</0>",
@@ -36,13 +33,10 @@
},
"call_name": "Nama panggilan",
"common": {
"camera": "Kamera",
"copied": "Disalin!",
"display_name": "Nama tampilan",
"encrypted": "Terenkripsi",
"home": "Beranda",
"loading": "Memuat…",
"microphone": "Mikrofon",
"password": "Kata sandi",
"profile": "Profil",
"settings": "Pengaturan",
@@ -50,8 +44,6 @@
"username": "Nama pengguna"
},
"disconnected_banner": "Koneksi ke server telah hilang.",
"full_screen_view_description": "<0>Mengirim catatan pengawakutuan akan membantu kami melacak masalahnya.</0>",
"full_screen_view_h1": "<0>Aduh, ada yang salah.</0>",
"hangup_button_label": "Akhiri panggilan",
"header_label": "Beranda Element Call",
"header_participants_label": "Peserta",
@@ -96,12 +88,8 @@
"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",
"room_auth_view_join_button": "Bergabung ke panggilan sekarang",
"screenshare_button_label": "Bagikan layar",
"select_input_unset_button": "Pilih sebuah opsi",
"settings": {
"developer_settings_label": "Pengaturan Pengembang",
"developer_settings_label_description": "Ekspos pengaturan pengembang dalam jendela pengaturan.",
"developer_tab_title": "Pengembang",
"feedback_tab_body": "Jika Anda mengalami masalah atau hanya ingin memberikan masukan, silakan kirimkan kami deskripsi pendek di bawah.",
"feedback_tab_description_label": "Masukan Anda",
@@ -109,10 +97,7 @@
"feedback_tab_send_logs_label": "Termasuk catatan pengawakutuan",
"feedback_tab_thank_you": "Terima kasih, kami telah menerima masukan Anda!",
"feedback_tab_title": "Masukan",
"more_tab_title": "Lainnya",
"opt_in_description": "<0></0><1></1>Anda dapat mengurungkan kembali izin dengan mencentang kotak ini. Jika Anda saat ini dalam panggilan, pengaturan ini akan diterapkan di akhir panggilan.",
"show_connection_stats_label": "Tampilkan statistik koneksi",
"speaker_device_selection_label": "Pembicara"
"opt_in_description": "<0></0><1></1>Anda dapat mengurungkan kembali izin dengan mencentang kotak ini. Jika Anda saat ini dalam panggilan, pengaturan ini akan diterapkan di akhir panggilan."
},
"star_rating_input_label_one": "{{count}} bintang",
"star_rating_input_label_other": "{{count}} bintang",
@@ -125,9 +110,5 @@
"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}}",
"video_tile": {
"sfu_participant_local": "Anda"
},
"waiting_for_participants": "Menunggu peserta lain…"
"version": "Versi: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Chiudi",
"copy": "Copia",
"copy_link": "Copia collegamento",
"go": "Vai",
"invite": "Invita",
@@ -14,16 +13,14 @@
"sign_out": "Disconnetti",
"submit": "Invia"
},
"analytics_notice": "Partecipando a questa beta, acconsenti alla raccolta di dati anonimi che usiamo per migliorare il prodotto. Puoi trovare più informazioni su quali dati monitoriamo nella nostra <2>informativa sulla privacy</2> e nell'<6>informativa sui cookie</6>.",
"analytics_notice": "Partecipando a questa beta, acconsenti alla raccolta di dati anonimi che usiamo per migliorare il prodotto. Puoi trovare più informazioni su quali dati monitoriamo nella nostra <2>informativa sulla privacy</2> e nell'<5>informativa sui cookie</5>.",
"app_selection_modal": {
"continue_in_browser": "Continua nel browser",
"open_in_app": "Apri nell'app",
"text": "Tutto pronto per entrare?",
"title": "Seleziona app"
},
"browser_media_e2ee_unsupported": "Il tuo browser non supporta la crittografia end-to-end dei media. I browser supportati sono Chrome, Safari, Firefox >=117",
"call_ended_view": {
"body": "Sei stato disconnesso dalla chiamata",
"create_account_button": "Crea profilo",
"create_account_prompt": "<0>Ti va di terminare impostando una password per mantenere il profilo?</0><1>Potrai mantenere il tuo nome e impostare un avatar da usare in chiamate future</1>",
"feedback_done": "<0>Grazie per la tua opinione!</0>",
@@ -35,21 +32,16 @@
},
"call_name": "Nome della chiamata",
"common": {
"camera": "Fotocamera",
"copied": "Copiato!",
"display_name": "Il tuo nome",
"encrypted": "Cifrata",
"home": "Pagina iniziale",
"loading": "Caricamento…",
"microphone": "Microfono",
"profile": "Profilo",
"settings": "Impostazioni",
"unencrypted": "Non cifrata",
"username": "Nome utente"
},
"disconnected_banner": "La connessione al server è stata persa.",
"full_screen_view_description": "<0>L'invio di registri di debug ci aiuterà ad individuare il problema.</0>",
"full_screen_view_h1": "<0>Ops, qualcosa è andato storto.</0>",
"hangup_button_label": "Termina chiamata",
"header_label": "Inizio di Element Call",
"header_participants_label": "Partecipanti",
@@ -94,22 +86,15 @@
"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>",
"room_auth_view_join_button": "Entra in chiamata ora",
"screenshare_button_label": "Condividi schermo",
"select_input_unset_button": "Seleziona un'opzione",
"settings": {
"developer_settings_label": "Impostazioni per sviluppatori",
"developer_settings_label_description": "Mostra le impostazioni per sviluppatori nella finestra delle impostazioni.",
"developer_tab_title": "Sviluppatore",
"feedback_tab_body": "Se stai riscontrando problemi o semplicemente vuoi dare un'opinione, inviaci una breve descrizione qua sotto.",
"feedback_tab_description_label": "Il tuo commento",
"feedback_tab_h4": "Invia commento",
"feedback_tab_send_logs_label": "Includi registri di debug",
"feedback_tab_thank_you": "Grazie, abbiamo ricevuto il tuo commento!",
"more_tab_title": "Altro",
"opt_in_description": "<0></0><1></1>Puoi revocare il consenso deselezionando questa casella. Se attualmente sei in una chiamata, avrà effetto al termine di essa.",
"show_connection_stats_label": "Mostra statistiche connessione",
"speaker_device_selection_label": "Altoparlante"
"opt_in_description": "<0></0><1></1>Puoi revocare il consenso deselezionando questa casella. Se attualmente sei in una chiamata, avrà effetto al termine di essa."
},
"star_rating_input_label_one": "{{count}} stelle",
"star_rating_input_label_other": "{{count}} stelle",
@@ -122,9 +107,5 @@
"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}}",
"video_tile": {
"sfu_participant_local": "Tu"
},
"waiting_for_participants": "In attesa di altri partecipanti…"
"version": "Versione: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "閉じる",
"copy": "コピー",
"go": "続行",
"no": "いいえ",
"register": "登録",
@@ -18,19 +17,15 @@
"common": {
"audio": "音声",
"avatar": "アバター",
"camera": "カメラ",
"copied": "コピーしました!",
"display_name": "表示名",
"home": "ホーム",
"loading": "読み込んでいます…",
"microphone": "マイク",
"password": "パスワード",
"profile": "プロフィール",
"settings": "設定",
"username": "ユーザー名",
"video": "ビデオ"
},
"full_screen_view_h1": "<0>何かがうまく行きませんでした。</0>",
"header_label": "Element Call ホーム",
"join_existing_call_modal": {
"join_button": "はい、通話に参加",
@@ -57,17 +52,13 @@
"register_auth_links": "<0>既にアカウントをお持ちですか?</0><1><0>ログイン</0>または<2>ゲストとしてアクセス</2></1>",
"register_confirm_password_label": "パスワードを確認",
"return_home_button": "ホーム画面に戻る",
"room_auth_view_join_button": "今すぐ通話に参加",
"screenshare_button_label": "画面共有",
"select_input_unset_button": "オプションを選択",
"settings": {
"developer_tab_title": "開発者",
"feedback_tab_h4": "フィードバックを送信",
"feedback_tab_send_logs_label": "デバッグログを含める",
"speaker_device_selection_label": "スピーカー"
"feedback_tab_send_logs_label": "デバッグログを含める"
},
"unauthenticated_view_body": "アカウントがありませんか? <2>アカウントを作成</2>",
"unauthenticated_view_login_button": "アカウントにログイン",
"version": "バージョン:{{version}}",
"waiting_for_participants": "他の参加者を待機しています…"
"version": "バージョン:{{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Aizvērt",
"copy": "Ievietot starpliktuvē",
"go": "Aiziet",
"no": "Nē",
"register": "Reģistrēties",
@@ -13,9 +12,8 @@
"sign_out": "Atteikties",
"submit": "Iesniegt"
},
"analytics_notice": "Piedalīšanās šajā beta apliecina piekrišanu anonīmu datu ievākšanai, ko mēs izmantojam, lai uzlabotu izstrādājumu. Vairāk informācijas par datiem, ko mēs ievācam, var atrast mūsu <2>privātuma nosacījumos</2> un <6>sīkdatņu nosacījumos</6>.",
"analytics_notice": "Piedalīšanās šajā beta apliecina piekrišanu anonīmu datu ievākšanai, ko mēs izmantojam, lai uzlabotu izstrādājumu. Vairāk informācijas par datiem, ko mēs ievācam, var atrast mūsu <2>privātuma nosacījumos</2> un <5>sīkdatņu nosacījumos</5>.",
"call_ended_view": {
"body": "Tu tiki atvienots no zvana",
"create_account_button": "Izveidot kontu",
"create_account_prompt": "<0>Kādēļ nepabeigt ar paroles iestatīšanu, lai paturētu savu kontu?</0><1>Būs iespējams paturēt savu vārdu un iestatīt attēlu izmantošanai turpmākajos zvanos</1>",
"feedback_done": "<0>Paldies par atsauksmi!</0>",
@@ -28,20 +26,15 @@
"common": {
"audio": "Skaņa",
"avatar": "Attēls",
"camera": "Kamera",
"copied": "Ievietots starpliktuvē.",
"display_name": "Attēlojamais vārds",
"home": "Sākums",
"loading": "Lādējas…",
"microphone": "Mikrofons",
"password": "Parole",
"profile": "Profils",
"settings": "Iestatījumi",
"username": "Lietotājvārds"
},
"disconnected_banner": "Ir zaudēts savienojums ar serveri.",
"full_screen_view_description": "<0>Atkļūdošanas žurnāla ierakstu iesūtīšana palīdzēs mums atklāt nepilnību.</0>",
"full_screen_view_h1": "<0>Ak vai, kaut kas nogāja greizi!</0>",
"header_label": "Element Call sākums",
"join_existing_call_modal": {
"join_button": "Jā, pievienoties zvanam",
@@ -75,12 +68,8 @@
"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>",
"room_auth_view_join_button": "Pievienoties zvanam tagad",
"screenshare_button_label": "Kopīgot ekrānu",
"select_input_unset_button": "Atlasīt iespēju",
"settings": {
"developer_settings_label": "Izstrādātāja iestatījumi",
"developer_settings_label_description": "Izstādīt izstrādātāja iestatījumus iestatījumu logā.",
"developer_tab_title": "Izstrādātājs",
"feedback_tab_body": "Ja tiek piedzīvoti sarežģījumi vai vienkārši ir vēlme sniegt kādu atsauksmi, lūgums zemāk nosūtīt mums īsu aprakstu.",
"feedback_tab_description_label": "Tava atsauksme",
@@ -88,10 +77,7 @@
"feedback_tab_send_logs_label": "Iekļaut atkļūdošanas žurnāla ierakstus",
"feedback_tab_thank_you": "Paldies, mēs saņēmām atsauksmi!",
"feedback_tab_title": "Atsauksmes",
"more_tab_title": "Vairāk",
"opt_in_description": "<0></0><1></1>Savu piekrišanu var atsaukt ar atzīmes noņemšanu no šīs rūtiņas. Ja pašreiz atrodies zvanā, šis iestatījums stāsies spēkā zvana beigās.",
"show_connection_stats_label": "Rādīt savienojuma apkopojumu",
"speaker_device_selection_label": "Runātājs"
"opt_in_description": "<0></0><1></1>Savu piekrišanu var atsaukt ar atzīmes noņemšanu no šīs rūtiņas. Ja pašreiz atrodies zvanā, šis iestatījums stāsies spēkā zvana beigās."
},
"star_rating_input_label_one": "{{count}} zvaigzne",
"star_rating_input_label_other": "{{count}} zvaigznes",
@@ -99,6 +85,5 @@
"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}}",
"waiting_for_participants": "Gaida citus dalībniekus…"
"version": "Versija: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Zamknij",
"copy": "Kopiuj",
"copy_link": "Kopiuj link",
"go": "Przejdź",
"invite": "Zaproś",
@@ -15,16 +14,14 @@
"sign_out": "Wyloguj się",
"submit": "Wyślij"
},
"analytics_notice": "Uczestnicząc w tej becie, upoważniasz nas do zbierania anonimowych danych, które wykorzystamy do ulepszenia produktu. Dowiedz się więcej na temat danych, które zbieramy w naszej <2>Polityce prywatności</2> i <6>Polityce ciasteczek</6>.",
"analytics_notice": "Uczestnicząc w tej becie, upoważniasz nas do zbierania anonimowych danych, które wykorzystamy do ulepszenia produktu. Dowiedz się więcej na temat danych, które zbieramy w naszej <2>Polityce prywatności</2> i <5>Polityce ciasteczek</5>.",
"app_selection_modal": {
"continue_in_browser": "Kontynuuj w przeglądarce",
"open_in_app": "Otwórz w aplikacji",
"text": "Gotowy, by dołączyć?",
"title": "Wybierz aplikację"
},
"browser_media_e2ee_unsupported": "Twoja przeglądarka nie wspiera szyfrowania end-to-end. Wspierane przeglądarki to Chrome, Safari, Firefox >=117",
"call_ended_view": {
"body": "Rozłączono Cię z połączenia",
"create_account_button": "Utwórz konto",
"create_account_prompt": "<0>Może zechcesz ustawić hasło, aby zachować swoje konto?</0><1>Będziesz w stanie utrzymać swoją nazwę i ustawić awatar do wyświetlania podczas połączeń w przyszłości</1>",
"feedback_done": "<0>Dziękujemy za Twoją opinię!</0>",
@@ -38,13 +35,10 @@
"common": {
"audio": "Dźwięk",
"avatar": "Awatar",
"camera": "Kamera",
"copied": "Skopiowano!",
"display_name": "Nazwa wyświetlana",
"encrypted": "Szyfrowane",
"home": "Strona domowa",
"loading": "Ładowanie…",
"microphone": "Mikrofon",
"password": "Hasło",
"profile": "Profil",
"settings": "Ustawienia",
@@ -53,8 +47,6 @@
"video": "Wideo"
},
"disconnected_banner": "Utracono połączenie z serwerem.",
"full_screen_view_description": "<0>Wysłanie dzienników debuggowania pomoże nam ustalić przyczynę problemu.</0>",
"full_screen_view_h1": "<0>Ojej, coś poszło nie tak.</0>",
"hangup_button_label": "Zakończ połączenie",
"header_label": "Strona główna Element Call",
"header_participants_label": "Uczestnicy",
@@ -99,12 +91,8 @@
"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>",
"room_auth_view_join_button": "Dołącz do połączenia teraz",
"screenshare_button_label": "Udostępnij ekran",
"select_input_unset_button": "Wybierz opcję",
"settings": {
"developer_settings_label": "Opcje programisty",
"developer_settings_label_description": "Wyświetl opcje programisty w oknie ustawień.",
"developer_tab_title": "Programista",
"feedback_tab_body": "Jeśli posiadasz problemy lub chciałbyś zgłosić swoją opinię, wyślij nam krótki opis.",
"feedback_tab_description_label": "Twoje opinie",
@@ -112,10 +100,7 @@
"feedback_tab_send_logs_label": "Dołącz dzienniki debugowania",
"feedback_tab_thank_you": "Dziękujemy, otrzymaliśmy Twoją opinię!",
"feedback_tab_title": "Opinia użytkownika",
"more_tab_title": "Więcej",
"opt_in_description": "<0></0><1></1>Możesz wycofać swoją zgodę poprzez odznaczenie tego pola. Jeśli już jesteś w trakcie rozmowy, opcja zostanie zastosowana po jej zakończeniu.",
"show_connection_stats_label": "Pokaż statystyki połączenia",
"speaker_device_selection_label": "Głośnik"
"opt_in_description": "<0></0><1></1>Możesz wycofać swoją zgodę poprzez odznaczenie tego pola. Jeśli już jesteś w trakcie rozmowy, opcja zostanie zastosowana po jej zakończeniu."
},
"star_rating_input_label_one": "{{count}} gwiazdki",
"star_rating_input_label_other": "{{count}} gwiazdki",
@@ -128,9 +113,5 @@
"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}}",
"video_tile": {
"sfu_participant_local": "Ty"
},
"waiting_for_participants": "Oczekiwanie na pozostałych uczestników…"
"version": "Wersja: {{version}}"
}

174
locales/ro/app.json Normal file
View File

@@ -0,0 +1,174 @@
{
"a11y": {
"user_menu": "Meniul utilizatorului"
},
"action": {
"close": "Închide",
"copy_link": "Copiază linkul",
"edit": "Editare",
"go": "Du-te",
"invite": "Invită",
"lower_hand": "Mâna inferioară",
"no": "No",
"pick_reaction": "Alegeți reacția",
"raise_hand": "Ridicați mâna",
"register": "Inregistrare",
"remove": "elimina",
"show_less": "Arată mai puțin",
"show_more": "Arată mai mult",
"sign_in": "Autentificare",
"sign_out": "Sign out",
"submit": "Trimiteți",
"upload_file": "Încărcați fișierul"
},
"analytics_notice": "Prin participarea la această versiune beta, sunteți de acord cu colectarea de date anonime, pe care le folosim pentru a îmbunătăți produsul. Puteți găsi mai multe informații despre datele pe care le urmărim în Politica noastră de <2> confidențialitate </2> și Politica noastră <6> privind cookie-urile</6>.",
"app_selection_modal": {
"continue_in_browser": "Continuați în browser",
"open_in_app": "Deschideți în aplicație",
"text": "Sunteți gata să vă alăturați?",
"title": "Selectați aplicația"
},
"call_ended_view": {
"create_account_button": "Creează cont",
"create_account_prompt": "<0>De ce să nu terminați prin configurarea unei parole pentru a vă păstra contul? </0><1>Veți putea să vă păstrați numele și să setați un avatar pentru a fi utilizat la apelurile viitoare </1>",
"feedback_done": "<0>Vă mulțumim pentru feedback! </0>",
"feedback_prompt": "<0>Ne-ar plăcea să auzim feedback-ul dvs., astfel încât să vă putem îmbunătăți experiența. </0>",
"headline": "{{displayName}}, apelul tău s-a încheiat.",
"not_now_button": "Nu acum, reveniți la ecranul de pornire",
"reconnect_button": "Reconecta",
"survey_prompt": "Cum a mers?"
},
"call_name": "Numele apelului",
"common": {
"analytics": "Analiză",
"audio": "Audio",
"avatar": "avatar",
"back": "Înapoi",
"display_name": "Nume afișat",
"encrypted": "Criptat",
"home": "Acasa",
"loading": "Se încarcă...",
"next": "Urmator\n",
"options": "Opțiuni",
"password": "Parolă",
"preferences": "preferinte",
"profile": "Profil",
"reaction": "Reacție",
"reactions": "Reacții",
"settings": "Settings",
"unencrypted": "Nu este criptat",
"username": "Nume utilizator",
"video": "Videoclip"
},
"developer_mode": {
"crypto_version": "Versiunea Crypto: {{version}}",
"device_id": "ID-ul dispozitivului: {{id}}",
"duplicate_tiles_label": "Numărul de exemplare suplimentare de cartonașe per participant",
"hostname": "Numele gazdei: {{hostname}}",
"matrix_id": "ID-ul matricei: {{id}}"
},
"disconnected_banner": "Conectivitatea la server a fost pierdută.",
"group_call_loader": {
"banned_body": "Ai fost interzis să ieși din cameră.",
"banned_heading": "Interzis",
"call_ended_body": "Ați fost eliminat din apel.",
"call_ended_heading": "Apel încheiat",
"knock_reject_body": "Cererea dvs. de a vă alătura a fost respinsă.",
"knock_reject_heading": "Acces refuzat",
"reason": "Motivul"
},
"hangup_button_label": "Încheiați apelul",
"header_label": "Element Call Home",
"header_participants_label": "Participanți",
"invite_modal": {
"link_copied_toast": "Link copiat în clipboard",
"title": "Invitați la acest apel"
},
"join_existing_call_modal": {
"join_button": "Da, alăturați-vă apelului",
"text": "Acest apel există deja, doriți să vă alăturați?",
"title": "Alăturați-vă apelului existent?"
},
"layout_grid_label": "GRILĂ",
"layout_spotlight_label": "Spotlight",
"lobby": {
"ask_to_join": "Solicitare de participare la apel",
"join_as_guest": "Alăturați-vă ca invitat",
"join_button": "Alăturați-vă apelului",
"leave_button": "Înapoi la cele mai recente",
"waiting_for_invite": "Solicitare trimisă! În așteptarea permisiunii de a participa..."
},
"log_in": "Autentificare",
"logging_in": "Autentificare...",
"login_auth_links": "<0>Creați un cont </0> sau <2> accesați ca invitat </2>",
"login_auth_links_prompt": "Nu sunteți încă înregistrat?",
"login_subheading": "Pentru a continua la Element",
"login_title": "Logare",
"microphone_off": "Microfon oprit",
"microphone_on": "Microfon pornit",
"mute_microphone_button_label": "Dezactivați microfonul",
"qr_code": "COD QR",
"rageshake_button_error_caption": "Încearcă din nou trimiterea jurnalelor",
"rageshake_request_modal": {
"body": "Un alt utilizator al acestui apel are o problemă. Pentru a diagnostica mai bine aceste probleme, am dori să colectăm un jurnal de depanare.",
"title": "Solicitare jurnal de depanare"
},
"rageshake_send_logs": "Trimiteți jurnale de depanare",
"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": {
"passwords_must_match": "Parolele trebuie să se potrivească",
"registering": "Înregistrare..."
},
"register_auth_links": "<0>Ai deja un cont? </0><1><0>Conectați-vă </0> sau <2> accesați ca invitat </2> </1>",
"register_confirm_password_label": "Confirmă Parola",
"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": {
"effect_volume_description": "Reglați volumul la care reacționează reacțiile și efectele ridicate de mână",
"effect_volume_label": "Volumul efectului sonor"
},
"developer_tab_title": "dezvoltator",
"feedback_tab_body": "Dacă întâmpinați probleme sau pur și simplu doriți să oferiți feedback, vă rugăm să ne trimiteți o scurtă descriere mai jos.",
"feedback_tab_description_label": "Feedback-ul tău",
"feedback_tab_h4": "Trimiteți Feedback",
"feedback_tab_send_logs_label": "Includeți jurnale de depanare",
"feedback_tab_thank_you": "Vă mulțumim, am primit feedback-ul dvs.!",
"feedback_tab_title": "Feedback",
"opt_in_description": "<0></0><1></1>Puteți retrage consimțământul debifând această casetă. Dacă sunteți în prezent la un apel, această setare va intra în vigoare la sfârșitul apelului.",
"preferences_tab": {
"reactions_play_sound_description": "Redați un efect sonor atunci când cineva trimite o reacție la un apel.",
"reactions_play_sound_label": "Redați sunete de reacție",
"reactions_show_description": "Afișați o animație atunci când cineva trimite o reacție.",
"reactions_show_label": "Afișați reacțiile"
}
},
"start_new_call": "Începe un nou apel",
"start_video_button_label": "Începeți videoclipul",
"stop_screenshare_button_label": "Partajarea ecranului",
"stop_video_button_label": "Opriți videoclipul",
"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}}",
"video_tile": {
"always_show": "Arată întotdeauna",
"change_fit_contain": "Se potrivește cadrului",
"collapse": "colaps",
"expand": "Extindeți",
"mute_for_me": "Mute pentru mine",
"muted_for_me": "Dezactivat pentru mine",
"volume": "VOLUM"
}
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Закрыть",
"copy": "Копировать",
"go": "Далее",
"no": "Нет",
"register": "Зарегистрироваться",
@@ -13,7 +12,7 @@
"sign_out": "Выйти",
"submit": "Отправить"
},
"analytics_notice": "Участвуя в этой бета-версии, вы соглашаетесь на сбор анонимных данных, которые мы используем для улучшения продукта. Более подробную информацию о том, какие данные мы отслеживаем, вы можете найти в нашей <2> Политике конфиденциальности</2> и нашей <6> Политике использования файлов cookie</6>.",
"analytics_notice": "Участвуя в этой бета-версии, вы соглашаетесь на сбор анонимных данных, которые мы используем для улучшения продукта. Более подробную информацию о том, какие данные мы отслеживаем, вы можете найти в нашей <2> Политике конфиденциальности</2> и нашей <5> Политике использования файлов cookie</5>.",
"call_ended_view": {
"create_account_button": "Создать аккаунт",
"create_account_prompt": "<0>Почему бы не задать пароль, тем самым сохранив аккаунт?</0><1>Так вы можете оставить своё имя и задать аватар для будущих звонков.</1>",
@@ -26,20 +25,15 @@
"common": {
"audio": "Аудио",
"avatar": "Аватар",
"camera": "Камера",
"copied": "Скопировано!",
"display_name": "Видимое имя",
"home": "Начало",
"loading": "Загрузка…",
"microphone": "Микрофон",
"password": "Пароль",
"profile": "Профиль",
"settings": "Настройки",
"username": "Имя пользователя",
"video": "Видео"
},
"full_screen_view_description": "<0>Отправка журналов поможет нам найти и устранить проблему.</0>",
"full_screen_view_h1": "<0>Упс, что-то пошло не так.</0>",
"header_label": "Главная Element Call",
"join_existing_call_modal": {
"join_button": "Да, присоединиться",
@@ -69,12 +63,8 @@
"register_auth_links": "<0>Уже есть аккаунт?</0><1><0>Войти с ним</0> или <2>Зайти как гость</2></1>",
"register_confirm_password_label": "Подтвердите пароль",
"return_home_button": "Вернуться в Начало",
"room_auth_view_join_button": "Присоединиться сейчас",
"screenshare_button_label": "Поделиться экраном",
"select_input_unset_button": "Выберите вариант",
"settings": {
"developer_settings_label": "Настройки Разработчика",
"developer_settings_label_description": "Раскрыть настройки разработчика в окне настроек.",
"developer_tab_title": "Разработчику",
"feedback_tab_body": "Если у вас возникли проблемы или вы просто хотите оставить отзыв, отправьте нам краткое описание ниже.",
"feedback_tab_description_label": "Ваш отзыв",
@@ -82,16 +72,12 @@
"feedback_tab_send_logs_label": "Приложить журнал отладки",
"feedback_tab_thank_you": "Спасибо. Мы получили ваш отзыв!",
"feedback_tab_title": "Отзыв",
"more_tab_title": "Больше",
"opt_in_description": "<0></0><1></1>Вы можете отозвать согласие, сняв этот флажок. Если вы в данный момент находитесь в разговоре, эта настройка вступит в силу по окончании разговора.",
"show_connection_stats_label": "Показать статистику соединения",
"speaker_device_selection_label": "Динамик"
"opt_in_description": "<0></0><1></1>Вы можете отозвать согласие, сняв этот флажок. Если вы в данный момент находитесь в разговоре, эта настройка вступит в силу по окончании разговора."
},
"star_rating_input_label_one": "{{count}} отмечен",
"star_rating_input_label_other": "{{count}} отмеченных",
"submitting": "Отправляем…",
"unauthenticated_view_body": "Ещё не зарегистрированы? <2>Создайте аккаунт</2>",
"unauthenticated_view_login_button": "Войдите в свой аккаунт",
"version": "Версия: {{version}}",
"waiting_for_participants": "Ожидание других участников…"
"version": "Версия: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Zatvoriť",
"copy": "Kopírovať",
"copy_link": "Kopírovať odkaz",
"go": "Prejsť",
"invite": "Pozvať",
@@ -15,16 +14,14 @@
"sign_out": "Odhlásiť sa",
"submit": "Odoslať"
},
"analytics_notice": "Účasťou v tejto beta verzii súhlasíte so zhromažďovaním anonymných údajov, ktoré použijeme na zlepšenie produktu. Viac informácií o tom, ktoré údaje sledujeme, nájdete v našich <2>Zásadách ochrany osobných údajov</2> a <6>Zásadách používania súborov cookie</6>.",
"analytics_notice": "Účasťou v tejto beta verzii súhlasíte so zhromažďovaním anonymných údajov, ktoré použijeme na zlepšenie produktu. Viac informácií o tom, ktoré údaje sledujeme, nájdete v našich <2>Zásadách ochrany osobných údajov</2> a <5>Zásadách používania súborov cookie</5>.",
"app_selection_modal": {
"continue_in_browser": "Pokračovať v prehliadači",
"open_in_app": "Otvoriť v aplikácii",
"text": "Ste pripravení sa pridať?",
"title": "Vybrať aplikáciu"
},
"browser_media_e2ee_unsupported": "Váš webový prehliadač nepodporuje end-to-end šifrovanie médií. Podporované prehliadače sú Chrome, Safari, Firefox >=117",
"call_ended_view": {
"body": "Boli ste odpojení z hovoru",
"create_account_button": "Vytvoriť účet",
"create_account_prompt": "<0>Prečo neskončiť nastavením hesla, aby ste si zachovali svoj účet? </0><1>Budete si môcť ponechať svoje meno a nastaviť obrázok, ktorý sa bude používať pri budúcich hovoroch</1>",
"feedback_done": "<0> Ďakujeme za vašu spätnú väzbu!</0>",
@@ -37,13 +34,10 @@
"call_name": "Názov hovoru",
"common": {
"avatar": "Obrázok",
"camera": "Kamera",
"copied": "Skopírované!",
"display_name": "Zobrazované meno",
"encrypted": "Šifrované",
"home": "Domov",
"loading": "Načítanie…",
"microphone": "Mikrofón",
"password": "Heslo",
"profile": "Profil",
"settings": "Nastavenia",
@@ -51,8 +45,6 @@
"username": "Meno používateľa"
},
"disconnected_banner": "Spojenie so serverom sa stratilo.",
"full_screen_view_description": "<0>Odoslanie záznamov ladenia nám pomôže nájsť problém.</0>",
"full_screen_view_h1": "<0>Hups, niečo sa pokazilo.</0>",
"hangup_button_label": "Ukončiť hovor",
"header_label": "Domov Element Call",
"header_participants_label": "Účastníci",
@@ -97,12 +89,8 @@
"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>",
"room_auth_view_join_button": "Pripojiť sa k hovoru teraz",
"screenshare_button_label": "Zdieľať obrazovku",
"select_input_unset_button": "Vyberte možnosť",
"settings": {
"developer_settings_label": "Nastavenia pre vývojárov",
"developer_settings_label_description": "Zobraziť nastavenia pre vývojárov v okne nastavení.",
"developer_tab_title": "Vývojár",
"feedback_tab_body": "Ak máte problémy alebo jednoducho chcete poskytnúť spätnú väzbu, pošlite nám krátky popis nižšie.",
"feedback_tab_description_label": "Vaša spätná väzba",
@@ -110,10 +98,7 @@
"feedback_tab_send_logs_label": "Zahrnúť záznamy o ladení",
"feedback_tab_thank_you": "Ďakujeme, dostali sme vašu spätnú väzbu!",
"feedback_tab_title": "Spätná väzba",
"more_tab_title": "Viac",
"opt_in_description": "<0></0><1></1>Súhlas môžete odvolať zrušením označenia tohto políčka. Ak práve prebieha hovor, toto nastavenie nadobudne platnosť po skončení hovoru.",
"show_connection_stats_label": "Zobraziť štatistiky pripojenia",
"speaker_device_selection_label": "Reproduktor"
"opt_in_description": "<0></0><1></1>Súhlas môžete odvolať zrušením označenia tohto políčka. Ak práve prebieha hovor, toto nastavenie nadobudne platnosť po skončení hovoru."
},
"star_rating_input_label_one": "{{count}} hviezdička",
"star_rating_input_label_other": "{{count}} hviezdičiek",
@@ -126,9 +111,5 @@
"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}}",
"video_tile": {
"sfu_participant_local": "Vy"
},
"waiting_for_participants": "Čaká sa na ďalších účastníkov…"
"version": "Verzia: {{version}}"
}

View File

@@ -15,12 +15,9 @@
},
"common": {
"audio": "Ses",
"camera": "Kamera",
"copied": "Kopyalandı",
"display_name": "Ekran adı",
"home": "Ev",
"loading": "Yükleniyor…",
"microphone": "Mikrofon",
"password": "Parola",
"settings": "Ayarlar"
},
@@ -49,14 +46,11 @@
"register_auth_links": "<0>Mevcut hesabınız mı var?</0><1><0>Gir</0> yahut <2>Konuk girişi</2></1>",
"register_confirm_password_label": "Parolayı tekrar edin",
"return_home_button": "Ev ekranına geri dön",
"room_auth_view_join_button": "Aramaya katıl",
"screenshare_button_label": "Ekran paylaş",
"select_input_unset_button": "Bir seçenek seç",
"settings": {
"developer_tab_title": "Geliştirici",
"feedback_tab_h4": "Geri bildirim ver",
"feedback_tab_send_logs_label": "Hata ayıklama kütüğünü dahil et",
"more_tab_title": "Daha"
"feedback_tab_send_logs_label": "Hata ayıklama kütüğünü dahil et"
},
"unauthenticated_view_body": "Kaydolmadınız mı? <2>Hesap açın</2>",
"unauthenticated_view_login_button": "Hesabınıza girin"

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "Закрити",
"copy": "Копіювати",
"copy_link": "Скопіювати посилання",
"go": "Далі",
"invite": "Запросити",
@@ -15,16 +14,14 @@
"sign_out": "Вийти",
"submit": "Надіслати"
},
"analytics_notice": "Користуючись дочасним доступом, ви даєте згоду на збір анонімних даних, які ми використовуємо для вдосконалення продукту. Ви можете знайти більше інформації про те, які дані ми відстежуємо в нашій <2>Політиці Приватності</2> і нашій <6>Політиці про куки</6>.",
"analytics_notice": "Користуючись дочасним доступом, ви даєте згоду на збір анонімних даних, які ми використовуємо для вдосконалення продукту. Ви можете знайти більше інформації про те, які дані ми відстежуємо в нашій <2>Політиці Приватності</2> і нашій <5>Політиці про куки</5>.",
"app_selection_modal": {
"continue_in_browser": "Продовжити у браузері",
"open_in_app": "Відкрити у застосунку",
"text": "Готові приєднатися?",
"title": "Вибрати застосунок"
},
"browser_media_e2ee_unsupported": "Ваш браузер не підтримує наскрізне шифрування мультимедійних даних. Підтримувані браузери: Chrome, Safari, Firefox >=117",
"call_ended_view": {
"body": "Вас від'єднано від виклику",
"create_account_button": "Створити обліковий запис",
"create_account_prompt": "<0>Чому б не завершити, налаштувавши пароль для збереження свого облікового запису?</0><1>Ви зможете зберегти своє ім'я та встановити аватарку для подальшого користування під час майбутніх викликів</1>",
"feedback_done": "<0>Дякуємо за ваш відгук!</0>",
@@ -38,13 +35,10 @@
"common": {
"audio": "Звук",
"avatar": "Аватар",
"camera": "Камера",
"copied": "Скопійовано!",
"display_name": "Псевдонім",
"encrypted": "Зашифровано",
"home": "Домівка",
"loading": "Завантаження…",
"microphone": "Мікрофон",
"password": "Пароль",
"profile": "Профіль",
"settings": "Налаштування",
@@ -53,8 +47,6 @@
"video": "Відео"
},
"disconnected_banner": "Втрачено зв'язок з сервером.",
"full_screen_view_description": "<0>Надсилання журналів налагодження допоможе нам виявити проблему.</0>",
"full_screen_view_h1": "<0>Йой, щось пішло не за планом.</0>",
"hangup_button_label": "Завершити виклик",
"header_label": "Домівка Element Call",
"header_participants_label": "Учасники",
@@ -99,12 +91,8 @@
"register_confirm_password_label": "Підтвердити пароль",
"return_home_button": "Повернутися на екран домівки",
"room_auth_view_eula_caption": "Натискаючи \"Приєднатися до виклику зараз\", ви погоджуєтеся з нашою <2>Ліцензійною угодою з кінцевим користувачем (EULA)</2>",
"room_auth_view_join_button": "Приєднатися до виклику зараз",
"screenshare_button_label": "Поділитися екраном",
"select_input_unset_button": "Вибрати опцію",
"settings": {
"developer_settings_label": "Налаштування розробника",
"developer_settings_label_description": "Відкрийте налаштування розробника у вікні налаштувань.",
"developer_tab_title": "Розробнику",
"feedback_tab_body": "Якщо у вас виникли проблеми або ви просто хочете залишити відгук, надішліть нам короткий опис нижче.",
"feedback_tab_description_label": "Ваш відгук",
@@ -112,10 +100,7 @@
"feedback_tab_send_logs_label": "Долучити журнали налагодження",
"feedback_tab_thank_you": "Дякуємо, ми отримали ваш відгук!",
"feedback_tab_title": "Відгук",
"more_tab_title": "Докладніше",
"opt_in_description": "<0></0><1></1>Ви можете відкликати згоду, прибравши цей прапорець. Якщо ви зараз розмовляєте, це налаштування застосується після завершення виклику.",
"show_connection_stats_label": "Показати стан з'єднання",
"speaker_device_selection_label": "Динамік"
"opt_in_description": "<0></0><1></1>Ви можете відкликати згоду, прибравши цей прапорець. Якщо ви зараз розмовляєте, це налаштування застосується після завершення виклику."
},
"star_rating_input_label_one": "{{count}} зірок",
"star_rating_input_label_other": "{{count}} зірок",
@@ -128,9 +113,5 @@
"unauthenticated_view_eula_caption": "Натискаючи \"Далі\", ви погоджуєтеся з нашою <2>Ліцензійною угодою з кінцевим користувачем (EULA)</2>",
"unauthenticated_view_login_button": "Увійдіть до свого облікового запису",
"unmute_microphone_button_label": "Увімкнути мікрофон",
"version": "Версія: {{version}}",
"video_tile": {
"sfu_participant_local": "Ви"
},
"waiting_for_participants": "Очікування на інших учасників…"
"version": "Версія: {{version}}"
}

View File

@@ -1,7 +1,6 @@
{
"action": {
"close": "Đóng",
"copy": "Sao chép",
"no": "Không",
"register": "Đăng ký",
"sign_in": "Đăng nhập",
@@ -18,19 +17,14 @@
"common": {
"audio": "Âm thanh",
"avatar": "Ảnh đại diện",
"camera": "Máy quay",
"copied": "Đã sao chép!",
"display_name": "Tên hiển thị",
"loading": "Đang tải…",
"microphone": "Micrô",
"password": "Mật khẩu",
"profile": "Hồ sơ",
"settings": "Cài đặt",
"username": "Tên người dùng",
"video": "Truyền hình"
},
"full_screen_view_description": "<0>Gửi nhật ký gỡ lỗi sẽ giúp chúng tôi theo dõi vấn đề.</0>",
"full_screen_view_h1": "<0>Ối, có cái gì đó sai.</0>",
"join_existing_call_modal": {
"join_button": "Vâng, tham gia cuộc gọi",
"text": "Cuộc gọi đã tồn tại, bạn có muốn tham gia không?",
@@ -55,21 +49,17 @@
},
"register_auth_links": "<0>Đã có tài khoản?</0><1><0>Đăng nhập</0> Hay <2>Tham gia dưới tên Khách</2></1>",
"register_confirm_password_label": "Xác nhận mật khẩu",
"room_auth_view_join_button": "Tham gia cuộc gọi",
"screenshare_button_label": "Chia sẻ màn hình",
"settings": {
"developer_settings_label": "Cài đặt phát triển",
"developer_tab_title": "Nhà phát triển",
"feedback_tab_description_label": "Phản hồi của bạn",
"feedback_tab_h4": "Gửi phản hồi",
"feedback_tab_send_logs_label": "Kèm theo nhật ký gỡ lỗi",
"feedback_tab_thank_you": "Cảm ơn, chúng tôi đã nhận được phản hồi!",
"feedback_tab_title": "Phản hồi",
"speaker_device_selection_label": "Loa"
"feedback_tab_title": "Phản hồi"
},
"submitting": "Đang gửi…",
"unauthenticated_view_body": "Chưa đăng ký? <2>Tạo tài khoản</2>",
"unauthenticated_view_login_button": "Đăng nhập vào tài khoản của bạn",
"version": "Phiên bản: {{version}}",
"waiting_for_participants": "Đang đợi những người khác…"
"version": "Phiên bản: {{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "关闭",
"copy": "复制",
"go": "开始",
"no": "否",
"register": "注册",
@@ -13,16 +12,14 @@
"sign_out": "登出",
"submit": "提交"
},
"analytics_notice": "参与测试即表示您同意我们收集匿名数据,用于改进产品。您可以在我们的<2>隐私政策</2>和<6>Cookie政策</6>中找到有关我们跟踪哪些数据以及更多信息。",
"analytics_notice": "参与测试即表示您同意我们收集匿名数据,用于改进产品。您可以在我们的<2>隐私政策</2>和<5>Cookie政策</5>中找到有关我们跟踪哪些数据以及更多信息。",
"app_selection_modal": {
"continue_in_browser": "在浏览器中继续",
"open_in_app": "在应用中打开",
"text": "准备好加入了吗?",
"title": "选择应用程序"
},
"browser_media_e2ee_unsupported": "您的浏览器不支持媒体端对端加密。支持的浏览器有 Chrome、Safari、Firefox >=117",
"call_ended_view": {
"body": "通话已中断",
"create_account_button": "创建账户",
"create_account_prompt": "<0>为何不设置密码来保留你的账户?</0><1>保留昵称并设置头像,以便在未来的通话中使用。</1>",
"feedback_done": "<0>感谢反馈!</0>",
@@ -36,13 +33,10 @@
"common": {
"audio": "音频",
"avatar": "头像",
"camera": "摄像头",
"copied": "已复制!",
"display_name": "显示名称",
"encrypted": "已加密",
"home": "主页",
"loading": "加载中……",
"microphone": "麦克风",
"password": "密码",
"profile": "个人信息",
"settings": "设置",
@@ -51,8 +45,6 @@
"video": "视频"
},
"disconnected_banner": "与服务器的连接中断。",
"full_screen_view_description": "<0>提交日志以帮助我们修复问题。</0>",
"full_screen_view_h1": "<0>哎哟,出问题了。</0>",
"hangup_button_label": "通话结束",
"header_label": "Element Call主页",
"join_existing_call_modal": {
@@ -92,12 +84,8 @@
"register_confirm_password_label": "确认密码",
"return_home_button": "返回主页",
"room_auth_view_eula_caption": "点击 \"加入通话\",即表示您同意我们的<2>最终用户许可协议 (EULA)</2>",
"room_auth_view_join_button": "现在加入通话",
"screenshare_button_label": "屏幕共享",
"select_input_unset_button": "选择一个选项",
"settings": {
"developer_settings_label": "开发者设置",
"developer_settings_label_description": "在设置中显示开发者设置。",
"developer_tab_title": "开发者",
"feedback_tab_body": "如果遇到问题或想提供一些反馈意见,请在下面向我们发送简短描述。",
"feedback_tab_description_label": "您的反馈",
@@ -105,10 +93,7 @@
"feedback_tab_send_logs_label": "包含调试日志",
"feedback_tab_thank_you": "谢谢,我们收到了反馈!",
"feedback_tab_title": "反馈",
"more_tab_title": "更多",
"opt_in_description": "<0></0><1></1>您可以取消选中复选框来撤回同意。如果正在通话中,此设置将在通话结束时生效。",
"show_connection_stats_label": "显示连接统计信息",
"speaker_device_selection_label": "发言人"
"opt_in_description": "<0></0><1></1>您可以取消选中复选框来撤回同意。如果正在通话中,此设置将在通话结束时生效。"
},
"star_rating_input_label_one": "{{count}} 个星",
"star_rating_input_label_other": "{{count}} 个星",
@@ -121,9 +106,5 @@
"unauthenticated_view_eula_caption": "点击 \"开始\",即表示您同意我们的<2>最终用户许可协议 (EULA)</2>",
"unauthenticated_view_login_button": "登录你的账户",
"unmute_microphone_button_label": "取消麦克风静音",
"version": "版本:{{version}}",
"video_tile": {
"sfu_participant_local": "你"
},
"waiting_for_participants": "等待其他参与者……"
"version": "版本:{{version}}"
}

View File

@@ -4,7 +4,6 @@
},
"action": {
"close": "關閉",
"copy": "複製",
"copy_link": "複製連結",
"go": "前往",
"invite": "邀請",
@@ -15,16 +14,14 @@
"sign_out": "登出",
"submit": "遞交"
},
"analytics_notice": "參與此測試版即表示您同意蒐集匿名資料,我們使用這些資料來改進產品。您可以在我們的<2>隱私政策</2>與我們的 <6>Cookie 政策</6> 中找到關於我們追蹤哪些資料的更多資訊。",
"analytics_notice": "參與此測試版即表示您同意蒐集匿名資料,我們使用這些資料來改進產品。您可以在我們的<2>隱私政策</2>與我們的 <5>Cookie 政策</5> 中找到關於我們追蹤哪些資料的更多資訊。",
"app_selection_modal": {
"continue_in_browser": "在瀏覽器中繼續",
"open_in_app": "在應用程式中開啟",
"text": "準備好加入了?",
"title": "選取應用程式"
},
"browser_media_e2ee_unsupported": "您的網路瀏覽器不支援媒體端到端加密。支援的瀏覽器包含了 Chrome、Safari、Firefox >=117",
"call_ended_view": {
"body": "您已從通話斷線",
"create_account_button": "建立帳號",
"create_account_prompt": "<0>何不設定密碼以保留此帳號?</0><1>您可以保留暱稱並設定頭像,以便未來通話時使用</1>",
"feedback_done": "<0>感謝您的回饋!</0>",
@@ -38,13 +35,10 @@
"common": {
"audio": "語音",
"avatar": "大頭照",
"camera": "相機",
"copied": "已複製!",
"display_name": "顯示名稱",
"encrypted": "已加密",
"home": "首頁",
"loading": "載入中…",
"microphone": "麥克風",
"password": "密碼",
"profile": "個人檔案",
"settings": "設定",
@@ -53,8 +47,6 @@
"video": "視訊"
},
"disconnected_banner": "到伺服器的連線已遺失。",
"full_screen_view_description": "<0>送出除錯紀錄,可幫助我們修正問題。</0>",
"full_screen_view_h1": "<0>喔喔,有些地方怪怪的。</0>",
"hangup_button_label": "結束通話",
"header_label": "Element Call 首頁",
"header_participants_label": "參與者",
@@ -99,12 +91,8 @@
"register_confirm_password_label": "確認密碼",
"return_home_button": "回到首頁",
"room_auth_view_eula_caption": "點擊「立刻加入通話」即表示您同意我們的<2>終端使用者授權協議 (EULA)</2>",
"room_auth_view_join_button": "現在加入通話",
"screenshare_button_label": "分享畫面",
"select_input_unset_button": "選擇一個選項",
"settings": {
"developer_settings_label": "開發者設定",
"developer_settings_label_description": "在設定視窗中顯示開發者設定。",
"developer_tab_title": "開發者",
"feedback_tab_body": "若您遇到問題或只是想提供一些回饋,請在下方傳送簡短說明給我們。",
"feedback_tab_description_label": "您的回饋",
@@ -112,10 +100,7 @@
"feedback_tab_send_logs_label": "包含除錯紀錄",
"feedback_tab_thank_you": "感謝,我們已經收到您的回饋了!",
"feedback_tab_title": "回饋",
"more_tab_title": "更多",
"opt_in_description": "<0></0><1></1>您可以透過取消核取此方塊來撤回同意。若您目前正在通話中,此設定將在通話結束時生效。",
"show_connection_stats_label": "顯示連線統計資料",
"speaker_device_selection_label": "發言者"
"opt_in_description": "<0></0><1></1>您可以透過取消核取此方塊來撤回同意。若您目前正在通話中,此設定將在通話結束時生效。"
},
"star_rating_input_label_one": "{{count}} 個星星",
"star_rating_input_label_other": "{{count}} 個星星",
@@ -128,9 +113,5 @@
"unauthenticated_view_eula_caption": "點擊「前往」即表示您同意我們的<2>終端使用者授權協議 (EULA)</2>",
"unauthenticated_view_login_button": "登入您的帳號",
"unmute_microphone_button_label": "將麥克風取消靜音",
"version": "版本: {{version}}",
"video_tile": {
"sfu_participant_local": "您"
},
"waiting_for_participants": "等待其他參加者…"
"version": "版本: {{version}}"
}

View File

@@ -3,8 +3,12 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "NODE_OPTIONS=--max-old-space-size=16384 vite build",
"dev": "yarn dev:full",
"dev:full": "vite",
"dev:embedded": "vite --config vite-embedded.config.js",
"build": "yarn build:full",
"build:full": "NODE_OPTIONS=--max-old-space-size=16384 vite build",
"build:embedded": "yarn build:full --config vite-embedded.config.js",
"serve": "vite preview",
"prettier:check": "prettier -c .",
"prettier:format": "prettier -w .",
@@ -17,75 +21,85 @@
"i18n:check": "i18next --fail-on-warnings --fail-on-update",
"test": "vitest",
"test:coverage": "vitest --coverage",
"backend": "docker-compose -f backend-docker-compose.yml up"
"backend": "docker-compose -f dev-backend-docker-compose.yml up",
"test:playwright": "playwright test",
"test:playwright:open": "yarn test:playwright --ui"
},
"devDependencies": {
"@babel/core": "^7.16.5",
"@babel/preset-env": "^7.22.20",
"@babel/preset-react": "^7.22.15",
"@babel/preset-typescript": "^7.23.0",
"@livekit/components-core": "^0.11.0",
"@codecov/vite-plugin": "^1.3.0",
"@fontsource/inconsolata": "^5.1.0",
"@fontsource/inter": "^5.1.0",
"@formatjs/intl-durationformat": "^0.7.0",
"@formatjs/intl-segmenter": "^11.7.3",
"@livekit/components-core": "^0.12.0",
"@livekit/components-react": "^2.0.0",
"@livekit/protocol": "^1.33.0",
"@opentelemetry/api": "^1.4.0",
"@opentelemetry/core": "^1.25.1",
"@opentelemetry/exporter-trace-otlp-http": "^0.54.0",
"@opentelemetry/exporter-trace-otlp-http": "^0.57.0",
"@opentelemetry/resources": "^1.25.1",
"@opentelemetry/sdk-trace-base": "^1.25.1",
"@opentelemetry/sdk-trace-web": "^1.9.1",
"@opentelemetry/semantic-conventions": "^1.25.1",
"@playwright/test": "^1.51.0",
"@radix-ui/react-dialog": "^1.0.4",
"@radix-ui/react-slider": "^1.1.2",
"@radix-ui/react-visually-hidden": "^1.0.3",
"@react-spring/web": "^9.4.4",
"@sentry/react": "^8.0.0",
"@sentry/vite-plugin": "^2.0.0",
"@sentry/vite-plugin": "^3.0.0",
"@stylistic/eslint-plugin": "^3.0.0",
"@testing-library/dom": "^10.1.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.0.0",
"@testing-library/react-hooks": "^8.0.1",
"@testing-library/user-event": "^14.5.1",
"@types/content-type": "^1.1.5",
"@types/grecaptcha": "^3.0.9",
"@types/jsdom": "^21.1.7",
"@types/lodash": "^4.14.199",
"@types/node": "^20.0.0",
"@types/lodash-es": "^4.17.12",
"@types/node": "^22.0.0",
"@types/pako": "^2.0.3",
"@types/qrcode": "^1.5.5",
"@types/react": "^18.3.0",
"@types/react-dom": "^18.3.0",
"@types/react-router-dom": "^5.3.3",
"@types/sdp-transform": "^2.4.5",
"@types/uuid": "10",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"@use-gesture/react": "^10.2.11",
"@vector-im/compound-design-tokens": "^1.0.0",
"@vector-im/compound-web": "^6.0.0",
"@vector-im/compound-design-tokens": "^3.0.0",
"@vector-im/compound-web": "^7.2.0",
"@vitejs/plugin-basic-ssl": "^1.0.1",
"@vitejs/plugin-react": "^4.0.1",
"@vitest/coverage-v8": "^2.0.5",
"@vitest/coverage-v8": "^3.0.0",
"babel-plugin-transform-vite-meta-env": "^1.0.3",
"classnames": "^2.3.1",
"eslint": "^8.14.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^9.0.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-deprecate": "^0.8.2",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-matrix-org": "^1.2.1",
"eslint-plugin-matrix-org": "^2.0.0",
"eslint-plugin-react": "^7.29.4",
"eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-rxjs": "^5.0.3",
"eslint-plugin-unicorn": "^56.0.0",
"global-jsdom": "^25.0.0",
"history": "^4.0.0",
"i18next": "^23.0.0",
"global-jsdom": "^26.0.0",
"i18next": "^24.0.0",
"i18next-browser-languagedetector": "^8.0.0",
"i18next-http-backend": "^2.0.0",
"i18next-parser": "^9.0.0",
"jsdom": "^25.0.0",
"i18next-parser": "^9.1.0",
"jsdom": "^26.0.0",
"knip": "^5.27.2",
"livekit-client": "^2.5.7",
"lodash": "^4.17.21",
"livekit-client": "2.9.1",
"lodash-es": "^4.17.21",
"loglevel": "^1.9.1",
"matrix-js-sdk": "matrix-org/matrix-js-sdk#0a29063bc9e61ee70ca43820d4bb91f6a27f1237",
"matrix-widget-api": "^1.8.2",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#8395919f0fd1af7cab1e793d736f2cdf18ef7686",
"matrix-widget-api": "1.11.0",
"normalize.css": "^8.0.1",
"observable-hooks": "^4.2.3",
"pako": "^2.0.4",
@@ -97,7 +111,7 @@
"react": "18",
"react-dom": "18",
"react-i18next": "^15.0.0",
"react-router-dom": "^5.2.0",
"react-router-dom": "^7.0.0",
"react-use-clipboard": "^1.0.7",
"react-use-measure": "^2.1.1",
"rxjs": "^7.8.1",
@@ -105,14 +119,16 @@
"typescript": "^5.1.6",
"typescript-eslint-language-service": "^5.0.5",
"unique-names-generator": "^4.6.0",
"vaul": "^0.9.0",
"vite": "^5.0.0",
"vite-plugin-html-template": "^1.1.0",
"vaul": "^1.0.0",
"vite": "^6.0.0",
"vite-plugin-generate-file": "^0.2.0",
"vite-plugin-html": "^3.2.2",
"vite-plugin-svgr": "^4.0.0",
"vitest": "^2.0.0",
"vitest": "^3.0.0",
"vitest-axe": "^1.0.0-pre.3"
},
"resolutions": {
"strip-ansi": "6.0.1"
"@livekit/components-core/rxjs": "^7.8.1",
"matrix-widget-api": "1.11.0"
}
}

View File

@@ -0,0 +1,86 @@
networks:
ecbackend:
services:
auth-service:
image: ghcr.io/element-hq/lk-jwt-service:latest-ci
hostname: auth-server
environment:
- LK_JWT_PORT=8080
- LIVEKIT_URL=ws://localhost:7880
- LIVEKIT_KEY=devkey
- LIVEKIT_SECRET=secret
# If the configured homeserver runs on localhost, it'll probably be using
# a self-signed certificate
- LIVEKIT_INSECURE_SKIP_VERIFY_TLS=YES_I_KNOW_WHAT_I_AM_DOING
deploy:
restart_policy:
condition: on-failure
ports:
# HOST_PORT:CONTAINER_PORT
- 8009:8080
networks:
- ecbackend
livekit:
image: livekit/livekit-server:latest
command: --dev --config /etc/livekit.yaml
restart: unless-stopped
# The SFU seems to work far more reliably when we let it share the host
# network rather than opening specific ports (but why?? we're not missing
# any…)
ports:
# HOST_PORT:CONTAINER_PORT
- 7880:7880/tcp
- 7881:7881/tcp
- 7882:7882/tcp
- 50100-50200:50100-50200/udp
volumes:
- ./backend/dev_livekit.yaml:/etc/livekit.yaml:Z
networks:
- ecbackend
redis:
image: redis:6-alpine
command: redis-server /etc/redis.conf
ports:
# HOST_PORT:CONTAINER_PORT
- 6379:6379
volumes:
- ./backend/redis.conf:/etc/redis.conf:Z
networks:
- ecbackend
synapse:
hostname: homeserver
image: docker.io/matrixdotorg/synapse:latest
environment:
- SYNAPSE_CONFIG_PATH=/data/cfg/homeserver.yaml
# Needed for rootless podman-compose such that the uid/gid mapping does
# fit local user uid. If the container runs as root (uid 0) it is fine as
# it actually maps to your non-root user on the host (e.g. 1000).
# Otherwise uid mapping will not match your non-root user.
- UID=0
- GID=0
volumes:
- ./backend/synapse_tmp:/data:Z
- ./backend/playwright_homeserver.yaml:/data/cfg/homeserver.yaml:Z
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
image: nginx:latest
volumes:
- ./backend/tls_localhost_nginx.conf:/etc/nginx/conf.d/default.conf:Z
- ./backend/tls_localhost_key.pem:/root/ssl/key.pem:Z
- ./backend/tls_localhost_cert.pem:/root/ssl/cert.pem:Z
ports:
# HOST_PORT:CONTAINER_PORT
- "8008:80"
- "4443:443"
depends_on:
- synapse
networks:
- ecbackend

81
playwright.config.ts Normal file
View File

@@ -0,0 +1,81 @@
/*
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 { defineConfig, devices } from "@playwright/test";
/**
* See https://playwright.dev/docs/test-configuration.
*/
export default defineConfig({
testDir: "./playwright",
/* Run tests in files in parallel */
fullyParallel: true,
/* Fail the build on CI if you accidentally left test.only in the source code. */
forbidOnly: !!process.env.CI,
/* Retry on CI only */
retries: process.env.CI ? 2 : 0,
/* Opt out of parallel tests on CI. */
workers: process.env.CI ? 1 : undefined,
/* Reporter to use. See https://playwright.dev/docs/test-reporters */
reporter: "html",
/* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
use: {
/* Base URL to use in actions like `await page.goto('/')`. */
baseURL: "https://localhost:3000",
/* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
trace: "on-first-retry",
},
/* Configure projects for major browsers */
projects: [
{
name: "chromium",
use: {
...devices["Desktop Chrome"],
permissions: [
"clipboard-write",
"clipboard-read",
"microphone",
"camera",
],
ignoreHTTPSErrors: true,
launchOptions: {
args: [
"--use-fake-ui-for-media-stream",
"--use-fake-device-for-media-stream",
"--mute-audio",
],
},
},
},
{
name: "firefox",
use: {
...devices["Desktop Firefox"],
ignoreHTTPSErrors: true,
launchOptions: {
firefoxUserPrefs: {
"permissions.default.microphone": 1,
"permissions.default.camera": 1,
},
},
},
},
// No safari for now, until I find a solution to fix `Not allowed to request resource` due to calling
// clear http to the homeserver
],
/* Run your local dev server before starting the tests */
webServer: {
command: "yarn dev",
url: "https://localhost:3000",
reuseExistingServer: !process.env.CI,
ignoreHTTPSErrors: true,
},
});

131
playwright/access.spec.ts Normal file
View File

@@ -0,0 +1,131 @@
/*
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";
test("Sign up a new account, then login, then logout", async ({ browser }) => {
const userId = `test_user-id_${Date.now()}`;
const newUserContext = await browser.newContext();
const newUserPage = await newUserContext.newPage();
await newUserPage.goto("/");
await expect(newUserPage.getByTestId("home_register")).toBeVisible();
await newUserPage.getByTestId("home_register").click();
await newUserPage.getByTestId("register_username").click();
await newUserPage.getByTestId("register_username").fill(userId);
await newUserPage.getByTestId("register_password").click();
await newUserPage.getByTestId("register_password").fill("password1!");
await newUserPage.getByTestId("register_confirm_password").click();
await newUserPage.getByTestId("register_confirm_password").fill("password1!");
await newUserPage.getByTestId("register_register").click();
await expect(
newUserPage.getByRole("heading", { name: "Start new call" }),
).toBeVisible();
// Now use a new page to login this account
const returningUserContext = await browser.newContext();
const returningUserPage = await returningUserContext.newPage();
await returningUserPage.goto("/");
await expect(returningUserPage.getByTestId("home_login")).toBeVisible();
await returningUserPage.getByTestId("home_login").click();
await returningUserPage.getByTestId("login_username").click();
await returningUserPage.getByTestId("login_username").fill(userId);
await returningUserPage.getByTestId("login_password").click();
await returningUserPage.getByTestId("login_password").fill("password1!");
await returningUserPage.getByTestId("login_login").click();
await expect(
returningUserPage.getByRole("heading", { name: "Start new call" }),
).toBeVisible();
// logout
await returningUserPage.getByTestId("usermenu_open").click();
await returningUserPage.locator('[data-test-id="usermenu_logout"]').click();
await expect(
returningUserPage.getByRole("link", { name: "Log In" }),
).toBeVisible();
await expect(returningUserPage.getByTestId("home_login")).toBeVisible();
});
test("As a guest, create a call, share link and other join", async ({
browser,
}) => {
// Use reduce motion to disable animations that are making the tests a bit flaky
const creatorContext = await browser.newContext({ reducedMotion: "reduce" });
const creatorPage = await creatorContext.newPage();
await creatorPage.goto("/");
// ========
// ARRANGE: The first user creates a call as guest, join it, then click the invite button to copy the invite link
// ========
await creatorPage.getByTestId("home_callName").click();
await creatorPage.getByTestId("home_callName").fill("Welcome");
await creatorPage.getByTestId("home_displayName").click();
await creatorPage.getByTestId("home_displayName").fill("Inviter");
await creatorPage.getByTestId("home_go").click();
await expect(creatorPage.locator("video")).toBeVisible();
// join
await creatorPage.getByTestId("lobby_joinCall").click();
// Spotlight mode to make checking the test visually clearer
await creatorPage.getByRole("radio", { name: "Spotlight" }).check();
// Get the invite link
await creatorPage.getByRole("button", { name: "Invite" }).click();
await expect(
creatorPage.getByRole("heading", { name: "Invite to this call" }),
).toBeVisible();
await expect(creatorPage.getByRole("img", { name: "QR Code" })).toBeVisible();
await expect(creatorPage.getByTestId("modal_inviteLink")).toBeVisible();
await expect(creatorPage.getByTestId("modal_inviteLink")).toBeVisible();
await creatorPage.getByTestId("modal_inviteLink").click();
let inviteLink = (await creatorPage.evaluate(
"navigator.clipboard.readText()",
)) as string;
expect(inviteLink).toContain("room/#/");
// ========
// ACT: The other user use the invite link to join the call as a guest
// ========
const guestInviteeContext = await browser.newContext({
reducedMotion: "reduce",
});
const guestPage = await guestInviteeContext.newPage();
await guestPage.goto(inviteLink);
await guestPage.getByTestId("joincall_displayName").fill("Invitee");
await expect(guestPage.getByTestId("joincall_joincall")).toBeVisible();
await guestPage.getByTestId("joincall_joincall").click();
await guestPage.getByTestId("lobby_joinCall").click();
await guestPage.getByRole("radio", { name: "Spotlight" }).check();
// ========
// ASSERT: check that there are two members in the call
// ========
// There should be two participants now
await expect(
guestPage.getByTestId("roomHeader_participants_count"),
).toContainText("2");
expect(await guestPage.getByTestId("videoTile").count()).toBe(2);
// Same in creator page
await expect(
creatorPage.getByTestId("roomHeader_participants_count"),
).toContainText("2");
expect(await creatorPage.getByTestId("videoTile").count()).toBe(2);
// XXX check the display names on the video tiles
});

View File

@@ -0,0 +1,55 @@
/*
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";
test("Start a new call then leave and show the feedback screen", async ({
page,
}) => {
await page.goto("/");
await page.getByTestId("home_callName").click();
await page.getByTestId("home_callName").fill("HelloCall");
await page.getByTestId("home_displayName").click();
await page.getByTestId("home_displayName").fill("John Doe");
await page.getByTestId("home_go").click();
await expect(page.locator("video")).toBeVisible();
await expect(page.getByTestId("lobby_joinCall")).toBeVisible();
// Check the button toolbar
// await expect(page.getByRole('button', { name: 'Mute microphone' })).toBeVisible();
// await expect(page.getByRole('button', { name: 'Stop video' })).toBeVisible();
await expect(page.getByRole("button", { name: "Settings" })).toBeVisible();
await expect(page.getByRole("button", { name: "End call" })).toBeVisible();
// Join the call
await page.getByTestId("lobby_joinCall").click();
// Ensure that the call is connected
await page
.locator("div")
.filter({ hasText: /^HelloCall$/ })
.click();
// Check the number of participants
await expect(page.locator("div").filter({ hasText: /^1$/ })).toBeVisible();
// The tooltip with the name should be visible
await expect(page.getByTestId("name_tag")).toContainText("John Doe");
// leave the call
await page.getByTestId("incall_leave").click();
await expect(page.getByRole("heading")).toContainText(
"John Doe, your call has ended. How did it go?",
);
await expect(page.getByRole("main")).toContainText(
"Why not finish by setting up a password to keep your account?",
);
await expect(
page.getByRole("link", { name: "Not now, return to home screen" }),
).toBeVisible();
});

View File

@@ -0,0 +1,30 @@
/*
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 { test, expect } from "@playwright/test";
test("has title", async ({ page }) => {
await page.goto("/");
await expect(page).toHaveTitle(/Element Call/);
});
test("Landing page", async ({ page }) => {
await page.goto("/");
// There should be a login button in the header
await expect(page.getByRole("link", { name: "Log In" })).toBeVisible();
await expect(
page.getByRole("heading", { name: "Start new call" }),
).toBeVisible();
await expect(page.getByTestId("home_callName")).toBeVisible();
await expect(page.getByTestId("home_displayName")).toBeVisible();
await expect(page.getByTestId("home_go")).toBeVisible();
});

View File

@@ -1,26 +0,0 @@
{
"applinks": {
"details": [
{
"appIDs": [
"7J4U792NQT.io.element.elementx",
"7J4U792NQT.io.element.elementx.nightly",
"7J4U792NQT.io.element.elementx.pr"
],
"components": [
{
"?": {
"no_universal_links": "?*"
},
"exclude": true,
"comment": "Opt out of universal links"
},
{
"/": "/*",
"comment": "Matches any URL"
}
]
}
]
}
}

View File

@@ -1,32 +0,0 @@
[
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "io.element.android.x.debug",
"sha256_cert_fingerprints": [
"B0:B0:51:DC:56:5C:81:2F:E1:7F:6F:3E:94:5B:4D:79:04:71:23:AB:0D:A6:12:86:76:9E:B2:94:91:97:13:0E"
]
}
},
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "io.element.android.x.nightly",
"sha256_cert_fingerprints": [
"CA:D3:85:16:84:3A:05:CC:EB:00:AB:7B:D3:80:0F:01:BA:8F:E0:4B:38:86:F3:97:D8:F7:9A:1B:C4:54:E4:0F"
]
}
},
{
"relation": ["delegate_permission/common.handle_all_urls"],
"target": {
"namespace": "android_app",
"package_name": "io.element.android.x",
"sha256_cert_fingerprints": [
"C6:DB:9B:9C:8C:BD:D6:5D:16:E8:EC:8C:8B:91:C8:31:B9:EF:C9:5C:BF:98:AE:41:F6:A9:D8:35:15:1A:7E:16"
]
}
}
]

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -1,20 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="favicon.png" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0"
/>
<title><%- title %></title>
<script>
window.global = window;
</script>
</head>
<!-- The default class is: .no-theme {display: none}. It will be overwritten once the app is loaded. -->
<body class="no-theme">
<div id="root"></div>
</body>
</html>

View File

@@ -1,142 +0,0 @@
{
"a11y": {
"user_menu": "Benutzermenü"
},
"action": {
"close": "Schließen",
"copy": "Kopieren",
"copy_link": "Link kopieren",
"go": "Los gehts",
"invite": "Einladen",
"no": "Nein",
"register": "Registrieren",
"remove": "Entfernen",
"sign_in": "Anmelden",
"sign_out": "Abmelden",
"submit": "Absenden"
},
"analytics_notice": "Mit der Teilnahme an der Beta akzeptierst du die Sammlung von anonymen Daten, die wir zur Verbesserung des Produkts verwenden. Weitere Informationen zu den von uns erhobenen Daten findest du in unserer <2>Datenschutzerklärung</2> und unseren <6>Cookie-Richtlinien</6>.",
"app_selection_modal": {
"continue_in_browser": "Weiter im Browser",
"open_in_app": "In der App öffnen",
"text": "Bereit, beizutreten?",
"title": "App auswählen"
},
"application_opened_another_tab": "Diese Anwendung wurde in einem anderen Tab geöffnet.",
"browser_media_e2ee_unsupported": "Dein Webbrowser unterstützt keine Medien-Ende-zu-Ende-Verschlüsselung. Unterstützte Browser sind Chrome, Safari, Firefox >=117",
"browser_media_e2ee_unsupported_heading": "Inkompatibler Browser",
"call_ended_view": {
"body": "Deine Verbindung wurde getrennt",
"create_account_button": "Konto erstellen",
"create_account_prompt": "<0>Warum vergibst du nicht abschließend ein Passwort, um dein Konto zu erhalten?</0><1>Du kannst deinen Namen behalten und ein Profilbild für zukünftige Anrufe festlegen.</1>",
"feedback_done": "<0>Danke für deine Rückmeldung!</0>",
"feedback_prompt": "<0>Wir würden uns freuen, deine Rückmeldung zu hören, um deine Erfahrung verbessern zu können.</0>",
"headline": "{{displayName}}, dein Anruf wurde beendet.",
"not_now_button": "Nicht jetzt, zurück zur Startseite",
"reconnect_button": "Erneut verbinden",
"survey_prompt": "Wie ist es gelaufen?"
},
"call_name": "Name des Anrufs",
"common": {
"audio": "Audio",
"avatar": "Profilbild",
"camera": "Kamera",
"copied": "Kopiert!",
"display_name": "Anzeigename",
"encrypted": "Verschlüsselt",
"error": "Fehler",
"home": "Startseite",
"loading": "Lade …",
"microphone": "Mikrofon",
"password": "Passwort",
"profile": "Profil",
"settings": "Einstellungen",
"unencrypted": "Nicht verschlüsselt",
"username": "Benutzername",
"video": "Video"
},
"disconnected_banner": "Die Verbindung zum Server wurde getrennt.",
"full_screen_view_description": "<0>Übermittelte Problemberichte helfen uns, Fehler zu beheben.</0>",
"full_screen_view_h1": "<0>Hoppla, etwas ist schiefgelaufen.</0>",
"hangup_button_label": "Anruf beenden",
"header_label": "Element Call-Startseite",
"header_participants_label": "Teilnehmende",
"invite_modal": {
"link_copied_toast": "Link in Zwischenablage kopiert",
"title": "Zu diesem Anruf einladen"
},
"join_existing_call_modal": {
"join_button": "Ja, Anruf beitreten",
"text": "Dieser Aufruf existiert bereits, möchtest Du teilnehmen?",
"title": "An bestehendem Anruf teilnehmen?"
},
"layout_grid_label": "Raster",
"layout_spotlight_label": "Rampenlicht",
"lobby": {
"join_button": "Anruf beitreten",
"leave_button": "Zurück zu kürzlichen Anrufen"
},
"log_in": "Anmelden",
"logging_in": "Anmelden …",
"login_auth_links": "<0>Konto erstellen</0> Oder <2>Als Gast betreten</2>",
"login_auth_links_prompt": "Noch nicht registriert?",
"login_subheading": "Weiter zu Element",
"login_title": "Anmelden",
"microphone_off": "Mikrofon aus",
"microphone_on": "Mikrofon an",
"mute_microphone_button_label": "Mikrofon deaktivieren",
"rageshake_button_error_caption": "Protokolle erneut senden",
"rageshake_request_modal": {
"body": "Ein anderer Benutzer dieses Anrufs hat ein Problem. Um es besser diagnostizieren zu können, würden wir gerne ein Debug-Protokoll erstellen.",
"title": "Debug-Log Anfrage"
},
"rageshake_send_logs": "Debug-Logs senden",
"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",
"register": {
"passwords_must_match": "Passwörter müssen übereinstimmen",
"registering": "Registrierung …"
},
"register_auth_links": "<0>Du hast bereits ein Konto?</0><1><0>Anmelden</0> Oder <2>Als Gast betreten</2></1>",
"register_confirm_password_label": "Passwort bestätigen",
"return_home_button": "Zurück zur Startseite",
"room_auth_view_eula_caption": "Mit einem Klick auf „Anruf beitreten“ akzeptierst du unseren <2>Endbenutzer-Lizenzvertrag (EULA)</2>",
"room_auth_view_join_button": "Anruf beitreten",
"screenshare_button_label": "Bildschirm teilen",
"select_input_unset_button": "Wähle eine Option",
"settings": {
"developer_settings_label": "Entwicklereinstellungen",
"developer_settings_label_description": "Zeige die Entwicklereinstellungen im Einstellungsfenster.",
"developer_tab_title": "Entwickler",
"feedback_tab_body": "Falls du auf Probleme stößt oder einfach nur eine Rückmeldung geben möchtest, sende uns bitte eine kurze Beschreibung.",
"feedback_tab_description_label": "Deine Rückmeldung",
"feedback_tab_h4": "Rückmeldung geben",
"feedback_tab_send_logs_label": "Debug-Protokolle einschließen",
"feedback_tab_thank_you": "Danke, wir haben deine Rückmeldung erhalten!",
"feedback_tab_title": "Rückmeldung",
"more_tab_title": "Mehr",
"opt_in_description": "<0></0><1></1>Du kannst deine Zustimmung durch Abwählen dieses Kästchens zurückziehen. Falls du dich aktuell in einem Anruf befindest, wird diese Einstellung nach dem Ende des Anrufs wirksam.",
"show_connection_stats_label": "Verbindungsstatistiken zeigen",
"speaker_device_selection_label": "Wiedergabegerät"
},
"star_rating_input_label_one": "{{count}} Stern",
"star_rating_input_label_other": "{{count}} Sterne",
"start_new_call": "Neuen Anruf beginnen",
"start_video_button_label": "Video aktivieren",
"stop_screenshare_button_label": "Bildschirm wird geteilt",
"stop_video_button_label": "Video deaktivieren",
"submitting": "Sende …",
"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",
"unmute_microphone_button_label": "Mikrofon aktivieren",
"version": "Version: {{version}}",
"video_tile": {
"sfu_participant_local": "Du"
},
"waiting_for_participants": "Warte auf weitere Teilnehmer …"
}

View File

@@ -1,18 +1,22 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["config:base"],
"extends": [
"config:recommended",
"schedule:monthly",
":enableVulnerabilityAlertsWithLabel(security)"
],
"addLabels": ["dependencies"],
"minimumReleaseAge": "5 days",
"packageRules": [
{
"groupName": "all non-major dependencies",
"groupSlug": "all-minor-patch",
"matchUpdateTypes": ["minor", "patch"],
"extends": ["schedule:weekly"]
"matchUpdateTypes": ["minor", "patch"]
},
{
"groupName": "GitHub Actions",
"matchDepTypes": ["action"],
"pinDigests": true,
"extends": ["schedule:monthly"]
"pinDigests": true
},
{
"description": "Disable Renovate for packages we want to monitor ourselves",
@@ -22,28 +26,35 @@
},
{
"groupName": "matrix-widget-api",
"matchDepNames": ["matrix-widget-api"]
"matchDepNames": ["matrix-widget-api"],
"extends": ["schedule:weekly"]
},
{
"groupName": "Compound",
"matchPackagePrefixes": ["@vector-im/compound-"],
"schedule": "before 5am on Tuesday and Friday"
"matchPackageNames": ["@vector-im/compound-{/,}**"],
"extends": ["schedule:weekly"]
},
{
"groupName": "LiveKit client",
"matchDepNames": ["livekit-client"]
"matchDepNames": ["livekit-client"],
"extends": ["schedule:weekly"]
},
{
"groupName": "LiveKit components",
"matchPackagePrefixes": ["@livekit/components-"]
"matchPackageNames": ["@livekit/components-{/,}**"],
"extends": ["schedule:weekly"]
},
{
"groupName": "Vaul",
"matchDepNames": ["vaul"],
"extends": ["schedule:monthly"],
"prHeader": "Please review modals on mobile for visual regressions."
}
],
"semanticCommits": "disabled",
"ignoreDeps": ["posthog-js"]
"ignoreDeps": ["posthog-js"],
"vulnerabilityAlerts": {
"schedule": ["at any time"],
"prHourlyLimit": 0,
"minimumReleaseAge": null
}
}

View File

@@ -1,12 +1,15 @@
/*
Copyright 2022-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
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 { Controls } from "../controls";
import { type setLogLevel as setLKLogLevel } from "livekit-client";
import type { DurationFormat as PolyfillDurationFormat } from "@formatjs/intl-durationformat";
import { type Controls } from "../controls";
declare global {
interface Document {
@@ -17,10 +20,16 @@ declare global {
interface Window {
controls: Controls;
setLKLogLevel: typeof setLKLogLevel;
}
interface HTMLElement {
// Safari only supports this prefixed, so tell the type system about it
webkitRequestFullscreen: () => void;
}
namespace Intl {
// Add DurationFormat as part of the Intl namespace because we polyfill it
const DurationFormat: typeof PolyfillDurationFormat;
}
}

View File

@@ -1,13 +1,13 @@
/*
Copyright 2023, 2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only
SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE in the repository root for full details.
*/
import "i18next";
// import all namespaces (for the default language, only)
import app from "../../public/locales/en-GB/app.json";
import type app from "../../locales/en/app.json";
declare module "i18next" {
interface CustomTypeOptions {

26
src/@types/matrix-js-sdk.d.ts vendored Normal file
View File

@@ -0,0 +1,26 @@
/*
Copyright 2024 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 ElementCallReactionEventType,
type ECallReactionEventContent,
} 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" {
export interface TimelineEvents {
[ElementCallReactionEventType]: ECallReactionEventContent;
}
export interface AccountDataEvents {
// Analytics account data event
"im.vector.analytics": {
id: string;
pseudonymousAnalyticsOptIn?: boolean;
};
}
}

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