Compare commits

..

6 Commits

Author SHA1 Message Date
RiotRobot
4d55e8f433 v1.11.92 2025-02-11 14:32:06 +00:00
RiotRobot
02990bd275 Upgrade dependency to matrix-js-sdk@36.2.0 2025-02-11 14:25:39 +00:00
Richard van der Hoff
67658aef56 Log when we show, and hide, encryption setup toasts (#29235) (#29238)
It's currently hard to debug when someone sees or hides one of these
toasts. Lets's add some logging.
2025-02-11 11:06:03 +00:00
ElementRobot
8941724020 [Backport staging] Wire up the "Forgot recovery key" button for the "Key storage out of sync" toast (#29190)
* Wire up the "Forgot recovery key" button for the "Key storage out of sync" toast (#29138)

* Wire up the "Forgot recovery key" button for the "Key storage out of sync" toast

* Unused import & fix test

* Test 'forgot' variant

* Fix dependencies

* Add more toast tests

* Unused import

* Test initialState in Encryption Tab

* Let's see if github has any more luck running this test than me

* Working playwright test with screenshot

* year

* Convert playwright test to use the bot client

* Disambiguate

Co-authored-by: Florian Duros <florianduros@element.io>

* Add doc & do other part of rename

* Split out into custom hook

* Fix tests

---------

Co-authored-by: Florian Duros <florianduros@element.io>
(cherry picked from commit 9657d39cd6)

* Update fetchdep.sh to understand merge queues

---------

Co-authored-by: David Baker <dbkr@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 00:01:52 +00:00
RiotRobot
0a8393c9e1 v1.11.92-rc.0 2025-02-04 12:47:45 +00:00
RiotRobot
0fa52e610e Upgrade dependency to matrix-js-sdk@36.2.0-rc.0 2025-02-04 12:31:52 +00:00
1484 changed files with 5619 additions and 7355 deletions

View File

@@ -200,13 +200,8 @@ module.exports = {
"@typescript-eslint/ban-ts-comment": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-empty-object-type": [
"error",
{
// We do this sometimes to brand interfaces
allowInterfaces: "with-single-extends",
},
],
// We do this sometimes to brand interfaces
"@typescript-eslint/no-empty-object-type": "off",
},
},
// temporary override for offending icon require files
@@ -252,7 +247,6 @@ module.exports = {
// We don't need super strict typing in test utilities
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-member-accessibility": "off",
"@typescript-eslint/no-empty-object-type": "off",
// Jest/Playwright specific

View File

@@ -51,7 +51,7 @@ jobs:
- name: Build and push
id: build-and-push
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6
with:
context: .
push: true

View File

@@ -104,7 +104,7 @@ jobs:
- name: Skip SonarCloud in merge queue
if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true'
uses: guibranco/github-status-action-v2@119b3320db3f04d89e91df840844b92d57ce3468
uses: guibranco/github-status-action-v2@ecd54a02cf761e85a8fb328fe937710fd4227cda
with:
authToken: ${{ secrets.GITHUB_TOKEN }}
state: success

View File

@@ -0,0 +1,21 @@
name: Close stale flaky issues
on:
workflow_dispatch: {}
schedule:
- cron: "30 1 * * *"
permissions: {}
jobs:
close:
runs-on: ubuntu-24.04
permissions:
actions: write
issues: write
steps:
- uses: actions/stale@v9
with:
only-labels: "Z-Flaky-Test"
days-before-stale: 14
days-before-close: 0
close-issue-message: "This flaky test issue has not been updated in 14 days. It is being closed as presumed resolved."
exempt-issue-labels: "Z-Flaky-Test-Disabled"
operations-per-run: 100

View File

@@ -1,27 +0,0 @@
name: Close stale issues & PRs
on:
workflow_dispatch: {}
schedule:
- cron: "30 1 * * *"
permissions: {}
jobs:
close:
runs-on: ubuntu-24.04
permissions:
actions: write
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
operations-per-run: 100
# Flaky test issue closing
only-issue-labels: "Z-Flaky-Test"
days-before-issue-stale: 14
days-before-issue-close: 0
close-issue-message: "This flaky test issue has not been updated in 14 days. It is being closed as presumed resolved."
exempt-issue-labels: "Z-Flaky-Test-Disabled"
# Stale PR closing
days-before-pr-stale: 180
days-before-pr-close: 0
close-pr-message: "This PR has been automatically closed because it has been stale for 180 days. If you wish to continue working on this PR, please ping a maintainer to reopen it."

View File

@@ -1,3 +1,36 @@
Changes in [1.11.92](https://github.com/element-hq/element-web/releases/tag/v1.11.92) (2025-02-11)
==================================================================================================
## ✨ Features
* [Backport staging] Log when we show, and hide, encryption setup toasts ([#29238](https://github.com/element-hq/element-web/pull/29238)). Contributed by @richvdh.
* Make profile header section match the designs ([#29163](https://github.com/element-hq/element-web/pull/29163)). Contributed by @MidhunSureshR.
* Always show back button in the right panel ([#29128](https://github.com/element-hq/element-web/pull/29128)). Contributed by @MidhunSureshR.
* Schedule dehydration on reload if the dehydration key is already cached locally ([#29021](https://github.com/element-hq/element-web/pull/29021)). Contributed by @uhoreg.
* update to twemoji 15.1.0 ([#29115](https://github.com/element-hq/element-web/pull/29115)). Contributed by @ara4n.
* Update matrix-widget-api ([#29112](https://github.com/element-hq/element-web/pull/29112)). Contributed by @toger5.
* Allow navigating through the memberlist using up/down keys ([#28949](https://github.com/element-hq/element-web/pull/28949)). Contributed by @MidhunSureshR.
* Style room header icons and facepile for toggled state ([#28968](https://github.com/element-hq/element-web/pull/28968)). Contributed by @MidhunSureshR.
* Move threads header below base card header ([#28969](https://github.com/element-hq/element-web/pull/28969)). Contributed by @MidhunSureshR.
* Add `Advanced` section to the user settings encryption tab ([#28804](https://github.com/element-hq/element-web/pull/28804)). Contributed by @florianduros.
* Fix outstanding UX issues with replies/mentions/keyword notifs ([#28270](https://github.com/element-hq/element-web/pull/28270)). Contributed by @taffyko.
* Distinguish room state and timeline events when dealing with widgets ([#28681](https://github.com/element-hq/element-web/pull/28681)). Contributed by @robintown.
* Switch OIDC primarily to new `/auth_metadata` API ([#29019](https://github.com/element-hq/element-web/pull/29019)). Contributed by @t3chguy.
* More memberlist changes ([#29069](https://github.com/element-hq/element-web/pull/29069)). Contributed by @MidhunSureshR.
## 🐛 Bug Fixes
* [Backport staging] Wire up the "Forgot recovery key" button for the "Key storage out of sync" toast ([#29190](https://github.com/element-hq/element-web/pull/29190)). Contributed by @RiotRobot.
* Encryption tab: hide `Advanced` section when the key storage is out of sync ([#29129](https://github.com/element-hq/element-web/pull/29129)). Contributed by @florianduros.
* Fix share button in discovery settings being disabled incorrectly ([#29151](https://github.com/element-hq/element-web/pull/29151)). Contributed by @t3chguy.
* Ensure switching rooms does not wrongly focus timeline search ([#29153](https://github.com/element-hq/element-web/pull/29153)). Contributed by @t3chguy.
* Stop showing a dialog prompting the user to enter an old recovery key ([#29143](https://github.com/element-hq/element-web/pull/29143)). Contributed by @richvdh.
* Make themed widgets reflect the effective theme ([#28342](https://github.com/element-hq/element-web/pull/28342)). Contributed by @robintown.
* support non-VS16 emoji ligatures in TwemojiMozilla ([#29100](https://github.com/element-hq/element-web/pull/29100)). Contributed by @ara4n.
* e2e test: Verify session with the encryption tab instead of the security \& privacy tab ([#29090](https://github.com/element-hq/element-web/pull/29090)). Contributed by @florianduros.
* Work around cloudflare R2 / aws client incompatability ([#29086](https://github.com/element-hq/element-web/pull/29086)). Contributed by @dbkr.
* Fix identity server settings visibility ([#29083](https://github.com/element-hq/element-web/pull/29083)). Contributed by @dbkr.
Changes in [1.11.91](https://github.com/element-hq/element-web/releases/tag/v1.11.91) (2025-01-28)
==================================================================================================
## ✨ Features

View File

@@ -189,6 +189,89 @@ give away to contributors - if you feel that Matrix-branded apparel is missing
from your life, please mail us your shipping address to matrix at matrix.org
and we'll try to fix it :)
## Sign off
In order to have a concrete record that your contribution is intentional
and you agree to license it under the same terms as the project's license, we've
adopted the same lightweight approach that the Linux Kernel
(https://www.kernel.org/doc/html/latest/process/submitting-patches.html), Docker
(https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other
projects use: the DCO (Developer Certificate of Origin:
http://developercertificate.org/). This is a simple declaration that you wrote
the contribution or otherwise have the right to contribute it to Matrix:
```
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
If you agree to this for your contribution, then all that's needed is to
include the line in your commit or pull request comment:
```
Signed-off-by: Your Name <your@email.example.org>
```
We accept contributions under a legally identifiable name, such as your name on
government documentation or common-law names (names claimed by legitimate usage
or repute). Unfortunately, we cannot accept anonymous contributions at this
time.
Git allows you to add this signoff automatically when using the `-s` flag to
`git commit`, which uses the name and email set in your `user.name` and
`user.email` git configs.
If you forgot to sign off your commits before making your pull request and are
on Git 2.17+ you can mass signoff using rebase:
```
git rebase --signoff origin/develop
```
## Private sign off
If you would like to provide your legal name privately to the Matrix.org
Foundation (instead of in a public commit or comment), you can do so by emailing
your legal name and a link to the pull request to dco@matrix.org. It helps to
include "sign off" or similar in the subject line. You will then be instructed
further.
Once private sign off is complete, doing so for future contributions will not
be required.
# Review expectations
See https://github.com/element-hq/element-meta/wiki/Review-process

120
README.md
View File

@@ -182,11 +182,123 @@ Dockerfile.
# Development
Please read through the following:
Before attempting to develop on Element you **must** read the [developer guide
for `matrix-react-sdk`](https://github.com/matrix-org/matrix-react-sdk#developer-guide), which
also defines the design, architecture and style for Element too.
1. [Developer guide](./developer_guide.md)
2. [Code style](./code_style.md)
3. [Contribution guide](./CONTRIBUTING.md)
Read the [Choosing an issue](docs/choosing-an-issue.md) page for some guidance
about where to start. Before starting work on a feature, it's best to ensure
your plan aligns well with our vision for Element. Please chat with the team in
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) before
you start so we can ensure it's something we'd be willing to merge.
You should also familiarise yourself with the ["Here be Dragons" guide
](https://docs.google.com/document/d/12jYzvkidrp1h7liEuLIe6BMdU0NUjndUYI971O06ooM)
to the tame & not-so-tame dragons (gotchas) which exist in the codebase.
The idea of Element is to be a relatively lightweight "skin" of customisations on
top of the underlying `matrix-react-sdk`. `matrix-react-sdk` provides both the
higher and lower level React components useful for building Matrix communication
apps using React.
Please note that Element is intended to run correctly without access to the public
internet. So please don't depend on resources (JS libs, CSS, images, fonts)
hosted by external CDNs or servers but instead please package all dependencies
into Element itself.
# Setting up a dev environment
Much of the functionality in Element is actually in the `matrix-js-sdk` module.
It is possible to set these up in a way that makes it easy to track the `develop` branches
in git and to make local changes without having to manually rebuild each time.
First clone and build `matrix-js-sdk`:
```bash
git clone https://github.com/matrix-org/matrix-js-sdk.git
pushd matrix-js-sdk
yarn link
yarn install
popd
```
Clone the repo and switch to the `element-web` directory:
```bash
git clone https://github.com/element-hq/element-web.git
cd element-web
```
Configure the app by copying `config.sample.json` to `config.json` and
modifying it. See the [configuration docs](docs/config.md) for details.
Finally, build and start Element itself:
```bash
yarn link matrix-js-sdk
yarn install
yarn start
```
Wait a few seconds for the initial build to finish; you should see something like:
```
[element-js] <s> [webpack.Progress] 100%
[element-js]
[element-js] 「wdm」: 1840 modules
[element-js] 「wdm」: Compiled successfully.
```
Remember, the command will not terminate since it runs the web server
and rebuilds source files when they change. This development server also
disables caching, so do NOT use it in production.
Open <http://127.0.0.1:8080/> in your browser to see your newly built Element.
**Note**: The build script uses inotify by default on Linux to monitor directories
for changes. If the inotify limits are too low your build will fail silently or with
`Error: EMFILE: too many open files`. To avoid these issues, we recommend a watch limit
of at least `128M` and instance limit around `512`.
You may be interested in issues [#15750](https://github.com/element-hq/element-web/issues/15750) and
[#15774](https://github.com/element-hq/element-web/issues/15774) for further details.
To set a new inotify watch and instance limit, execute:
```
sudo sysctl fs.inotify.max_user_watches=131072
sudo sysctl fs.inotify.max_user_instances=512
sudo sysctl -p
```
If you wish, you can make the new limits permanent, by executing:
```
echo fs.inotify.max_user_watches=131072 | sudo tee -a /etc/sysctl.conf
echo fs.inotify.max_user_instances=512 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```
---
When you make changes to `matrix-js-sdk` they should be automatically picked up by webpack and built.
If any of these steps error with, `file table overflow`, you are probably on a mac
which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again.
You'll need to do this in each new terminal you open before building Element.
## Running the tests
There are a number of application-level tests in the `tests` directory; these
are designed to run with Jest and JSDOM. To run them
```
yarn test
```
### End-to-End tests
See [matrix-react-sdk](https://github.com/matrix-org/matrix-react-sdk/#end-to-end-tests) for how to run the end-to-end tests.
# Translations

View File

@@ -5,6 +5,15 @@ adjacent to. As of writing, these are:
- element-desktop
- element-web
- matrix-js-sdk
Other projects might extend this code style for increased strictness. For example, matrix-events-sdk
has stricter code organization to reduce the maintenance burden. These projects will declare their code
style within their own repos.
Note that some requirements will be layer-specific. Where the requirements don't make sense for the
project, they are used to the best of their ability, used in spirit, or ignored if not applicable,
in that order.
## Guiding principles
@@ -225,19 +234,17 @@ Unless otherwise specified, the following applies to all code:
Inheriting all the rules of TypeScript, the following additionally apply:
1. Component source files are named with upper camel case (e.g. views/rooms/EventTile.js)
2. They are organised in a typically two-level hierarchy - first whether the component is a view or a structure, and then a broad functional grouping (e.g. 'rooms' here)
3. Types for lifecycle functions are not required (render, componentDidMount, and so on).
4. Class components must always have a `Props` interface declared immediately above them. It can be
1. Types for lifecycle functions are not required (render, componentDidMount, and so on).
2. Class components must always have a `Props` interface declared immediately above them. It can be
empty if the component accepts no props.
5. Class components should have an `State` interface declared immediately above them, but after `Props`.
6. Props and State should not be exported. Use `React.ComponentProps<typeof ComponentNameHere>`
3. Class components should have an `State` interface declared immediately above them, but after `Props`.
4. Props and State should not be exported. Use `React.ComponentProps<typeof ComponentNameHere>`
instead.
7. One component per file, except when a component is a utility component specifically for the "primary"
5. One component per file, except when a component is a utility component specifically for the "primary"
component. The utility component should not be exported.
8. Exported constants, enums, interfaces, functions, etc must be separate from files containing components
6. Exported constants, enums, interfaces, functions, etc must be separate from files containing components
or stores.
9. Stores should use a singleton pattern with a static instance property:
7. Stores should use a singleton pattern with a static instance property:
```typescript
class FooStore {
@@ -254,41 +261,44 @@ Inheriting all the rules of TypeScript, the following additionally apply:
}
```
10. Stores must support using an alternative MatrixClient and dispatcher instance.
11. Utilities which require JSX must be split out from utilities which do not. This is to prevent import
cycles during runtime where components accidentally include more of the app than they intended.
12. Interdependence between stores should be kept to a minimum. Break functions and constants out to utilities
8. Stores must support using an alternative MatrixClient and dispatcher instance.
9. Utilities which require JSX must be split out from utilities which do not. This is to prevent import
cycles during runtime where components accidentally include more of the app than they intended.
10. Interdependence between stores should be kept to a minimum. Break functions and constants out to utilities
if at all possible.
13. A component should only use CSS class names in line with the component name.
11. A component should only use CSS class names in line with the component name.
1. When knowingly using a class name from another component, document it with a [comment](#comments).
14. Curly braces within JSX should be padded with a space, however properties on those components should not.
12. Curly braces within JSX should be padded with a space, however properties on those components should not.
See above code example.
15. Functions used as properties should either be defined on the class or stored in a variable. They should not
13. Functions used as properties should either be defined on the class or stored in a variable. They should not
be inline unless mocking/short-circuiting the value.
16. Prefer hooks (functional components) over class components. Be consistent with the existing area if unsure
14. Prefer hooks (functional components) over class components. Be consistent with the existing area if unsure
which should be used.
1. Unless the component is considered a "structure", in which case use classes.
17. Write more views than structures. Structures are chunks of functionality like MatrixChat while views are
15. Write more views than structures. Structures are chunks of functionality like MatrixChat while views are
isolated components.
18. Components should serve a single, or near-single, purpose.
19. Prefer to derive information from component properties rather than establish state.
20. Do not use `React.Component::forceUpdate`.
16. Components should serve a single, or near-single, purpose.
17. Prefer to derive information from component properties rather than establish state.
18. Do not use `React.Component::forceUpdate`.
## Stylesheets (\*.pcss = PostCSS + Plugins)
Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, but actually it is not.
1. The view's CSS file MUST have the same name as the component (e.g. `view/rooms/_MessageTile.css` for `MessageTile.tsx` component).
2. Per-view CSS is optional - it could choose to inherit all its styling from the context of the rest of the app, although this is unusual.
3. Class names must be prefixed with "mx\_".
4. Class names must strictly denote the component which defines them.
For example: `mx_MyFoo` for `MyFoo` component.
5. Class names for DOM elements within a view which aren't components are named by appending a lower camel case identifier to the view's class name - e.g. .mx_MyFoo_randomDiv is how you'd name the class of an arbitrary div within the MyFoo view.
6. Use the `$font` variables instead of manual values.
7. Keep indentation/nesting to a minimum. Maximum suggested nesting is 5 layers.
8. Use the whole class name instead of shortcuts:
1. Class names must be prefixed with "mx\_".
2. Class names must denote the component which defines them, followed by any context.
The context is not further specified here in terms of meaning or syntax.
Use whatever is appropriate for your implementation use case.
Some examples:
1. `mx_MyFoo`
2. `mx_MyFoo_avatar`
3. `mx_MyFoo_avatarUser`
4. `mx_MyFoo_avatar--user`
3. Use the `$font` variables instead of manual values.
4. Keep indentation/nesting to a minimum. Maximum suggested nesting is 5 layers.
5. Use the whole class name instead of shortcuts:
```scss
.mx_MyFoo {
@@ -299,7 +309,7 @@ Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, b
}
```
9. Break multiple selectors over multiple lines this way:
6. Break multiple selectors over multiple lines this way:
```scss
.mx_MyFoo,
@@ -309,9 +319,9 @@ Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, b
}
```
10. Non-shared variables should use $lowerCamelCase. Shared variables use $dashed-naming.
11. Overrides to Z indexes, adjustments of dimensions/padding with pixels, and so on should all be
[documented](#comments) for what the values mean:
7. Non-shared variables should use $lowerCamelCase. Shared variables use $dashed-naming.
8. Overrides to Z indexes, adjustments of dimensions/padding with pixels, and so on should all be
[documented](#comments) for what the values mean:
```scss
.mx_MyFoo {
@@ -321,9 +331,7 @@ Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, b
}
```
12. Avoid the use of `!important`. If `!important` is necessary, add a [comment](#comments) explaining why.
13. The CSS for a component can override the rules for child components. For instance, .mxRoomList .mx_RoomTile {} would be the selector to override styles of RoomTiles when viewed in the context of a RoomList view. Overrides must be scoped to the View's CSS class - i.e. don't just define .mx_RoomTile {} in RoomList.css - only RoomTile.css is allowed to define its own CSS. Instead, say .mx_RoomList .mx_RoomTile {} to scope the override only to the context of RoomList views. N.B. overrides should be relatively rare as in general CSS inheritance should be enough.
14. Components should render only within the bounding box of their outermost DOM element. Page-absolute positioning and negative CSS margins and similar are generally not cool and stop the component from being reused easily in different places.
9. Avoid the use of `!important`. If `!important` is necessary, add a [comment](#comments) explaining why.
## Tests

2
debian/control vendored
View File

@@ -8,6 +8,6 @@ Package: element-web
Architecture: all
Recommends: httpd, element-io-archive-keyring
Description:
Element: the future of secure communication
A feature-rich client for Matrix.org
This package contains the web-based client that can be served through a web
server.

View File

@@ -1,126 +0,0 @@
# Developer Guide
## Development
Read the [Choosing an issue](docs/choosing-an-issue.md) page for some guidance
about where to start. Before starting work on a feature, it's best to ensure
your plan aligns well with our vision for Element. Please chat with the team in
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) before
you start so we can ensure it's something we'd be willing to merge.
You should also familiarise yourself with the ["Here be Dragons" guide
](https://docs.google.com/document/d/12jYzvkidrp1h7liEuLIe6BMdU0NUjndUYI971O06ooM)
to the tame & not-so-tame dragons (gotchas) which exist in the codebase.
Please note that Element is intended to run correctly without access to the public
internet. So please don't depend on resources (JS libs, CSS, images, fonts)
hosted by external CDNs or servers but instead please package all dependencies
into Element itself.
## Setting up a dev environment
Much of the functionality in Element is actually in the `matrix-js-sdk` module.
It is possible to set these up in a way that makes it easy to track the `develop` branches
in git and to make local changes without having to manually rebuild each time.
First clone and build `matrix-js-sdk`:
```bash
git clone https://github.com/matrix-org/matrix-js-sdk.git
pushd matrix-js-sdk
yarn link
yarn install
popd
```
Clone the repo and switch to the `element-web` directory:
```bash
git clone https://github.com/element-hq/element-web.git
cd element-web
```
Configure the app by copying `config.sample.json` to `config.json` and
modifying it. See the [configuration docs](docs/config.md) for details.
Finally, build and start Element itself:
```bash
yarn link matrix-js-sdk
yarn install
yarn start
```
Wait a few seconds for the initial build to finish; you should see something like:
```
[element-js] <s> [webpack.Progress] 100%
[element-js]
[element-js] 「wdm」: 1840 modules
[element-js] 「wdm」: Compiled successfully.
```
Remember, the command will not terminate since it runs the web server
and rebuilds source files when they change. This development server also
disables caching, so do NOT use it in production.
Open <http://127.0.0.1:8080/> in your browser to see your newly built Element.
**Note**: The build script uses inotify by default on Linux to monitor directories
for changes. If the inotify limits are too low your build will fail silently or with
`Error: EMFILE: too many open files`. To avoid these issues, we recommend a watch limit
of at least `128M` and instance limit around `512`.
You may be interested in issues [#15750](https://github.com/element-hq/element-web/issues/15750) and
[#15774](https://github.com/element-hq/element-web/issues/15774) for further details.
To set a new inotify watch and instance limit, execute:
```
sudo sysctl fs.inotify.max_user_watches=131072
sudo sysctl fs.inotify.max_user_instances=512
sudo sysctl -p
```
If you wish, you can make the new limits permanent, by executing:
```
echo fs.inotify.max_user_watches=131072 | sudo tee -a /etc/sysctl.conf
echo fs.inotify.max_user_instances=512 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```
---
When you make changes to `matrix-js-sdk` they should be automatically picked up by webpack and built.
If any of these steps error with, `file table overflow`, you are probably on a mac
which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again.
You'll need to do this in each new terminal you open before building Element.
## Running the tests
There are a number of application-level tests in the `tests` directory; these
are designed to run with Jest and JSDOM. To run them
```
yarn test
```
### End-to-End tests
See [matrix-react-sdk](https://github.com/matrix-org/matrix-react-sdk/#end-to-end-tests) for how to run the end-to-end tests.
## General github guidelines
1. **Pull requests must only be filed against the `develop` branch.**
2. Try to keep your pull requests concise. Split them up if necessary.
3. Ensure that you provide a description that explains the fix/feature and its intent.
## Adding new code
New code should be committed as follows:
- All new components: https://github.com/element-hq/element-web/tree/develop/src/components
- CSS: https://github.com/element-hq/element-web/tree/develop/res/css
- Theme specific CSS & resources: https://github.com/element-hq/element-web/tree/develop/res/themes

View File

@@ -592,4 +592,3 @@ The following are undocumented or intended for developer use only.
2. `sync_timeline_limit`
3. `dangerously_allow_unsafe_and_insecure_passwords`
4. `latex_maths_delims`: An optional setting to override the default delimiters used for maths parsing. See https://github.com/matrix-org/matrix-react-sdk/pull/5939 for details. Only used when `feature_latex_maths` is enabled.
5. `modules`: An optional list of modules to load. This is used for testing and development purposes only.

View File

@@ -38,8 +38,6 @@ const config: Config = {
"^!!raw-loader!.*": "jest-raw-loader",
"recorderWorkletFactory": "<rootDir>/__mocks__/empty.js",
"^fetch-mock$": "<rootDir>/node_modules/fetch-mock",
// Requires ESM which is incompatible with our current Jest setup
"^@element-hq/element-web-module-api$": "<rootDir>/__mocks__/empty.js",
},
transformIgnorePatterns: ["/node_modules/(?!(mime|matrix-js-sdk)).+$"],
collectCoverageFrom: [

View File

@@ -9,7 +9,7 @@ import * as fs from "fs";
import * as childProcess from "child_process";
import * as semver from "semver";
import { type BuildConfig } from "./BuildConfig";
import { BuildConfig } from "./BuildConfig";
// This expects to be run from ./scripts/install.ts

View File

@@ -1,7 +1,7 @@
{
"name": "element-web",
"version": "1.11.91",
"description": "Element: the future of secure communication",
"version": "1.11.92",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"repository": {
"type": "git",
@@ -74,13 +74,12 @@
"@types/react-dom": "18.3.5",
"oidc-client-ts": "3.1.0",
"jwt-decode": "4.0.0",
"caniuse-lite": "1.0.30001697",
"caniuse-lite": "1.0.30001692",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0",
"wrap-ansi": "npm:wrap-ansi@^7.0.0"
},
"dependencies": {
"@babel/runtime": "^7.12.5",
"@element-hq/element-web-module-api": "^0.1.1",
"@fontsource/inconsolata": "^5",
"@fontsource/inter": "^5",
"@formatjs/intl-segmenter": "^11.5.7",
@@ -91,7 +90,7 @@
"@sentry/browser": "^8.0.0",
"@types/png-chunks-extract": "^1.0.2",
"@types/react-virtualized": "^9.21.30",
"@vector-im/compound-design-tokens": "^3.0.0",
"@vector-im/compound-design-tokens": "^2.1.0",
"@vector-im/compound-web": "^7.6.1",
"@vector-im/matrix-wysiwyg": "2.38.0",
"@zxcvbn-ts/core": "^3.0.4",
@@ -128,7 +127,7 @@
"maplibre-gl": "^5.0.0",
"matrix-encrypt-attachment": "^1.0.3",
"matrix-events-sdk": "0.0.1",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-js-sdk": "36.2.0",
"matrix-widget-api": "^1.10.0",
"memoize-one": "^6.0.0",
"mime": "^4.0.4",
@@ -180,7 +179,7 @@
"@playwright/test": "^1.40.1",
"@principalstudio/html-webpack-inject-preload": "^1.2.7",
"@sentry/webpack-plugin": "^3.0.0",
"@stylistic/eslint-plugin": "^3.0.0",
"@stylistic/eslint-plugin": "^2.9.0",
"@svgr/webpack": "^8.0.0",
"@testcontainers/postgresql": "^10.16.0",
"@testing-library/dom": "^10.4.0",

View File

@@ -11,7 +11,7 @@ import type { Locator, Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import { SettingLevel } from "../../../src/settings/SettingLevel";
import { Layout } from "../../../src/settings/enums/Layout";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { ElementAppPage } from "../../pages/ElementAppPage";
// Find and click "Reply" button
const clickButtonReply = async (tile: Locator) => {

View File

@@ -16,8 +16,8 @@ import {
enableKeyBackup,
verify,
} from "./utils";
import { type Bot } from "../../pages/bot";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { Bot } from "../../pages/bot";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { isDendrite } from "../../plugins/homeserver/dendrite";
const checkDMRoom = async (page: Page) => {

View File

@@ -6,13 +6,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Locator, type Page } from "@playwright/test";
import { Locator, type Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import { viewRoomSummaryByName } from "../right-panel/utils";
import { isDendrite } from "../../plugins/homeserver/dendrite";
import { completeCreateSecretStorageDialog, createBot, logIntoElement } from "./utils.ts";
import { type Client } from "../../pages/client.ts";
import { Client } from "../../pages/client.ts";
const ROOM_NAME = "Test room";
const NAME = "Alice";

View File

@@ -20,7 +20,7 @@ import {
logIntoElement,
waitForVerificationRequest,
} from "./utils";
import { type Bot } from "../../pages/bot";
import { Bot } from "../../pages/bot";
test.describe("Device verification", { tag: "@no-webkit" }, () => {
let aliceBotClient: Bot;
@@ -29,7 +29,7 @@ test.describe("Device verification", { tag: "@no-webkit" }, () => {
let expectedBackupVersion: string;
test.beforeEach(async ({ page, homeserver, credentials }) => {
const res = await createBot(page, homeserver, credentials, true);
const res = await createBot(page, homeserver, credentials);
aliceBotClient = res.botClient;
expectedBackupVersion = res.expectedBackupVersion;
});

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Locator } from "@playwright/test";
import { Locator } from "@playwright/test";
import { expect, test } from "../../element-web-test";
import {
@@ -19,7 +19,7 @@ import {
verify,
} from "./utils";
import { bootstrapCrossSigningForClient } from "../../pages/client.ts";
import { type ElementAppPage } from "../../pages/ElementAppPage.ts";
import { ElementAppPage } from "../../pages/ElementAppPage.ts";
test.describe("Cryptography", function () {
test.use({

View File

@@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
import { GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
import { test, expect } from "../../element-web-test";
import { createBot, deleteCachedSecrets, logIntoElement } from "./utils";
@@ -34,6 +34,7 @@ test.describe("Key storage out of sync toast", () => {
await expect(page.getByRole("alert").first()).toMatchScreenshot("key-storage-out-of-sync-toast.png");
await page.getByRole("button", { name: "Enter recovery key" }).click();
await page.locator(".mx_Dialog").getByRole("button", { name: "use your Security Key" }).click();
await page.getByRole("textbox", { name: "Security key" }).fill(recoveryKey.encodedPrivateKey);
await page.getByRole("button", { name: "Continue" }).click();

View File

@@ -11,7 +11,7 @@ import { type Preset, type Visibility } from "matrix-js-sdk/src/matrix";
import type { Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import { doTwoWaySasVerification, awaitVerifier } from "./utils";
import { type Client } from "../../pages/client";
import { Client } from "../../pages/client";
test.describe("User verification", () => {
// note that there are other tests that check user verification works in `crypto.spec.ts`.

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { expect, type JSHandle, type Page } from "@playwright/test";
import { expect, JSHandle, type Page } from "@playwright/test";
import type { ICreateRoomOpts, MatrixClient } from "matrix-js-sdk/src/matrix";
import type {
@@ -18,9 +18,9 @@ import type {
Verifier,
VerifierEvent,
} from "matrix-js-sdk/src/crypto-api";
import { type Credentials, type HomeserverInstance } from "../../plugins/homeserver";
import { type Client } from "../../pages/client";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { Credentials, HomeserverInstance } from "../../plugins/homeserver";
import { Client } from "../../pages/client";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { Bot } from "../../pages/bot";
/**
@@ -28,13 +28,11 @@ import { Bot } from "../../pages/bot";
* @param page - the playwright `page` fixture
* @param homeserver - the homeserver to use
* @param credentials - the credentials to use for the bot client
* @param usePassphrase - whether to use a passphrase when creating the recovery key
*/
export async function createBot(
page: Page,
homeserver: HomeserverInstance,
credentials: Credentials,
usePassphrase = false,
): Promise<{ botClient: Bot; recoveryKey: GeneratedSecretStorageKey; expectedBackupVersion: string }> {
// Visit the login page of the app, to load the matrix sdk
await page.goto("/#/login");
@@ -46,7 +44,6 @@ export async function createBot(
const botClient = new Bot(page, homeserver, {
bootstrapCrossSigning: true,
bootstrapSecretStorage: true,
usePassphrase,
});
botClient.setCredentials(credentials);
// Backup is prepared in the background. Poll until it is ready.

View File

@@ -5,10 +5,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details.
*/
import { type APIRequestContext } from "playwright-core";
import { type KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
import { APIRequestContext } from "playwright-core";
import { KeyBackupInfo } from "matrix-js-sdk/src/crypto-api";
import { type HomeserverInstance } from "../plugins/homeserver";
import { HomeserverInstance } from "../plugins/homeserver";
import { ClientServerApi } from "../plugins/utils/api.ts";
/**

View File

@@ -6,11 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Locator, type Page } from "@playwright/test";
import { Locator, Page } from "@playwright/test";
import type { EventType, IContent, ISendEventResponse, MsgType, Visibility } from "matrix-js-sdk/src/matrix";
import { expect, test } from "../../element-web-test";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { SettingLevel } from "../../../src/settings/SettingLevel";
import { isDendrite } from "../../plugins/homeserver/dendrite";

View File

@@ -10,7 +10,7 @@ import { expect, test as base } from "../../element-web-test";
import { selectHomeserver } from "../utils";
import { emailHomeserver } from "../../plugins/homeserver/synapse/emailHomeserver.ts";
import { isDendrite } from "../../plugins/homeserver/dendrite";
import { type Credentials } from "../../plugins/homeserver";
import { Credentials } from "../../plugins/homeserver";
const email = "user@nowhere.dummy";

View File

@@ -10,7 +10,7 @@ import { Bot } from "../../pages/bot";
import type { Locator, Page } from "@playwright/test";
import type { ElementAppPage } from "../../pages/ElementAppPage";
import { test, expect } from "../../element-web-test";
import { type Credentials } from "../../plugins/homeserver";
import { Credentials } from "../../plugins/homeserver";
import { isDendrite } from "../../plugins/homeserver/dendrite";
test.describe("Lazy Loading", () => {

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Locator, type Page } from "@playwright/test";
import { Locator, Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";

View File

@@ -6,11 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Page } from "playwright-core";
import { Page } from "playwright-core";
import { expect, test } from "../../element-web-test";
import { selectHomeserver } from "../utils";
import { type Credentials, type HomeserverInstance } from "../../plugins/homeserver";
import { Credentials, HomeserverInstance } from "../../plugins/homeserver";
import { consentHomeserver } from "../../plugins/homeserver/synapse/consentHomeserver.ts";
import { isDendrite } from "../../plugins/homeserver/dendrite";

View File

@@ -6,9 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Page, expect, type TestInfo } from "@playwright/test";
import { Page, expect, TestInfo } from "@playwright/test";
import { type Credentials, type HomeserverInstance } from "../../plugins/homeserver";
import { Credentials, HomeserverInstance } from "../../plugins/homeserver";
/** Visit the login page, choose to log in with "OAuth test", register a new account, and redirect back to Element
*/

View File

@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
/* See readme.md for tips on writing these tests. */
import { type Locator, type Page } from "playwright-core";
import { Locator, Page } from "playwright-core";
import { test, expect } from "../../element-web-test";

View File

@@ -1,35 +0,0 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { test, expect } from "../../element-web-test";
test.describe("Module loading", () => {
test.use({
displayName: "Manny",
});
test.describe("Example Module", () => {
test.use({
config: {
modules: ["/modules/example-module.js"],
},
page: async ({ page }, use) => {
await page.route("/modules/example-module.js", async (route) => {
await route.fulfill({ path: "playwright/sample-files/example-module.js" });
});
await use(page);
},
});
test("should show alert", async ({ page }) => {
const dialogPromise = page.waitForEvent("dialog");
await page.goto("/");
const dialog = await dialogPromise;
expect(dialog.message()).toBe("Testing module loading successful!");
});
});
});

View File

@@ -6,8 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type MailpitClient } from "mailpit-api";
import { type Page } from "@playwright/test";
import { MailpitClient } from "mailpit-api";
import { Page } from "@playwright/test";
import { expect } from "../../element-web-test";

View File

@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
*/
import { test as base, expect } from "../../element-web-test";
import { type Credentials } from "../../plugins/homeserver";
import { Credentials } from "../../plugins/homeserver";
import { isDendrite } from "../../plugins/homeserver/dendrite";
const test = base.extend<{

View File

@@ -6,12 +6,12 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type Page } from "@playwright/test";
import { Page } from "@playwright/test";
import { test as base, expect } from "../../element-web-test";
import { type Client } from "../../pages/client";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { type Bot } from "../../pages/bot";
import { Client } from "../../pages/client";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { Bot } from "../../pages/bot";
type RoomRef = { name: string; roomId: string };

View File

@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
import { test, expect } from "../../element-web-test";
import type { Bot } from "../../pages/bot";
import type { Client } from "../../pages/client";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { ElementAppPage } from "../../pages/ElementAppPage";
test.describe("Poll history", () => {
type CreatePollOptions = {

View File

@@ -9,9 +9,9 @@ Please see LICENSE files in the repository root for full details.
import type { JSHandle, Page } from "@playwright/test";
import type { MatrixEvent, Room, IndexedDBStore, ReceiptType } from "matrix-js-sdk/src/matrix";
import { test as base, expect } from "../../element-web-test";
import { type Bot } from "../../pages/bot";
import { type Client } from "../../pages/client";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { Bot } from "../../pages/bot";
import { Client } from "../../pages/client";
import { ElementAppPage } from "../../pages/ElementAppPage";
type RoomRef = { name: string; roomId: string };

View File

@@ -9,8 +9,8 @@ Please see LICENSE files in the repository root for full details.
import type { JSHandle } from "@playwright/test";
import type { MatrixEvent, ISendEventResponse, ReceiptType } from "matrix-js-sdk/src/matrix";
import { expect } from "../../element-web-test";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { type Bot } from "../../pages/bot";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { Bot } from "../../pages/bot";
import { test } from ".";
import { isDendrite } from "../../plugins/homeserver/dendrite";

View File

@@ -6,7 +6,7 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type Page } from "@playwright/test";
import { Page } from "@playwright/test";
import { test as base, expect } from "../../element-web-test";

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Download, type Page } from "@playwright/test";
import { Download, type Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import { viewRoomSummaryByName } from "./utils";

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Locator, type Page } from "@playwright/test";
import { Locator, type Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import { checkRoomSummaryCard, viewRoomSummaryByName } from "./utils";

View File

@@ -8,7 +8,7 @@ Please see LICENSE files in the repository root for full details.
import { type Page, expect } from "@playwright/test";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { ElementAppPage } from "../../pages/ElementAppPage";
export async function viewRoomSummaryByName(page: Page, app: ElementAppPage, name: string): Promise<void> {
await app.viewRoomByName(name);

View File

@@ -6,10 +6,10 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Page } from "@playwright/test";
import { Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { ElementAppPage } from "../../pages/ElementAppPage";
test.describe("Room Header", () => {
test.use({

View File

@@ -6,9 +6,9 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type Locator, type Page } from "@playwright/test";
import { Locator, Page } from "@playwright/test";
import { type ElementAppPage } from "../../../pages/ElementAppPage";
import { ElementAppPage } from "../../../pages/ElementAppPage";
import { test as base, expect } from "../../../element-web-test";
import { SettingLevel } from "../../../../src/settings/SettingLevel";
import { Layout } from "../../../../src/settings/enums/Layout";

View File

@@ -5,7 +5,7 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
import { GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
import { test, expect } from ".";
import {
@@ -67,7 +67,7 @@ test.describe("Encryption tab", () => {
"should prompt to enter the recovery key when the secrets are not cached locally",
{ tag: "@screenshot" },
async ({ page, app, util }) => {
await verifySession(app, recoveryKey.encodedPrivateKey);
await verifySession(app, "new passphrase");
// We need to delete the cached secrets
await deleteCachedSecrets(page);
@@ -93,39 +93,4 @@ test.describe("Encryption tab", () => {
await checkDeviceIsConnectedKeyBackup(app, expectedBackupVersion, true);
},
);
test("should display the reset identity panel when the user clicks on 'Forgot recovery key?'", async ({
page,
app,
util,
}) => {
await verifySession(app, recoveryKey.encodedPrivateKey);
// We need to delete the cached secrets
await deleteCachedSecrets(page);
// The "Key storage is out sync" section is displayed and the user click on the "Forgot recovery key?" button
await util.openEncryptionTab();
const dialog = util.getEncryptionTabContent();
await dialog.getByRole("button", { name: "Forgot recovery key?" }).click();
// The user is prompted to reset their identity
await expect(dialog.getByText("Forgot your recovery key? Youll need to reset your identity.")).toBeVisible();
});
test("should warn before turning off key storage", { tag: "@screenshot" }, async ({ page, app, util }) => {
await verifySession(app, recoveryKey.encodedPrivateKey);
await util.openEncryptionTab();
await page.getByRole("checkbox", { name: "Allow key storage" }).click();
await expect(
page.getByRole("heading", { name: "Are you sure you want to turn off key storage and delete it?" }),
).toBeVisible();
await expect(util.getEncryptionTabContent()).toMatchScreenshot("delete-key-storage-confirm.png");
await page.getByRole("button", { name: "Delete key storage" }).click();
await expect(page.getByRole("checkbox", { name: "Allow key storage" })).not.toBeChecked();
});
});

View File

@@ -5,10 +5,10 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type Page } from "@playwright/test";
import { type GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
import { Page } from "@playwright/test";
import { GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
import { type ElementAppPage } from "../../../pages/ElementAppPage";
import { ElementAppPage } from "../../../pages/ElementAppPage";
import { test as base, expect } from "../../../element-web-test";
export { expect };
@@ -43,7 +43,7 @@ class Helpers {
*/
async verifyDevice(recoveryKey: GeneratedSecretStorageKey) {
// Select the security phrase
await this.page.getByRole("button", { name: "Verify with Security Key" }).click();
await this.page.getByRole("button", { name: "Verify with Security Key or Phrase" }).click();
await this.enterRecoveryKey(recoveryKey);
await this.page.getByRole("button", { name: "Done" }).click();
}
@@ -53,6 +53,9 @@ class Helpers {
* @param recoveryKey
*/
async enterRecoveryKey(recoveryKey: GeneratedSecretStorageKey) {
// Select to use recovery key
await this.page.getByRole("button", { name: "use your Security Key" }).click();
// Fill the recovery key
const dialog = this.page.locator(".mx_Dialog");
await dialog.getByRole("textbox").fill(recoveryKey.encodedPrivateKey);

View File

@@ -7,25 +7,22 @@
import { test, expect } from ".";
import { checkDeviceIsConnectedKeyBackup, createBot, verifySession } from "../../crypto/utils";
import type { GeneratedSecretStorageKey } from "matrix-js-sdk/src/crypto-api";
test.describe("Recovery section in Encryption tab", () => {
test.use({
displayName: "Alice",
});
let recoveryKey: GeneratedSecretStorageKey;
test.beforeEach(async ({ page, homeserver, credentials }) => {
// The bot bootstraps cross-signing, creates a key backup and sets up a recovery key
const res = await createBot(page, homeserver, credentials);
recoveryKey = res.recoveryKey;
await createBot(page, homeserver, credentials);
});
test(
"should change the recovery key",
{ tag: ["@screenshot", "@no-webkit"] },
async ({ page, app, homeserver, credentials, util, context }) => {
await verifySession(app, recoveryKey.encodedPrivateKey);
await verifySession(app, "new passphrase");
const dialog = await util.openEncryptionTab();
// The user can only change the recovery key
@@ -52,7 +49,7 @@ test.describe("Recovery section in Encryption tab", () => {
);
test("should setup the recovery key", { tag: ["@screenshot", "@no-webkit"] }, async ({ page, app, util }) => {
await verifySession(app, recoveryKey.encodedPrivateKey);
await verifySession(app, "new passphrase");
await util.removeSecretStorageDefaultKeyId();
// The key backup is deleted and the user needs to set it up

View File

@@ -6,7 +6,7 @@
* Please see LICENSE files in the repository root for full details.
*/
import { type Locator } from "@playwright/test";
import { Locator } from "@playwright/test";
import { test, expect } from "../../element-web-test";

View File

@@ -6,8 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Page, type Request } from "@playwright/test";
import { GenericContainer, type StartedTestContainer, Wait } from "testcontainers";
import { Page, Request } from "@playwright/test";
import { GenericContainer, StartedTestContainer, Wait } from "testcontainers";
import { test as base, expect } from "../../element-web-test";
import type { ElementAppPage } from "../../pages/ElementAppPage";

View File

@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
import type { Locator, Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import type { Preset, ICreateRoomOpts } from "matrix-js-sdk/src/matrix";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { isDendrite } from "../../plugins/homeserver/dendrite";
async function openSpaceCreateMenu(page: Page): Promise<Locator> {

View File

@@ -6,14 +6,14 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type JSHandle, type Locator, type Page } from "@playwright/test";
import { JSHandle, Locator, Page } from "@playwright/test";
import type { MatrixEvent, IContent, Room } from "matrix-js-sdk/src/matrix";
import { test as base, expect } from "../../../element-web-test";
import { type Bot } from "../../../pages/bot";
import { type Client } from "../../../pages/client";
import { type ElementAppPage } from "../../../pages/ElementAppPage";
import { type Credentials } from "../../../plugins/homeserver";
import { Bot } from "../../../pages/bot";
import { Client } from "../../../pages/client";
import { ElementAppPage } from "../../../pages/ElementAppPage";
import { Credentials } from "../../../plugins/homeserver";
type RoomRef = { name: string; roomId: string };

View File

@@ -13,8 +13,8 @@ import type { ISendEventResponse, EventType, MsgType } from "matrix-js-sdk/src/m
import { test, expect } from "../../element-web-test";
import { SettingLevel } from "../../../src/settings/SettingLevel";
import { Layout } from "../../../src/settings/enums/Layout";
import { type Client } from "../../pages/client";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { Client } from "../../pages/client";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { Bot } from "../../pages/bot";
// The avatar size used in the timeline

View File

@@ -12,7 +12,7 @@ import { uniqueId } from "lodash";
import { expect, type Page } from "@playwright/test";
import type { ClientEvent, MatrixEvent, Room } from "matrix-js-sdk/src/matrix";
import { type Client } from "../pages/client";
import { Client } from "../pages/client";
/**
* Resolves when room state matches predicate.

View File

@@ -10,8 +10,8 @@ import * as fs from "node:fs";
import type { Page } from "@playwright/test";
import { test, expect } from "../../element-web-test";
import { type ElementAppPage } from "../../pages/ElementAppPage";
import { type Credentials } from "../../plugins/homeserver";
import { ElementAppPage } from "../../pages/ElementAppPage";
import { Credentials } from "../../plugins/homeserver";
import type { UserWidget } from "../../../src/utils/WidgetUtils-types.ts";
const STICKER_PICKER_WIDGET_ID = "fake-sticker-picker";

View File

@@ -11,7 +11,7 @@ Please see LICENSE files in the repository root for full details.
import type { IWidget } from "matrix-widget-api/src/interfaces/IWidget";
import type { MatrixEvent, RoomStateEvent } from "matrix-js-sdk/src/matrix";
import { test, expect } from "../../element-web-test";
import { type Client } from "../../pages/client";
import { Client } from "../../pages/client";
const DEMO_WIDGET_ID = "demo-widget-id";
const DEMO_WIDGET_NAME = "Demo Widget";

View File

@@ -8,12 +8,12 @@ Please see LICENSE files in the repository root for full details.
import {
expect as baseExpect,
type Locator,
type Page,
type ExpectMatcherState,
type ElementHandle,
type PlaywrightTestArgs,
type Fixtures as _Fixtures,
Locator,
Page,
ExpectMatcherState,
ElementHandle,
PlaywrightTestArgs,
Fixtures as _Fixtures,
} from "@playwright/test";
import { sanitizeForFilePath } from "playwright-core/lib/utils";
import AxeBuilder from "@axe-core/playwright";
@@ -21,13 +21,13 @@ import _ from "lodash";
import { extname } from "node:path";
import type { IConfigOptions } from "../src/IConfigOptions";
import { type Credentials } from "./plugins/homeserver";
import { Credentials } from "./plugins/homeserver";
import { ElementAppPage } from "./pages/ElementAppPage";
import { Crypto } from "./pages/crypto";
import { Toasts } from "./pages/toasts";
import { Bot, type CreateBotOpts } from "./pages/bot";
import { Bot, CreateBotOpts } from "./pages/bot";
import { Webserver } from "./plugins/webserver";
import { type Options, type Services, test as base } from "./services.ts";
import { Options, Services, test as base } from "./services.ts";
// Enable experimental service worker support
// See https://playwright.dev/docs/service-workers-experimental#how-to-enable

View File

@@ -5,8 +5,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type BrowserContext, type Page, type TestInfo } from "@playwright/test";
import { type Readable } from "stream";
import { BrowserContext, Page, TestInfo } from "@playwright/test";
import { Readable } from "stream";
import stripAnsi from "strip-ansi";
export class Logger {

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type JSHandle, type Page } from "@playwright/test";
import { JSHandle, Page } from "@playwright/test";
import { uniqueId } from "lodash";
import { type MatrixClient } from "matrix-js-sdk/src/matrix";
@@ -41,10 +41,6 @@ export interface CreateBotOpts {
* Whether to bootstrap the secret storage
*/
bootstrapSecretStorage?: boolean;
/**
* Whether to use a passphrase when creating the recovery key
*/
usePassphrase?: boolean;
}
const defaultCreateBotOptions = {
@@ -52,7 +48,6 @@ const defaultCreateBotOptions = {
autoAcceptInvites: true,
startClient: true,
bootstrapCrossSigning: true,
usePassphrase: false,
} satisfies CreateBotOpts;
type ExtendedMatrixClient = MatrixClient & { __playwright_recovery_key: GeneratedSecretStorageKey };
@@ -211,8 +206,8 @@ export class Bot extends Client {
}
if (this.opts.bootstrapSecretStorage) {
await clientHandle.evaluate(async (cli, usePassphrase) => {
const passphrase = usePassphrase ? "new passphrase" : undefined;
await clientHandle.evaluate(async (cli) => {
const passphrase = "new passphrase";
const recoveryKey = await cli.getCrypto().createRecoveryKeyFromPassphrase(passphrase);
Object.assign(cli, { __playwright_recovery_key: recoveryKey });
@@ -221,7 +216,7 @@ export class Bot extends Client {
setupNewKeyBackup: true,
createSecretStorageKey: () => Promise.resolve(recoveryKey),
});
}, this.opts.usePassphrase);
});
}
return clientHandle;

View File

@@ -6,8 +6,8 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type JSHandle, type Page } from "@playwright/test";
import { type PageFunctionOn } from "playwright-core/types/structs";
import { JSHandle, Page } from "@playwright/test";
import { PageFunctionOn } from "playwright-core/types/structs";
import { Network } from "./network";
import type {
@@ -25,10 +25,9 @@ import type {
StateEvents,
TimelineEvents,
AccountDataEvents,
EmptyObject,
} from "matrix-js-sdk/src/matrix";
import type { RoomMessageEventContent } from "matrix-js-sdk/src/types";
import { type Credentials } from "../plugins/homeserver";
import { Credentials } from "../plugins/homeserver";
export class Client {
public network: Network;
@@ -364,7 +363,7 @@ export class Client {
event: JSHandle<MatrixEvent>,
receiptType?: ReceiptType,
unthreaded?: boolean,
): Promise<EmptyObject> {
): Promise<{}> {
const client = await this.prepareClient();
return client.evaluate(
(client, { event, receiptType, unthreaded }) => {
@@ -387,7 +386,7 @@ export class Client {
* @return {Promise} Resolves: {} an empty object.
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
public async setDisplayName(name: string): Promise<EmptyObject> {
public async setDisplayName(name: string): Promise<{}> {
const client = await this.prepareClient();
return client.evaluate(async (cli: MatrixClient, name) => cli.setDisplayName(name), name);
}
@@ -398,7 +397,7 @@ export class Client {
* @return {Promise} Resolves: {} an empty object.
* @return {module:http-api.MatrixError} Rejects: with an error response.
*/
public async setAvatarUrl(url: string): Promise<EmptyObject> {
public async setAvatarUrl(url: string): Promise<{}> {
const client = await this.prepareClient();
return client.evaluate(async (cli: MatrixClient, url) => cli.setAvatarUrl(url), url);
}

View File

@@ -6,9 +6,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type APIRequestContext, type Page, expect } from "@playwright/test";
import { APIRequestContext, Page, expect } from "@playwright/test";
import { type HomeserverInstance } from "../plugins/homeserver";
import { HomeserverInstance } from "../plugins/homeserver";
export class Crypto {
public constructor(

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Locator, type Page } from "@playwright/test";
import { Locator, Page } from "@playwright/test";
import type { SettingLevel } from "../../src/settings/SettingLevel";

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Page, expect, type Locator } from "@playwright/test";
import { Page, expect, Locator } from "@playwright/test";
export class Toasts {
public constructor(private readonly page: Page) {}

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Options } from "../../../services.ts";
import { Options } from "../../../services.ts";
export const isDendrite = ({ homeserverType }: Options): boolean => {
return homeserverType === "dendrite" || homeserverType === "pinecone";

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type ClientServerApi } from "../utils/api.ts";
import { ClientServerApi } from "../utils/api.ts";
export interface HomeserverInstance {
readonly baseUrl: string;

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Fixtures } from "../../../element-web-test.ts";
import { Fixtures } from "../../../element-web-test.ts";
export const consentHomeserver: Fixtures = {
_homeserver: [

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Fixtures } from "../../../element-web-test.ts";
import { Fixtures } from "../../../element-web-test.ts";
export const emailHomeserver: Fixtures = {
_homeserver: [

View File

@@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
import { TestContainers } from "testcontainers";
import { OAuthServer } from "../../oauth_server";
import { type Fixtures } from "../../../element-web-test.ts";
import { Fixtures } from "../../../element-web-test.ts";
export const legacyOAuthHomeserver: Fixtures = {
oAuthServer: [

View File

@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import { MatrixAuthenticationServiceContainer } from "../../../testcontainers/mas.ts";
import { type Fixtures } from "../../../element-web-test.ts";
import { Fixtures } from "../../../element-web-test.ts";
export const masHomeserver: Fixtures = {
mas: [

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type Fixtures } from "../../../element-web-test.ts";
import { Fixtures } from "../../../element-web-test.ts";
export const uiaLongSessionTimeoutHomeserver: Fixtures = {
synapseConfig: [

View File

@@ -8,8 +8,8 @@ Please see LICENSE files in the repository root for full details.
import http from "http";
import express from "express";
import { type AddressInfo } from "net";
import { type TestInfo } from "@playwright/test";
import { AddressInfo } from "net";
import { TestInfo } from "@playwright/test";
import { randB64Bytes } from "../utils/rand.ts";

View File

@@ -5,9 +5,9 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type APIRequestContext } from "@playwright/test";
import { APIRequestContext } from "@playwright/test";
import { type Credentials } from "../homeserver";
import { Credentials } from "../homeserver";
export type Verb = "GET" | "POST" | "PUT" | "DELETE";

View File

@@ -7,7 +7,7 @@ Please see LICENSE files in the repository root for full details.
*/
import * as http from "http";
import { type AddressInfo } from "net";
import { AddressInfo } from "net";
export class Webserver {
private server?: http.Server;

View File

@@ -1,16 +0,0 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
export default class ExampleModule {
static moduleApiVersion = "^0.1.0";
constructor(api) {
this.api = api;
}
async load() {
alert("Testing module loading successful!");
}
}

View File

@@ -6,18 +6,18 @@ Please see LICENSE files in the repository root for full details.
*/
import { test as base } from "@playwright/test";
import { type MailpitClient } from "mailpit-api";
import { Network, type StartedNetwork } from "testcontainers";
import { PostgreSqlContainer, type StartedPostgreSqlContainer } from "@testcontainers/postgresql";
import { MailpitClient } from "mailpit-api";
import { Network, StartedNetwork } from "testcontainers";
import { PostgreSqlContainer, StartedPostgreSqlContainer } from "@testcontainers/postgresql";
import { type SynapseConfig, SynapseContainer } from "./testcontainers/synapse.ts";
import { SynapseConfig, SynapseContainer } from "./testcontainers/synapse.ts";
import { Logger } from "./logger.ts";
import { type StartedMatrixAuthenticationServiceContainer } from "./testcontainers/mas.ts";
import { type HomeserverContainer, type StartedHomeserverContainer } from "./testcontainers/HomeserverContainer.ts";
import { MailhogContainer, type StartedMailhogContainer } from "./testcontainers/mailpit.ts";
import { type OAuthServer } from "./plugins/oauth_server";
import { StartedMatrixAuthenticationServiceContainer } from "./testcontainers/mas.ts";
import { HomeserverContainer, StartedHomeserverContainer } from "./testcontainers/HomeserverContainer.ts";
import { MailhogContainer, StartedMailhogContainer } from "./testcontainers/mailpit.ts";
import { OAuthServer } from "./plugins/oauth_server";
import { DendriteContainer, PineconeContainer } from "./testcontainers/dendrite.ts";
import { type HomeserverType } from "./plugins/homeserver";
import { HomeserverType } from "./plugins/homeserver";
export interface TestFixtures {
mailpitClient: MailpitClient;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

View File

@@ -5,11 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type AbstractStartedContainer, type GenericContainer } from "testcontainers";
import { type APIRequestContext, type TestInfo } from "@playwright/test";
import { AbstractStartedContainer, GenericContainer } from "testcontainers";
import { APIRequestContext, TestInfo } from "@playwright/test";
import { type HomeserverInstance } from "../plugins/homeserver";
import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts";
import { HomeserverInstance } from "../plugins/homeserver";
import { StartedMatrixAuthenticationServiceContainer } from "./mas.ts";
export interface HomeserverContainer<Config> extends GenericContainer {
withConfigField(key: string, value: any): this;

View File

@@ -12,8 +12,8 @@ import { set } from "lodash";
import { randB64Bytes } from "../plugins/utils/rand.ts";
import { StartedSynapseContainer } from "./synapse.ts";
import { deepCopy } from "../plugins/utils/object.ts";
import { type HomeserverContainer } from "./HomeserverContainer.ts";
import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts";
import { HomeserverContainer } from "./HomeserverContainer.ts";
import { StartedMatrixAuthenticationServiceContainer } from "./mas.ts";
const DEFAULT_CONFIG = {
version: 2,

View File

@@ -5,7 +5,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { AbstractStartedContainer, GenericContainer, type StartedTestContainer, Wait } from "testcontainers";
import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait } from "testcontainers";
import { MailpitClient } from "mailpit-api";
export class MailhogContainer extends GenericContainer {

View File

@@ -5,19 +5,13 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import {
AbstractStartedContainer,
GenericContainer,
type StartedTestContainer,
Wait,
type ExecResult,
} from "testcontainers";
import { type StartedPostgreSqlContainer } from "@testcontainers/postgresql";
import { AbstractStartedContainer, GenericContainer, StartedTestContainer, Wait, ExecResult } from "testcontainers";
import { StartedPostgreSqlContainer } from "@testcontainers/postgresql";
import * as YAML from "yaml";
import { getFreePort } from "../plugins/utils/port.ts";
import { deepCopy } from "../plugins/utils/object.ts";
import { type Credentials } from "../plugins/homeserver";
import { Credentials } from "../plugins/homeserver";
const DEFAULT_CONFIG = {
http: {

View File

@@ -5,27 +5,21 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import {
AbstractStartedContainer,
GenericContainer,
type RestartOptions,
type StartedTestContainer,
Wait,
} from "testcontainers";
import { type APIRequestContext, type TestInfo } from "@playwright/test";
import { AbstractStartedContainer, GenericContainer, RestartOptions, StartedTestContainer, Wait } from "testcontainers";
import { APIRequestContext, TestInfo } from "@playwright/test";
import crypto from "node:crypto";
import * as YAML from "yaml";
import { set } from "lodash";
import { getFreePort } from "../plugins/utils/port.ts";
import { randB64Bytes } from "../plugins/utils/rand.ts";
import { type Credentials } from "../plugins/homeserver";
import { Credentials } from "../plugins/homeserver";
import { deepCopy } from "../plugins/utils/object.ts";
import { type HomeserverContainer, type StartedHomeserverContainer } from "./HomeserverContainer.ts";
import { type StartedMatrixAuthenticationServiceContainer } from "./mas.ts";
import { Api, ClientServerApi, type Verb } from "../plugins/utils/api.ts";
import { HomeserverContainer, StartedHomeserverContainer } from "./HomeserverContainer.ts";
import { StartedMatrixAuthenticationServiceContainer } from "./mas.ts";
import { Api, ClientServerApi, Verb } from "../plugins/utils/api.ts";
const TAG = "develop@sha256:097ebca1226a0946f83f32c2b7f14fadaaa2ff36a4313cc3900aa1db7b2162f5";
const TAG = "develop@sha256:098126c6be750dffaff5bd19db254609aadaf34f76c70f2dca9821cb12428613";
const DEFAULT_CONFIG = {
server_name: "localhost",

View File

@@ -48,7 +48,6 @@
@import "./components/views/settings/devices/_FilteredDeviceListHeader.pcss";
@import "./components/views/settings/devices/_SecurityRecommendations.pcss";
@import "./components/views/settings/devices/_SelectableDeviceTile.pcss";
@import "./components/views/settings/encryption/_KeyStoragePanel.pcss";
@import "./components/views/settings/shared/_SettingsSubsection.pcss";
@import "./components/views/settings/shared/_SettingsSubsectionHeading.pcss";
@import "./components/views/spaces/_QuickThemeSwitcher.pcss";
@@ -358,9 +357,8 @@
@import "./views/settings/_UserProfileSettings.pcss";
@import "./views/settings/encryption/_AdvancedPanel.pcss";
@import "./views/settings/encryption/_ChangeRecoveryKey.pcss";
@import "./views/settings/encryption/_DestructiveComponent.pcss";
@import "./views/settings/encryption/_EncryptionCard.pcss";
@import "./views/settings/encryption/_RecoveryPanelOutOfSync.pcss";
@import "./views/settings/encryption/_ResetIdentityPanel.pcss";
@import "./views/settings/tabs/_SettingsBanner.pcss";
@import "./views/settings/tabs/_SettingsIndent.pcss";
@import "./views/settings/tabs/_SettingsSection.pcss";

View File

@@ -1,3 +0,0 @@
.mx_KeyBackupPanel_toggleRow {
flex-direction: row;
}

View File

@@ -1,11 +0,0 @@
/*
* Copyright 2025 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
* Please see LICENSE files in the repository root for full details.
*/
.mx_RecoveryPanelOutOfSync {
display: flex;
gap: var(--cpd-space-2x);
}

View File

@@ -5,11 +5,8 @@
* Please see LICENSE files in the repository root for full details.
*/
/**
* Shared by multiple components that confirm a destructive action in the user settings dialog.
*/
.mx_DestructiveComponent {
.mx_DestructiveComponent_content {
.mx_ResetIdentityPanel {
.mx_ResetIdentityPanel_content {
display: flex;
flex-direction: column;
gap: var(--cpd-space-3x);
@@ -20,7 +17,7 @@
}
}
.mx_DestructiveComponent_footer {
.mx_ResetIdentityPanel_footer {
display: flex;
flex-direction: column;
gap: var(--cpd-space-4x);

View File

@@ -72,6 +72,13 @@ if [[ "$head" == *":"* ]]; then
fi
clone ${TRY_ORG} $defrepo ${TRY_BRANCH}
# For merge queue runs we need to extract the temporary branch name
# the ref_name will look like `gh-readonly-queue/<branch>/pr-<number>-<sha>`
if [[ "$GITHUB_EVENT_NAME" == "merge_group" ]]; then
withoutPrefix=${GITHUB_REF_NAME#gh-readonly-queue/}
clone $deforg $defrepo ${withoutPrefix%%/pr-*}
fi
# Try the target branch of the push or PR.
if [ -n "$GITHUB_BASE_REF" ]; then
clone $deforg $defrepo $GITHUB_BASE_REF

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type JSXElementConstructor } from "react";
import { JSXElementConstructor } from "react";
export type { NonEmptyArray, XOR, Writeable } from "matrix-js-sdk/src/matrix";

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import type * as commonmark from "commonmark";
import * as commonmark from "commonmark";
declare module "commonmark" {
export type Attr = [key: string, value: string];

View File

@@ -18,7 +18,6 @@ declare module "diff-dom" {
newValue: HTMLElement | string;
}
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
interface IOpts {}
export class DiffDOM {

View File

@@ -10,43 +10,41 @@ Please see LICENSE files in the repository root for full details.
import "matrix-js-sdk/src/@types/global"; // load matrix-js-sdk's type extensions first
import "@types/modernizr";
import type { ModuleLoader } from "@element-hq/element-web-module-api";
import type { logger } from "matrix-js-sdk/src/logger";
import type ContentMessages from "../ContentMessages";
import { type IMatrixClientPeg } from "../MatrixClientPeg";
import type ToastStore from "../stores/ToastStore";
import type DeviceListener from "../DeviceListener";
import { type RoomListStore } from "../stores/room-list/Interface";
import { type PlatformPeg } from "../PlatformPeg";
import type RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore";
import { type IntegrationManagers } from "../integrations/IntegrationManagers";
import { type ModalManager } from "../Modal";
import type SettingsStore from "../settings/SettingsStore";
import { type Notifier } from "../Notifier";
import type RightPanelStore from "../stores/right-panel/RightPanelStore";
import type WidgetStore from "../stores/WidgetStore";
import type LegacyCallHandler from "../LegacyCallHandler";
import type UserActivity from "../UserActivity";
import { type ModalWidgetStore } from "../stores/ModalWidgetStore";
import { type WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
import type VoipUserMapper from "../VoipUserMapper";
import { type SpaceStoreClass } from "../stores/spaces/SpaceStore";
import type TypingStore from "../stores/TypingStore";
import { type EventIndexPeg } from "../indexing/EventIndexPeg";
import { type VoiceRecordingStore } from "../stores/VoiceRecordingStore";
import type PerformanceMonitor from "../performance";
import type UIStore from "../stores/UIStore";
import { type SetupEncryptionStore } from "../stores/SetupEncryptionStore";
import { type RoomScrollStateStore } from "../stores/RoomScrollStateStore";
import { type ConsoleLogger, type IndexedDBLogStore } from "../rageshake/rageshake";
import type ActiveWidgetStore from "../stores/ActiveWidgetStore";
import type AutoRageshakeStore from "../stores/AutoRageshakeStore";
import { type IConfigOptions } from "../IConfigOptions";
import { type MatrixDispatcher } from "../dispatcher/dispatcher";
import { type DeepReadonly } from "./common";
import type MatrixChat from "../components/structures/MatrixChat";
import { type InitialCryptoSetupStore } from "../stores/InitialCryptoSetupStore";
import { type ModuleApiType } from "../modules/Api.ts";
import ContentMessages from "../ContentMessages";
import { IMatrixClientPeg } from "../MatrixClientPeg";
import ToastStore from "../stores/ToastStore";
import DeviceListener from "../DeviceListener";
import { RoomListStore } from "../stores/room-list/Interface";
import { PlatformPeg } from "../PlatformPeg";
import RoomListLayoutStore from "../stores/room-list/RoomListLayoutStore";
import { IntegrationManagers } from "../integrations/IntegrationManagers";
import { ModalManager } from "../Modal";
import SettingsStore from "../settings/SettingsStore";
import { Notifier } from "../Notifier";
import RightPanelStore from "../stores/right-panel/RightPanelStore";
import WidgetStore from "../stores/WidgetStore";
import LegacyCallHandler from "../LegacyCallHandler";
import UserActivity from "../UserActivity";
import { ModalWidgetStore } from "../stores/ModalWidgetStore";
import { WidgetLayoutStore } from "../stores/widgets/WidgetLayoutStore";
import VoipUserMapper from "../VoipUserMapper";
import { SpaceStoreClass } from "../stores/spaces/SpaceStore";
import TypingStore from "../stores/TypingStore";
import { EventIndexPeg } from "../indexing/EventIndexPeg";
import { VoiceRecordingStore } from "../stores/VoiceRecordingStore";
import PerformanceMonitor from "../performance";
import UIStore from "../stores/UIStore";
import { SetupEncryptionStore } from "../stores/SetupEncryptionStore";
import { RoomScrollStateStore } from "../stores/RoomScrollStateStore";
import { ConsoleLogger, IndexedDBLogStore } from "../rageshake/rageshake";
import ActiveWidgetStore from "../stores/ActiveWidgetStore";
import AutoRageshakeStore from "../stores/AutoRageshakeStore";
import { IConfigOptions } from "../IConfigOptions";
import { MatrixDispatcher } from "../dispatcher/dispatcher";
import { DeepReadonly } from "./common";
import MatrixChat from "../components/structures/MatrixChat";
import { InitialCryptoSetupStore } from "../stores/InitialCryptoSetupStore";
/* eslint-disable @typescript-eslint/naming-convention */
@@ -124,8 +122,6 @@ declare global {
mxRoomScrollStateStore?: RoomScrollStateStore;
mxActiveWidgetStore?: ActiveWidgetStore;
mxOnRecaptchaLoaded?: () => void;
mxModuleLoader: ModuleLoader;
mxModuleApi: ModuleApiType;
// electron-only
electron?: Electron;

View File

@@ -11,7 +11,6 @@ import type { BLURHASH_FIELD } from "../utils/image-media";
import type { JitsiCallMemberEventType, JitsiCallMemberContent } from "../call-types";
import type { ILayoutStateEvent, WIDGET_LAYOUT_EVENT_TYPE } from "../stores/widgets/types";
import type { EncryptedFile } from "matrix-js-sdk/src/types";
import type { EmptyObject } from "matrix-js-sdk/src/matrix";
import type { DeviceClientInformation } from "../utils/device/types.ts";
import type { UserWidget } from "../utils/WidgetUtils-types.ts";
@@ -36,7 +35,7 @@ declare module "matrix-js-sdk/src/types" {
[JitsiCallMemberEventType]: JitsiCallMemberContent;
// Unstable widgets state events
"im.vector.modular.widgets": IWidget | EmptyObject;
"im.vector.modular.widgets": IWidget | {};
[WIDGET_LAYOUT_EVENT_TYPE]: ILayoutStateEvent;
// Element custom state events
@@ -105,6 +104,6 @@ declare module "matrix-js-sdk/src/types" {
// https://github.com/matrix-org/matrix-doc/pull/3246
waveform?: number[];
};
"org.matrix.msc3245.voice"?: EmptyObject;
"org.matrix.msc3245.voice"?: {};
}
}

View File

@@ -6,13 +6,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type PropsWithChildren } from "react";
import type React from "react";
import React, { PropsWithChildren } from "react";
declare module "react" {
// Fix forwardRef types for Generic components - https://stackoverflow.com/a/58473012
function forwardRef<T, P extends object>(
function forwardRef<T, P = {}>(
render: (props: PropsWithChildren<P>, ref: React.ForwardedRef<T>) => React.ReactElement | null,
): (props: P & React.RefAttributes<T>) => React.ReactElement | null;

View File

@@ -9,23 +9,21 @@ Please see LICENSE files in the repository root for full details.
*/
import {
type IAddThreePidOnlyBody,
type IRequestMsisdnTokenResponse,
type IRequestTokenResponse,
type MatrixClient,
IAddThreePidOnlyBody,
IRequestMsisdnTokenResponse,
IRequestTokenResponse,
MatrixClient,
MatrixError,
HTTPError,
type IThreepid,
type UIAResponse,
IThreepid,
UIAResponse,
} from "matrix-js-sdk/src/matrix";
import Modal from "./Modal";
import { _t, UserFriendlyError } from "./languageHandler";
import IdentityAuthClient from "./IdentityAuthClient";
import { SSOAuthEntry } from "./components/views/auth/InteractiveAuthEntryComponents";
import InteractiveAuthDialog, {
type InteractiveAuthDialogProps,
} from "./components/views/dialogs/InteractiveAuthDialog";
import InteractiveAuthDialog, { InteractiveAuthDialogProps } from "./components/views/dialogs/InteractiveAuthDialog";
function getIdServerDomain(matrixClient: MatrixClient): string {
const idBaseUrl = matrixClient.getIdentityServerUrl(true);
@@ -251,7 +249,6 @@ export default class AddThreepid {
* @param {{type: string, session?: string}} auth UI auth object
* @return {Promise<Object>} Response from /3pid/add call (in current spec, an empty object)
*/
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
private makeAddThreepidOnlyRequest = (auth?: IAddThreePidOnlyBody["auth"] | null): Promise<{}> => {
return this.matrixClient.addThreePidOnly({
sid: this.sessionId!,

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import React, { type ReactNode, Suspense } from "react";
import React, { ReactNode, Suspense } from "react";
import { _t } from "./languageHandler";
import BaseDialog from "./components/views/dialogs/BaseDialog";

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { type RoomMember, type User, type Room, type ResizeMethod } from "matrix-js-sdk/src/matrix";
import { RoomMember, User, Room, ResizeMethod } from "matrix-js-sdk/src/matrix";
import { useIdColorHash } from "@vector-im/compound-web";
import DMRoomMap from "./utils/DMRoomMap";

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