Merge branch 'develop' into mention-text-and-pills-ux

This commit is contained in:
taffyko 2024-11-15 14:43:30 -08:00
commit 3702cc03d7
506 changed files with 6225 additions and 7447 deletions

View file

@ -1,60 +0,0 @@
module.exports = {
plugins: ["matrix-org"],
extends: ["./.eslintrc.js"],
parserOptions: {
project: ["./tsconfig.module_system.json"],
},
overrides: [
{
files: ["module_system/**/*.{ts,tsx}"],
extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"],
// NOTE: These rules are frozen and new rules should not be added here.
// New changes belong in https://github.com/matrix-org/eslint-plugin-matrix-org/
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
// We disable this while we're transitioning
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
// Ban matrix-js-sdk/src imports in favour of matrix-js-sdk/src/matrix imports to prevent unleashing hell.
"no-restricted-imports": [
"error",
{
paths: [
{
name: "matrix-js-sdk",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/src",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/src/",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/src/index",
message: "Please use matrix-js-sdk/src/matrix instead",
},
],
patterns: [
{
group: ["matrix-js-sdk/lib", "matrix-js-sdk/lib/", "matrix-js-sdk/lib/**"],
message: "Please use matrix-js-sdk/src/* instead",
},
],
},
],
},
},
],
};

View file

@ -266,6 +266,63 @@ module.exports = {
parserOptions: { parserOptions: {
project: ["./playwright/tsconfig.json"], project: ["./playwright/tsconfig.json"],
}, },
rules: {
"react-hooks/rules-of-hooks": ["off"],
},
},
{
files: ["module_system/**/*.{ts,tsx}"],
parserOptions: {
project: ["./tsconfig.module_system.json"],
},
extends: ["plugin:matrix-org/typescript", "plugin:matrix-org/react"],
// NOTE: These rules are frozen and new rules should not be added here.
// New changes belong in https://github.com/matrix-org/eslint-plugin-matrix-org/
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
// We disable this while we're transitioning
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
// Ban matrix-js-sdk/src imports in favour of matrix-js-sdk/src/matrix imports to prevent unleashing hell.
"no-restricted-imports": [
"error",
{
paths: [
{
name: "matrix-js-sdk",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/src",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/src/",
message: "Please use matrix-js-sdk/src/matrix instead",
},
{
name: "matrix-js-sdk/src/index",
message: "Please use matrix-js-sdk/src/matrix instead",
},
],
patterns: [
{
group: ["matrix-js-sdk/lib", "matrix-js-sdk/lib/", "matrix-js-sdk/lib/**"],
message: "Please use matrix-js-sdk/src/* instead",
},
],
},
],
},
}, },
], ],
settings: { settings: {

View file

@ -21,13 +21,13 @@ jobs:
fetch-depth: 0 # needed for docker-package to be able to calculate the version fetch-depth: 0 # needed for docker-package to be able to calculate the version
- name: Install Cosign - name: Install Cosign
uses: sigstore/cosign-installer@4959ce089c160fddf62f7b42464195ba1a56d382 # v3 uses: sigstore/cosign-installer@dc72c7d5c4d10cd6bcb8cf6e3fd625a9e5e537da # v3
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3 uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3 uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3
with: with:
install: true install: true

View file

@ -15,7 +15,7 @@ jobs:
report: report:
if: github.event.workflow_run.conclusion != 'cancelled' if: github.event.workflow_run.conclusion != 'cancelled'
name: Report results name: Report results
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
environment: Netlify environment: Netlify
permissions: permissions:
statuses: write statuses: write

View file

@ -36,7 +36,7 @@ env:
jobs: jobs:
build: build:
name: "Build Element-Web" name: "Build Element-Web"
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
if: inputs.skip != true if: inputs.skip != true
steps: steps:
- name: Checkout code - name: Checkout code
@ -69,7 +69,6 @@ jobs:
VERSION: "${{ steps.layered_build.outputs.VERSION }}" VERSION: "${{ steps.layered_build.outputs.VERSION }}"
run: | run: |
yarn build yarn build
echo $VERSION > webapp/version
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@ -144,7 +143,7 @@ jobs:
name: end-to-end-tests name: end-to-end-tests
needs: playwright needs: playwright
if: always() if: always()
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
if: inputs.skip != true if: inputs.skip != true

View file

@ -9,7 +9,7 @@ on:
jobs: jobs:
deploy: deploy:
if: github.event.workflow_run.conclusion != 'cancelled' && github.event.workflow_run.event == 'pull_request' if: github.event.workflow_run.conclusion != 'cancelled' && github.event.workflow_run.event == 'pull_request'
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
environment: Netlify environment: Netlify
steps: steps:
- name: 📝 Create Deployment - name: 📝 Create Deployment

View file

@ -5,7 +5,7 @@ on:
- cron: "0 6 * * *" # Every day at 6am UTC - cron: "0 6 * * *" # Every day at 6am UTC
jobs: jobs:
update: update:
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4

View file

@ -5,7 +5,7 @@ on:
jobs: jobs:
check_base_branch: check_base_branch:
name: Check PR base branch name: Check PR base branch
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/github-script@v7 - uses: actions/github-script@v7
with: with:

View file

@ -49,7 +49,7 @@ jobs:
ref: master ref: master
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10 wait-interval: 10
check-name: "Docker Buildx (vanilla)" check-name: "Docker Buildx"
allowed-conclusions: success allowed-conclusions: success
- name: Wait for debian package - name: Wait for debian package

View file

@ -20,6 +20,9 @@ on:
jobs: jobs:
prepare: prepare:
runs-on: ubuntu-24.04 runs-on: ubuntu-24.04
env:
# The order is specified bottom-up to avoid any races for allchange
REPOS: matrix-js-sdk element-web element-desktop
steps: steps:
- name: Checkout Element Desktop - name: Checkout Element Desktop
uses: actions/checkout@v4 uses: actions/checkout@v4

View file

@ -34,27 +34,6 @@ jobs:
- name: Typecheck - name: Typecheck
run: "yarn run lint:types" run: "yarn run lint:types"
- name: Switch js-sdk to release mode
working-directory: node_modules/matrix-js-sdk
run: |
scripts/switch_package_to_release.cjs
yarn install
yarn run build:compile
yarn run build:types
- name: Typecheck (release mode)
run: "yarn run lint:types"
# Temporary while we directly import matrix-js-sdk/src/* which means we need
# certain @types/* packages to make sense of matrix-js-sdk types.
#- name: Typecheck (release mode; no yarn link)
# if: github.event_name != 'pull_request' && github.ref_name != 'master'
# run: |
# yarn unlink matrix-js-sdk
# yarn add github:matrix-org/matrix-js-sdk#develop
# yarn install --force
# yarn run lint:types
i18n_lint: i18n_lint:
name: "i18n Check" name: "i18n Check"
uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main
@ -71,7 +50,7 @@ jobs:
rethemendex_lint: rethemendex_lint:
name: "Rethemendex Check" name: "Rethemendex Check"
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -144,6 +123,12 @@ jobs:
cache: "yarn" cache: "yarn"
node-version: "lts/*" node-version: "lts/*"
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Run linter
run: "yarn run lint:knip"
- name: Install Deps - name: Install Deps
run: "scripts/layered.sh" run: "scripts/layered.sh"

View file

@ -29,7 +29,7 @@ env:
jobs: jobs:
jest: jest:
name: Jest name: Jest
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@ -93,7 +93,7 @@ jobs:
name: jest-tests name: jest-tests
needs: jest needs: jest
if: always() if: always()
runs-on: ubuntu-22.04 runs-on: ubuntu-24.04
steps: steps:
- if: needs.jest.result != 'skipped' && needs.jest.result != 'success' - if: needs.jest.result != 'skipped' && needs.jest.result != 'success'
run: exit 1 run: exit 1

View file

@ -2,6 +2,6 @@
"*": "prettier --write", "*": "prettier --write",
"src/**/*.(ts|tsx)": ["eslint --fix"], "src/**/*.(ts|tsx)": ["eslint --fix"],
"scripts/**/*.(ts|tsx)": ["eslint --fix"], "scripts/**/*.(ts|tsx)": ["eslint --fix"],
"module_system/**/*.(ts|tsx)": ["eslint --fix --config .eslintrc-module_system.js module_system"], "module_system/**/*.(ts|tsx)": ["eslint --fix"],
"*.pcss": ["stylelint --fix"] "*.pcss": ["stylelint --fix"]
} }

View file

@ -1 +1 @@
20 22

View file

@ -1,6 +1,6 @@
module.exports = { module.exports = {
extends: ["stylelint-config-standard"], extends: ["stylelint-config-standard"],
customSyntax: require("postcss-scss"), customSyntax: "postcss-scss",
plugins: ["stylelint-scss"], plugins: ["stylelint-scss"],
rules: { rules: {
"comment-empty-line-before": null, "comment-empty-line-before": null,

View file

@ -1,3 +1,76 @@
Changes in [1.11.85](https://github.com/element-hq/element-web/releases/tag/v1.11.85) (2024-11-12)
==================================================================================================
# Security
- Fixes for [CVE-2024-51750](https://www.cve.org/CVERecord?id=CVE-2024-51750) / [GHSA-w36j-v56h-q9pc](https://github.com/element-hq/element-web/security/advisories/GHSA-w36j-v56h-q9pc)
- Fixes for [CVE-2024-51749](https://www.cve.org/CVERecord?id=CVE-2024-51749) / [GHSA-5486-384g-mcx2](https://github.com/element-hq/element-web/security/advisories/GHSA-5486-384g-mcx2)
- Update JS SDK with the fixes for [CVE-2024-50336](https://www.cve.org/CVERecord?id=CVE-2024-50336) / [GHSA-xvg8-m4x3-w6xr](https://github.com/matrix-org/matrix-js-sdk/security/advisories/GHSA-xvg8-m4x3-w6xr)
Changes in [1.11.84](https://github.com/element-hq/element-web/releases/tag/v1.11.84) (2024-11-05)
==================================================================================================
## ✨ Features
* Remove abandoned MSC3886, MSC3903, MSC3906 implementations ([#28274](https://github.com/element-hq/element-web/pull/28274)). Contributed by @t3chguy.
* Update to React 18 ([#24763](https://github.com/element-hq/element-web/pull/24763)). Contributed by @t3chguy.
* Deduplicate icons using Compound ([#28239](https://github.com/element-hq/element-web/pull/28239)). Contributed by @t3chguy.
* Replace legacy Tooltips with Compound tooltips ([#28231](https://github.com/element-hq/element-web/pull/28231)). Contributed by @t3chguy.
* Deduplicate icons using Compound Design Tokens ([#28219](https://github.com/element-hq/element-web/pull/28219)). Contributed by @t3chguy.
* Add reactions to html export ([#28210](https://github.com/element-hq/element-web/pull/28210)). Contributed by @langleyd.
* Remove feature\_dehydration ([#28173](https://github.com/element-hq/element-web/pull/28173)). Contributed by @florianduros.
## 🐛 Bug Fixes
* Remove upgrade encryption in `DeviceListener` and `SetupEncryptionToast` ([#28299](https://github.com/element-hq/element-web/pull/28299)). Contributed by @florianduros.
* Fix 'remove alias' button in room settings ([#28269](https://github.com/element-hq/element-web/pull/28269)). Contributed by @Dev-Gurjar.
* Add back unencrypted path in `StopGapWidgetDriver.sendToDevice` ([#28295](https://github.com/element-hq/element-web/pull/28295)). Contributed by @florianduros.
* Fix other devices not being decorated as such ([#28279](https://github.com/element-hq/element-web/pull/28279)). Contributed by @t3chguy.
* Fix pill contrast in invitation dialog ([#28250](https://github.com/element-hq/element-web/pull/28250)). Contributed by @florianduros.
* Close right panel chat when minimising maximised voip widget ([#28241](https://github.com/element-hq/element-web/pull/28241)). Contributed by @t3chguy.
* Fix develop changelog parsing ([#28232](https://github.com/element-hq/element-web/pull/28232)). Contributed by @t3chguy.
* Fix Ctrl+F shortcut not working with minimised room summary card ([#28223](https://github.com/element-hq/element-web/pull/28223)). Contributed by @t3chguy.
* Fix network dropdown missing checkbox \& aria-checked ([#28220](https://github.com/element-hq/element-web/pull/28220)). Contributed by @t3chguy.
Changes in [1.11.83](https://github.com/element-hq/element-web/releases/tag/v1.11.83) (2024-10-29)
==================================================================================================
## ✨ Features
* Enable Element Call by default on release instances ([#28314](https://github.com/element-hq/element-web/pull/28314)). Contributed by @t3chguy.
Changes in [1.11.82](https://github.com/element-hq/element-web/releases/tag/v1.11.82) (2024-10-22)
==================================================================================================
## ✨ Features
* Deduplicate more icons using Compound Design Tokens ([#132](https://github.com/element-hq/matrix-react-sdk/pull/132)). Contributed by @t3chguy.
* Always show link new device flow even if unsupported ([#147](https://github.com/element-hq/matrix-react-sdk/pull/147)). Contributed by @t3chguy.
* Update design of files list in right panel ([#144](https://github.com/element-hq/matrix-react-sdk/pull/144)). Contributed by @t3chguy.
* Remove feature\_dehydration ([#138](https://github.com/element-hq/matrix-react-sdk/pull/138)). Contributed by @florianduros.
* Upgrade emojibase-bindings and remove local handling of emoticon variations ([#127](https://github.com/element-hq/matrix-react-sdk/pull/127)). Contributed by @langleyd.
* Add support for rendering media captions ([#43](https://github.com/element-hq/matrix-react-sdk/pull/43)). Contributed by @tulir.
* Replace composer icons with Compound variants ([#123](https://github.com/element-hq/matrix-react-sdk/pull/123)). Contributed by @t3chguy.
* Tweak default right panel size to be 320px except for maximised widgets at 420px ([#110](https://github.com/element-hq/matrix-react-sdk/pull/110)). Contributed by @t3chguy.
* Add a pinned message badge under a pinned message ([#118](https://github.com/element-hq/matrix-react-sdk/pull/118)). Contributed by @florianduros.
* Ditch right panel tabs and re-add close button ([#99](https://github.com/element-hq/matrix-react-sdk/pull/99)). Contributed by @t3chguy.
* Force verification even for refreshed clients ([#44](https://github.com/element-hq/matrix-react-sdk/pull/44)). Contributed by @dbkr.
* Update emoji text, border and background colour in timeline ([#119](https://github.com/element-hq/matrix-react-sdk/pull/119)). Contributed by @florianduros.
* Disable ICE fallback based on well-known configuration ([#111](https://github.com/element-hq/matrix-react-sdk/pull/111)). Contributed by @t3chguy.
* Remove legacy room header and promote beta room header ([#105](https://github.com/element-hq/matrix-react-sdk/pull/105)). Contributed by @t3chguy.
* Respect `io.element.jitsi` `useFor1To1Calls` in well-known ([#112](https://github.com/element-hq/matrix-react-sdk/pull/112)). Contributed by @t3chguy.
* Use Compound close icon in favour of mishmash of x/close icons ([#108](https://github.com/element-hq/matrix-react-sdk/pull/108)). Contributed by @t3chguy.
## 🐛 Bug Fixes
* Correct typo in option documentation ([#28148](https://github.com/element-hq/element-web/pull/28148)). Contributed by @AndrewKvalheim.
* Revert #124 and #135 ([#139](https://github.com/element-hq/matrix-react-sdk/pull/139)). Contributed by @dbkr.
* Add aria-label to e2e icon ([#136](https://github.com/element-hq/matrix-react-sdk/pull/136)). Contributed by @florianduros.
* Fix bell icons on room list hover being black squares ([#135](https://github.com/element-hq/matrix-react-sdk/pull/135)). Contributed by @dbkr.
* Fix vertical overflow on the mobile register screen ([#137](https://github.com/element-hq/matrix-react-sdk/pull/137)). Contributed by @langleyd.
* Allow to unpin redacted event ([#98](https://github.com/element-hq/matrix-react-sdk/pull/98)). Contributed by @florianduros.
Changes in [1.11.81](https://github.com/element-hq/element-web/releases/tag/v1.11.81) (2024-10-15) Changes in [1.11.81](https://github.com/element-hq/element-web/releases/tag/v1.11.81) (2024-10-15)
================================================================================================== ==================================================================================================
This release fixes High severity vulnerability CVE-2024-47771 / GHSA-963w-49j9-gxj6 This release fixes High severity vulnerability CVE-2024-47771 / GHSA-963w-49j9-gxj6

View file

@ -1,5 +1,5 @@
# Builder # Builder
FROM --platform=$BUILDPLATFORM node:20-bullseye as builder FROM --platform=$BUILDPLATFORM node:22-bullseye as builder
# Support custom branch of the js-sdk. This also helps us build images of element-web develop. # Support custom branch of the js-sdk. This also helps us build images of element-web develop.
ARG USE_CUSTOM_SDKS=false ARG USE_CUSTOM_SDKS=false

View file

@ -1,5 +1 @@
{ {}
"src/components/views/auth/AuthFooter.tsx": "src/components/views/auth/VectorAuthFooter.tsx",
"src/components/views/auth/AuthHeaderLogo.tsx": "src/components/views/auth/VectorAuthHeaderLogo.tsx",
"src/components/views/auth/AuthPage.tsx": "src/components/views/auth/VectorAuthPage.tsx"
}

View file

@ -11,8 +11,8 @@ Customisations will be removed from the codebase in a future release.
Element Web and the React SDK support "customisation points" that can be used to Element Web and the React SDK support "customisation points" that can be used to
easily add custom logic specific to a particular deployment of Element Web. easily add custom logic specific to a particular deployment of Element Web.
An example of this is the [security customisations An example of this is the [media customisations
module](https://github.com/element-hq/element-web/blob/develop/src/customisations/Security.ts). module](https://github.com/element-hq/element-web/blob/develop/src/customisations/Media.ts).
This module in the React SDK only defines some empty functions and their types: This module in the React SDK only defines some empty functions and their types:
it does not do anything by default. it does not do anything by default.
@ -21,14 +21,14 @@ Web so that you can add your own code. Even though the default module is part of
the React SDK, you can still override it from the Element Web layer: the React SDK, you can still override it from the Element Web layer:
1. Copy the default customisation module to 1. Copy the default customisation module to
`element-web/src/customisations/YourNameSecurity.ts` `element-web/src/customisations/YourNameMedia.ts`
2. Edit customisations points and make sure export the ones you actually want to 2. Edit customisations points and make sure export the ones you actually want to
activate activate
3. Create/add an entry to `customisations.json` next to the webpack config: 3. Create/add an entry to `customisations.json` next to the webpack config:
```json ```json
{ {
"src/customisations/Security.ts": "src/customisations/YourNameSecurity.ts" "src/customisations/Media.ts": "src/customisations/YourNameMedia.ts"
} }
``` ```

View file

@ -41,7 +41,15 @@ The Docker image can be used to serve element-web as a web server. The easiest w
it is to use the prebuilt image: it is to use the prebuilt image:
```bash ```bash
docker run -p 80:80 vectorim/element-web docker run --rm -p 127.0.0.1:80:80 vectorim/element-web
```
A server can also be made available to clients outside the local host by omitting the
explicit local address as described in
[docker run documentation](https://docs.docker.com/engine/reference/commandline/run/#publish-or-expose-port--p---expose):
```bash
docker run --rm -p 80:80 vectorim/element-web
``` ```
To supply your own custom `config.json`, map a volume to `/app/config.json`. For example, To supply your own custom `config.json`, map a volume to `/app/config.json`. For example,
@ -49,7 +57,7 @@ if your custom config was located at `/etc/element-web/config.json` then your Do
would be: would be:
```bash ```bash
docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web docker run --rm -p 127.0.0.1:80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web
``` ```
To build the image yourself: To build the image yourself:

View file

@ -29,7 +29,7 @@ default theme, you would use `default_theme: "custom-Electric Blue"`.
e.g. in config.json: e.g. in config.json:
``` ```json5
"setting_defaults": { "setting_defaults": {
"custom_themes": [ "custom_themes": [
{ {
@ -59,6 +59,10 @@ e.g. in config.json:
"timeline-text-color": "#2e2f32", "timeline-text-color": "#2e2f32",
"timeline-text-secondary-color": "#61708b", "timeline-text-secondary-color": "#61708b",
"timeline-highlights-color": "#f3f8fd", "timeline-highlights-color": "#f3f8fd",
// These should both be 8 values long
"username-colors": ["#ff0000", /*...*/],
"avatar-background-colors": ["#cc0000", /*...*/]
}, },
"compound": { "compound": {
"--cpd-color-icon-accent-tertiary": "var(--cpd-color-blue-800)", "--cpd-color-icon-accent-tertiary": "var(--cpd-color-blue-800)",

View file

@ -46,5 +46,13 @@
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx", "map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx",
"setting_defaults": { "setting_defaults": {
"RustCrypto.staged_rollout_percent": 60 "RustCrypto.staged_rollout_percent": 60
},
"features": {
"feature_video_rooms": true,
"feature_group_calls": true,
"feature_element_call_video_rooms": true
},
"element_call": {
"url": "https://call.element.io"
} }
} }

View file

@ -38,7 +38,7 @@ const config: Config = {
"recorderWorkletFactory": "<rootDir>/__mocks__/empty.js", "recorderWorkletFactory": "<rootDir>/__mocks__/empty.js",
"^fetch-mock$": "<rootDir>/node_modules/fetch-mock", "^fetch-mock$": "<rootDir>/node_modules/fetch-mock",
}, },
transformIgnorePatterns: ["/node_modules/(?!matrix-js-sdk).+$"], transformIgnorePatterns: ["/node_modules/(?!(mime|matrix-js-sdk)).+$"],
collectCoverageFrom: [ collectCoverageFrom: [
"<rootDir>/src/**/*.{js,ts,tsx}", "<rootDir>/src/**/*.{js,ts,tsx}",
// getSessionLock is piped into a different JS context via stringification, and the coverage functionality is // getSessionLock is piped into a different JS context via stringification, and the coverage functionality is

53
knip.ts Normal file
View file

@ -0,0 +1,53 @@
import { KnipConfig } from "knip";
export default {
entry: [
"src/vector/index.ts",
"src/serviceworker/index.ts",
"src/workers/*.worker.ts",
"src/utils/exportUtils/exportJS.js",
"scripts/**",
"playwright/**",
"test/**",
"res/decoder-ring/**",
],
project: ["**/*.{js,ts,jsx,tsx}"],
ignore: [
"docs/**",
"res/jitsi_external_api.min.js",
// Used by jest
"__mocks__/maplibre-gl.js",
// Keep for now
"src/hooks/useLocalStorageState.ts",
"src/components/views/elements/InfoTooltip.tsx",
"src/components/views/elements/StyledCheckbox.tsx",
],
ignoreDependencies: [
// Required for `action-validator`
"@action-validator/*",
// Used for git pre-commit hooks
"husky",
// Used by jest
"babel-jest",
// Used by babel
"@babel/runtime",
"@babel/plugin-transform-class-properties",
// Referenced in PCSS
"github-markdown-css",
// False positive
"sw.js",
// Used by webpack
"buffer",
"process",
"util",
// Used by workflows
"ts-prune",
// Required due to bug in bloom-filters https://github.com/Callidon/bloom-filters/issues/75
"@types/seedrandom",
],
ignoreBinaries: [
// Used in scripts & workflows
"jq",
],
ignoreExportsUsedInFile: true,
} satisfies KnipConfig;

View file

@ -1,6 +1,6 @@
{ {
"name": "element-web", "name": "element-web",
"version": "1.11.81", "version": "1.11.85",
"description": "A feature-rich client for Matrix.org", "description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.", "author": "New Vector Ltd.",
"repository": { "repository": {
@ -35,7 +35,7 @@
"i18n:lint": "matrix-i18n-lint && prettier --log-level=silent --write src/i18n/strings/ --ignore-path /dev/null", "i18n:lint": "matrix-i18n-lint && prettier --log-level=silent --write src/i18n/strings/ --ignore-path /dev/null",
"i18n:diff": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && yarn i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json", "i18n:diff": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && yarn i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
"make-component": "node scripts/make-react-component.js", "make-component": "node scripts/make-react-component.js",
"rethemendex": "res/css/rethemendex.sh", "rethemendex": "./res/css/rethemendex.sh",
"clean": "rimraf lib webapp", "clean": "rimraf lib webapp",
"build": "yarn clean && yarn build:genfiles && yarn build:bundle", "build": "yarn clean && yarn build:genfiles && yarn build:bundle",
"build-stats": "yarn clean && yarn build:genfiles && yarn build:bundle-stats", "build-stats": "yarn clean && yarn build:genfiles && yarn build:bundle-stats",
@ -45,23 +45,20 @@
"build:bundle": "webpack --progress --mode production", "build:bundle": "webpack --progress --mode production",
"build:bundle-stats": "webpack --progress --mode production --json > webpack-stats.json", "build:bundle-stats": "webpack --progress --mode production --json > webpack-stats.json",
"build:module_system": "ts-node --project ./tsconfig.module_system.json module_system/scripts/install.ts", "build:module_system": "ts-node --project ./tsconfig.module_system.json module_system/scripts/install.ts",
"dist": "scripts/package.sh", "dist": "./scripts/package.sh",
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n modules,res \"yarn build:module_system\" \"yarn build:res\" && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js\"", "start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n modules,res \"yarn build:module_system\" \"yarn build:res\" && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js\"",
"start:https": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js --server-type https\"", "start:https": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n res,element-js \"yarn start:res\" \"yarn start:js --server-type https\"",
"start:res": "ts-node scripts/copy-res.ts -w", "start:res": "ts-node scripts/copy-res.ts -w",
"start:js": "webpack serve --output-path webapp --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js --mode development", "start:js": "webpack serve --output-path webapp --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js --mode development",
"lint": "yarn lint:types && yarn lint:js && yarn lint:style && yarn lint:workflows", "lint": "yarn lint:types && yarn lint:js && yarn lint:style && yarn lint:workflows",
"lint:js": "yarn lint:js:src && yarn lint:js:module_system", "lint:js": "eslint --max-warnings 0 src test playwright module_system && prettier --check .",
"lint:js:src": "eslint --max-warnings 0 src test playwright && prettier --check .", "lint:js-fix": "prettier --log-level=warn --write . && eslint --fix src test playwright module_system",
"lint:js:module_system": "eslint --max-warnings 0 --config .eslintrc-module_system.js module_system",
"lint:js-fix": "yarn lint:js-fix:src && yarn lint:js-fix:module_system",
"lint:js-fix:src": "prettier --log-level=warn --write . && eslint --fix src test playwright",
"lint:js-fix:module_system": "eslint --fix --config .eslintrc-module_system.js module_system",
"lint:types": "yarn lint:types:src && yarn lint:types:module_system", "lint:types": "yarn lint:types:src && yarn lint:types:module_system",
"lint:types:src": "tsc --noEmit --jsx react && tsc --noEmit --jsx react -p playwright", "lint:types:src": "tsc --noEmit --jsx react && tsc --noEmit --jsx react -p playwright",
"lint:types:module_system": "tsc --noEmit --project ./tsconfig.module_system.json", "lint:types:module_system": "tsc --noEmit --project ./tsconfig.module_system.json",
"lint:style": "stylelint \"res/css/**/*.pcss\"", "lint:style": "stylelint \"res/css/**/*.pcss\"",
"lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'", "lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'",
"lint:knip": "knip",
"test": "jest", "test": "jest",
"test:playwright": "playwright test", "test:playwright": "playwright test",
"test:playwright:open": "yarn test:playwright --ui", "test:playwright:open": "yarn test:playwright --ui",
@ -74,29 +71,28 @@
"update:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js" "update:jitsi": "curl -s https://meet.element.io/libs/external_api.min.js > ./res/jitsi_external_api.min.js"
}, },
"resolutions": { "resolutions": {
"@types/seedrandom": "3.0.8",
"oidc-client-ts": "3.1.0", "oidc-client-ts": "3.1.0",
"jwt-decode": "4.0.0", "jwt-decode": "4.0.0",
"caniuse-lite": "1.0.30001668", "caniuse-lite": "1.0.30001679",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0", "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0",
"wrap-ansi": "npm:wrap-ansi@^7.0.0" "wrap-ansi": "npm:wrap-ansi@^7.0.0"
}, },
"dependencies": { "dependencies": {
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"@formatjs/intl-segmenter": "^11.5.7", "@formatjs/intl-segmenter": "^11.5.7",
"@matrix-org/analytics-events": "^0.26.0", "@matrix-org/analytics-events": "^0.29.0",
"@matrix-org/emojibase-bindings": "^1.3.3", "@matrix-org/emojibase-bindings": "^1.3.3",
"@vector-im/matrix-wysiwyg": "2.37.13",
"@matrix-org/react-sdk-module-api": "^2.4.0", "@matrix-org/react-sdk-module-api": "^2.4.0",
"@matrix-org/spec": "^1.7.0", "@matrix-org/spec": "^1.7.0",
"@sentry/browser": "^8.0.0", "@sentry/browser": "^8.0.0",
"@vector-im/compound-design-tokens": "^1.8.0", "@vector-im/compound-design-tokens": "^2.0.1",
"@vector-im/compound-web": "^7.1.0", "@vector-im/compound-web": "^7.3.0",
"@vector-im/matrix-wysiwyg": "2.37.13",
"@zxcvbn-ts/core": "^3.0.4", "@zxcvbn-ts/core": "^3.0.4",
"@zxcvbn-ts/language-common": "^3.0.4", "@zxcvbn-ts/language-common": "^3.0.4",
"@zxcvbn-ts/language-en": "^3.0.2", "@zxcvbn-ts/language-en": "^3.0.2",
"await-lock": "^2.1.0", "await-lock": "^2.1.0",
"bloom-filters": "^3.0.1", "bloom-filters": "^3.0.3",
"blurhash": "^2.0.3", "blurhash": "^2.0.3",
"browserslist": "^4.23.2", "browserslist": "^4.23.2",
"classnames": "^2.2.6", "classnames": "^2.2.6",
@ -114,8 +110,8 @@
"highlight.js": "^11.3.1", "highlight.js": "^11.3.1",
"html-entities": "^2.0.0", "html-entities": "^2.0.0",
"is-ip": "^3.1.0", "is-ip": "^3.1.0",
"jsrsasign": "^11.0.0",
"js-xxhash": "^4.0.0", "js-xxhash": "^4.0.0",
"jsrsasign": "^11.0.0",
"jszip": "^3.7.0", "jszip": "^3.7.0",
"katex": "^0.16.0", "katex": "^0.16.0",
"linkify-element": "4.1.3", "linkify-element": "4.1.3",
@ -123,19 +119,20 @@
"linkify-string": "4.1.3", "linkify-string": "4.1.3",
"linkifyjs": "4.1.3", "linkifyjs": "4.1.3",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"maplibre-gl": "^2.0.0", "maplibre-gl": "^4.0.0",
"matrix-encrypt-attachment": "^1.0.3", "matrix-encrypt-attachment": "^1.0.3",
"matrix-events-sdk": "0.0.1", "matrix-events-sdk": "0.0.1",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-widget-api": "^1.9.0", "matrix-widget-api": "^1.10.0",
"memoize-one": "^6.0.0", "memoize-one": "^6.0.0",
"mime": "^4.0.4",
"oidc-client-ts": "^3.0.1", "oidc-client-ts": "^3.0.1",
"opus-recorder": "^8.0.3", "opus-recorder": "^8.0.3",
"pako": "^2.0.3", "pako": "^2.0.3",
"png-chunks-extract": "^1.0.0", "png-chunks-extract": "^1.0.0",
"posthog-js": "1.157.2", "posthog-js": "1.157.2",
"qrcode": "1.5.4", "qrcode": "1.5.4",
"re-resizable": "6.9.17", "re-resizable": "6.10.1",
"react": "^18.3.1", "react": "^18.3.1",
"react-beautiful-dnd": "^13.1.0", "react-beautiful-dnd": "^13.1.0",
"react-blurhash": "^0.3.0", "react-blurhash": "^0.3.0",
@ -148,18 +145,16 @@
"tar-js": "^0.3.0", "tar-js": "^0.3.0",
"temporal-polyfill": "^0.2.5", "temporal-polyfill": "^0.2.5",
"ua-parser-js": "^1.0.2", "ua-parser-js": "^1.0.2",
"uuid": "^10.0.0", "uuid": "^11.0.0",
"what-input": "^5.2.10" "what-input": "^5.2.10"
}, },
"devDependencies": { "devDependencies": {
"@action-validator/cli": "^0.6.0", "@action-validator/cli": "^0.6.0",
"@action-validator/core": "^0.6.0", "@action-validator/core": "^0.6.0",
"@axe-core/playwright": "^4.8.1", "@axe-core/playwright": "^4.8.1",
"@babel/cli": "^7.12.10",
"@babel/core": "^7.12.10", "@babel/core": "^7.12.10",
"@babel/eslint-parser": "^7.12.10", "@babel/eslint-parser": "^7.12.10",
"@babel/eslint-plugin": "^7.12.10", "@babel/eslint-plugin": "^7.12.10",
"@babel/parser": "^7.12.11",
"@babel/plugin-proposal-export-default-from": "^7.12.1", "@babel/plugin-proposal-export-default-from": "^7.12.1",
"@babel/plugin-syntax-dynamic-import": "^7.8.3", "@babel/plugin-syntax-dynamic-import": "^7.8.3",
"@babel/plugin-transform-class-properties": "^7.12.1", "@babel/plugin-transform-class-properties": "^7.12.1",
@ -172,7 +167,6 @@
"@babel/preset-env": "^7.12.11", "@babel/preset-env": "^7.12.11",
"@babel/preset-react": "^7.12.10", "@babel/preset-react": "^7.12.10",
"@babel/preset-typescript": "^7.12.7", "@babel/preset-typescript": "^7.12.7",
"@babel/register": "^7.12.10",
"@babel/runtime": "^7.12.5", "@babel/runtime": "^7.12.5",
"@casualbot/jest-sonar-reporter": "2.2.7", "@casualbot/jest-sonar-reporter": "2.2.7",
"@peculiar/webcrypto": "^1.4.3", "@peculiar/webcrypto": "^1.4.3",
@ -186,7 +180,6 @@
"@testing-library/react": "^16.0.0", "@testing-library/react": "^16.0.0",
"@testing-library/user-event": "^14.5.2", "@testing-library/user-event": "^14.5.2",
"@types/commonmark": "^0.27.4", "@types/commonmark": "^0.27.4",
"@types/content-type": "^1.1.5",
"@types/counterpart": "^0.18.1", "@types/counterpart": "^0.18.1",
"@types/css-tree": "^2.3.8", "@types/css-tree": "^2.3.8",
"@types/diff-match-patch": "^1.0.32", "@types/diff-match-patch": "^1.0.32",
@ -208,18 +201,15 @@
"@types/qrcode": "^1.3.5", "@types/qrcode": "^1.3.5",
"@types/react": "18.3.3", "@types/react": "18.3.3",
"@types/react-beautiful-dnd": "^13.0.0", "@types/react-beautiful-dnd": "^13.0.0",
"@types/react-dom": "18.3.0", "@types/react-dom": "18.3.1",
"@types/react-transition-group": "^4.4.0", "@types/react-transition-group": "^4.4.0",
"@types/sanitize-html": "2.13.0", "@types/sanitize-html": "2.13.0",
"@types/sdp-transform": "^2.4.6",
"@types/seedrandom": "3.0.8",
"@types/semver": "^7.5.8", "@types/semver": "^7.5.8",
"@types/tar-js": "^0.3.5", "@types/tar-js": "^0.3.5",
"@types/ua-parser-js": "^0.7.36", "@types/ua-parser-js": "^0.7.36",
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0", "@typescript-eslint/parser": "^8.0.0",
"axe-core": "4.10.0",
"babel-jest": "^29.0.0", "babel-jest": "^29.0.0",
"babel-loader": "^9.0.0", "babel-loader": "^9.0.0",
"babel-plugin-jsx-remove-data-test-id": "^3.0.0", "babel-plugin-jsx-remove-data-test-id": "^3.0.0",
@ -242,7 +232,7 @@
"eslint-plugin-jsx-a11y": "^6.5.1", "eslint-plugin-jsx-a11y": "^6.5.1",
"eslint-plugin-matrix-org": "^2.0.2", "eslint-plugin-matrix-org": "^2.0.2",
"eslint-plugin-react": "^7.28.0", "eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0", "eslint-plugin-react-hooks": "^5.0.0",
"eslint-plugin-unicorn": "^56.0.0", "eslint-plugin-unicorn": "^56.0.0",
"express": "^4.18.2", "express": "^4.18.2",
"fake-indexeddb": "^6.0.0", "fake-indexeddb": "^6.0.0",
@ -259,14 +249,12 @@
"jest-mock": "^29.6.2", "jest-mock": "^29.6.2",
"jest-raw-loader": "^1.0.1", "jest-raw-loader": "^1.0.1",
"jsqr": "^1.4.0", "jsqr": "^1.4.0",
"knip": "^5.36.2",
"lint-staged": "^15.0.2", "lint-staged": "^15.0.2",
"mailhog": "^4.16.0", "mailhog": "^4.16.0",
"matrix-mock-request": "^2.5.0",
"matrix-web-i18n": "^3.2.1", "matrix-web-i18n": "^3.2.1",
"mini-css-extract-plugin": "2.9.0", "mini-css-extract-plugin": "2.9.0",
"minimist": "^1.2.6", "minimist": "^1.2.6",
"mkdirp": "^3.0.0",
"mocha-junit-reporter": "^2.2.0",
"modernizr": "^3.12.0", "modernizr": "^3.12.0",
"node-fetch": "^2.6.7", "node-fetch": "^2.6.7",
"playwright-core": "^1.45.1", "playwright-core": "^1.45.1",
@ -276,7 +264,7 @@
"postcss-import": "16.1.0", "postcss-import": "16.1.0",
"postcss-loader": "8.1.1", "postcss-loader": "8.1.1",
"postcss-mixins": "^11.0.0", "postcss-mixins": "^11.0.0",
"postcss-nested": "^6.0.0", "postcss-nested": "^7.0.0",
"postcss-preset-env": "^10.0.0", "postcss-preset-env": "^10.0.0",
"postcss-scss": "^4.0.4", "postcss-scss": "^4.0.4",
"postcss-simple-vars": "^7.0.1", "postcss-simple-vars": "^7.0.1",
@ -298,6 +286,7 @@
"webpack-bundle-analyzer": "^4.8.0", "webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^5.0.0", "webpack-cli": "^5.0.0",
"webpack-dev-server": "^5.0.0", "webpack-dev-server": "^5.0.0",
"webpack-version-file-plugin": "^0.5.0",
"yaml": "^2.3.3" "yaml": "^2.3.3"
}, },
"@casualbot/jest-sonar-reporter": { "@casualbot/jest-sonar-reporter": {

View file

@ -1,4 +1,4 @@
FROM mcr.microsoft.com/playwright:v1.48.0-jammy FROM mcr.microsoft.com/playwright:v1.48.2-jammy
WORKDIR /work WORKDIR /work

View file

@ -51,6 +51,6 @@ test.describe("Invisible cryptography", () => {
/* should show an error for a message from a previously verified device */ /* should show an error for a message from a previously verified device */
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from user that was previously verified"); await bobSecondDevice.sendMessage(testRoomId, "test encrypted from user that was previously verified");
const lastTile = page.locator(".mx_EventTile_last"); const lastTile = page.locator(".mx_EventTile_last");
await expect(lastTile).toContainText("Verified identity has changed"); await expect(lastTile).toContainText("Sender's verified identity has changed");
}); });
}); });

View file

@ -60,6 +60,11 @@ test.describe("User verification", () => {
// Accept // Accept
await toast.getByRole("button", { name: "Verify User" }).click(); await toast.getByRole("button", { name: "Verify User" }).click();
// Wait for the QR code to be rendered. If we don't do this, then the QR code can be rendered just as
// Playwright tries to click the "Verify by emoji" button, which seems to make it miss the button.
// (richvdh: I thought Playwright was supposed to be resilient to such things, but empirically not.)
await expect(page.getByAltText("QR Code")).toBeVisible();
// request verification by emoji // request verification by emoji
await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click(); await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click();
@ -101,13 +106,20 @@ test.describe("User verification", () => {
const toast = await toasts.getToast("Verification requested"); const toast = await toasts.getToast("Verification requested");
await toast.getByRole("button", { name: "Verify User" }).click(); await toast.getByRole("button", { name: "Verify User" }).click();
// Wait for the QR code to be rendered. If we don't do this, then the QR code can be rendered just as
// Playwright tries to click the "Verify by emoji" button, which seems to make it miss the button.
// (richvdh: I thought Playwright was supposed to be resilient to such things, but empirically not.)
await expect(page.getByAltText("QR Code")).toBeVisible();
// request verification by emoji // request verification by emoji
await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click(); await page.locator("#mx_RightPanel").getByRole("button", { name: "Verify by emoji" }).click();
/* on the bot side, wait for the verifier to exist ... */ /* on the bot side, wait for the verifier to exist ... */
const botVerifier = await awaitVerifier(bobVerificationRequest); const botVerifier = await awaitVerifier(bobVerificationRequest);
// ... confirm ... // ... and confirm. We expect the verification to fail; we catch the error on the DOM side
botVerifier.evaluate((verifier) => verifier.verify()).catch(() => {}); // to stop playwright marking the evaluate as failing in the UI.
const botVerification = botVerifier.evaluate((verifier) => verifier.verify().catch(() => {}));
// ... and abort the verification // ... and abort the verification
await page.getByRole("button", { name: "They don't match" }).click(); await page.getByRole("button", { name: "They don't match" }).click();
@ -115,6 +127,8 @@ test.describe("User verification", () => {
await expect(dialog.getByText("Your messages are not secure")).toBeVisible(); await expect(dialog.getByText("Your messages are not secure")).toBeVisible();
await dialog.getByRole("button", { name: "OK" }).click(); await dialog.getByRole("button", { name: "OK" }).click();
await expect(dialog).not.toBeVisible(); await expect(dialog).not.toBeVisible();
await botVerification;
}); });
}); });

View file

@ -196,14 +196,7 @@ export class Helpers {
*/ */
async assertEmptyPinnedMessagesList() { async assertEmptyPinnedMessagesList() {
const rightPanel = this.getRightPanel(); const rightPanel = this.getRightPanel();
await expect(rightPanel).toMatchScreenshot(`pinned-messages-list-empty.png`, { await expect(rightPanel).toMatchScreenshot(`pinned-messages-list-empty.png`);
css: `
// hide the tooltip "Room information" to avoid flakiness
[data-floating-ui-portal] {
display: none !important;
}
`,
});
} }
/** /**

View file

@ -31,8 +31,8 @@ test.describe("Pinned messages", () => {
const tile = util.getEventTile("Msg1"); const tile = util.getEventTile("Msg1");
await expect(tile).toMatchScreenshot("pinned-message-Msg1.png", { await expect(tile).toMatchScreenshot("pinned-message-Msg1.png", {
mask: [tile.locator(".mx_MessageTimestamp")], mask: [tile.locator(".mx_MessageTimestamp")],
// Hide the jump to bottom button in the timeline to avoid flakiness
css: ` css: `
// Hide the jump to bottom button in the timeline to avoid flakiness
.mx_JumpToBottomButton { .mx_JumpToBottomButton {
display: none !important; display: none !important;
} }

View file

@ -42,7 +42,7 @@ export class Helpers {
*/ */
async assertReleaseAnnouncementIsVisible(name: string) { async assertReleaseAnnouncementIsVisible(name: string) {
await expect(this.getReleaseAnnouncement(name)).toBeVisible(); await expect(this.getReleaseAnnouncement(name)).toBeVisible();
await expect(this.page).toMatchScreenshot(`release-announcement-${name}.png`); await expect(this.page).toMatchScreenshot(`release-announcement-${name}.png`, { showTooltips: true });
} }
/** /**

View file

@ -357,9 +357,9 @@ test.describe("Threads", () => {
await bot.joinRoom(roomId); await bot.joinRoom(roomId);
await page.goto("/#/room/" + roomId); await page.goto("/#/room/" + roomId);
// Exclude timestamp, read marker, and mapboxgl-map from snapshots // Exclude timestamp, read marker, and maplibregl-map from snapshots
const css = const css =
".mx_MessageTimestamp, .mx_MessagePanel_myReadMarker, .mapboxgl-map { visibility: hidden !important; }"; ".mx_MessageTimestamp, .mx_MessagePanel_myReadMarker, .maplibregl-map { visibility: hidden !important; }";
let locator = page.locator(".mx_RoomView_body"); let locator = page.locator(".mx_RoomView_body");
// User sends message // User sends message

View file

@ -6,32 +6,48 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only
Please see LICENSE files in the repository root for full details. Please see LICENSE files in the repository root for full details.
*/ */
import * as fs from "node:fs";
import type { Page } from "@playwright/test"; import type { Page } from "@playwright/test";
import { test, expect } from "../../element-web-test"; import { test, expect } from "../../element-web-test";
import { ElementAppPage } from "../../pages/ElementAppPage"; import { ElementAppPage } from "../../pages/ElementAppPage";
import { Credentials } from "../../plugins/homeserver";
const STICKER_PICKER_WIDGET_ID = "fake-sticker-picker"; const STICKER_PICKER_WIDGET_ID = "fake-sticker-picker";
const STICKER_PICKER_WIDGET_NAME = "Fake Stickers"; const STICKER_PICKER_WIDGET_NAME = "Fake Stickers";
const STICKER_NAME = "Test Sticker"; const STICKER_NAME = "Test Sticker";
const ROOM_NAME_1 = "Sticker Test"; const ROOM_NAME_1 = "Sticker Test";
const ROOM_NAME_2 = "Sticker Test Two"; const ROOM_NAME_2 = "Sticker Test Two";
const STICKER_MESSAGE = JSON.stringify({ const STICKER_IMAGE = fs.readFileSync("playwright/sample-files/riot.png");
action: "m.sticker",
api: "fromWidget", function getStickerMessage(contentUri: string, mimetype: string): string {
data: { return JSON.stringify({
name: "teststicker", action: "m.sticker",
description: STICKER_NAME, api: "fromWidget",
file: "test.png", data: {
content: { name: "teststicker",
body: STICKER_NAME, description: STICKER_NAME,
msgtype: "m.sticker", file: "test.png",
url: "mxc://localhost/somewhere", content: {
body: STICKER_NAME,
info: {
h: 480,
mimetype: mimetype,
size: 13818,
w: 480,
},
msgtype: "m.sticker",
url: contentUri,
},
}, },
}, requestId: "1",
requestId: "1", widgetId: STICKER_PICKER_WIDGET_ID,
widgetId: STICKER_PICKER_WIDGET_ID, });
}); }
const WIDGET_HTML = `
function getWidgetHtml(contentUri: string, mimetype: string) {
const stickerMessage = getStickerMessage(contentUri, mimetype);
return `
<html lang="en"> <html lang="en">
<head> <head>
<title>Fake Sticker Picker</title> <title>Fake Sticker Picker</title>
@ -51,13 +67,13 @@ const WIDGET_HTML = `
<button name="Send" id="sendsticker">Press for sticker</button> <button name="Send" id="sendsticker">Press for sticker</button>
<script> <script>
document.getElementById('sendsticker').onclick = () => { document.getElementById('sendsticker').onclick = () => {
window.parent.postMessage(${STICKER_MESSAGE}, '*') window.parent.postMessage(${stickerMessage}, '*')
}; };
</script> </script>
</body> </body>
</html> </html>
`; `;
}
async function openStickerPicker(app: ElementAppPage) { async function openStickerPicker(app: ElementAppPage) {
const options = await app.openMessageComposerOptions(); const options = await app.openMessageComposerOptions();
await options.getByRole("menuitem", { name: "Sticker" }).click(); await options.getByRole("menuitem", { name: "Sticker" }).click();
@ -71,7 +87,8 @@ async function sendStickerFromPicker(page: Page) {
await expect(page.locator(".mx_AppTileFullWidth#stickers")).not.toBeVisible(); await expect(page.locator(".mx_AppTileFullWidth#stickers")).not.toBeVisible();
} }
async function expectTimelineSticker(page: Page, roomId: string) { async function expectTimelineSticker(page: Page, roomId: string, contentUri: string) {
const contentId = contentUri.split("/").slice(-1)[0];
// Make sure it's in the right room // Make sure it's in the right room
await expect(page.locator(".mx_EventTile_sticker > a")).toHaveAttribute("href", new RegExp(`/${roomId}/`)); await expect(page.locator(".mx_EventTile_sticker > a")).toHaveAttribute("href", new RegExp(`/${roomId}/`));
@ -80,13 +97,43 @@ async function expectTimelineSticker(page: Page, roomId: string) {
// download URL. // download URL.
await expect(page.locator(`img[alt="${STICKER_NAME}"]`)).toHaveAttribute( await expect(page.locator(`img[alt="${STICKER_NAME}"]`)).toHaveAttribute(
"src", "src",
new RegExp("/download/localhost/somewhere"), new RegExp(`/localhost/${contentId}`),
); );
} }
async function expectFileTile(page: Page, roomId: string, contentUri: string) {
await expect(page.locator(".mx_MFileBody_info_filename")).toContainText(STICKER_NAME);
}
async function setWidgetAccountData(
app: ElementAppPage,
user: Credentials,
stickerPickerUrl: string,
provideCreatorUserId: boolean = true,
) {
await app.client.setAccountData("m.widgets", {
[STICKER_PICKER_WIDGET_ID]: {
content: {
type: "m.stickerpicker",
name: STICKER_PICKER_WIDGET_NAME,
url: stickerPickerUrl,
creatorUserId: provideCreatorUserId ? user.userId : undefined,
},
sender: user.userId,
state_key: STICKER_PICKER_WIDGET_ID,
type: "m.widget",
id: STICKER_PICKER_WIDGET_ID,
},
});
}
test.describe("Stickers", () => { test.describe("Stickers", () => {
test.use({ test.use({
displayName: "Sally", displayName: "Sally",
room: async ({ app }, use) => {
const roomId = await app.client.createRoom({ name: ROOM_NAME_1 });
await use({ roomId });
},
}); });
// We spin up a web server for the sticker picker so that we're not testing to see if // We spin up a web server for the sticker picker so that we're not testing to see if
@ -96,34 +143,19 @@ test.describe("Stickers", () => {
// //
// See sendStickerFromPicker() for more detail on iframe comms. // See sendStickerFromPicker() for more detail on iframe comms.
let stickerPickerUrl: string; let stickerPickerUrl: string;
test.beforeEach(async ({ webserver }) => {
stickerPickerUrl = webserver.start(WIDGET_HTML);
});
test("should send a sticker to multiple rooms", async ({ page, app, user }) => { test("should send a sticker to multiple rooms", async ({ webserver, page, app, user, room }) => {
const roomId1 = await app.client.createRoom({ name: ROOM_NAME_1 });
const roomId2 = await app.client.createRoom({ name: ROOM_NAME_2 }); const roomId2 = await app.client.createRoom({ name: ROOM_NAME_2 });
const { content_uri: contentUri } = await app.client.uploadContent(STICKER_IMAGE, { type: "image/png" });
await app.client.setAccountData("m.widgets", { const widgetHtml = getWidgetHtml(contentUri, "image/png");
[STICKER_PICKER_WIDGET_ID]: { stickerPickerUrl = webserver.start(widgetHtml);
content: { setWidgetAccountData(app, user, stickerPickerUrl);
type: "m.stickerpicker",
name: STICKER_PICKER_WIDGET_NAME,
url: stickerPickerUrl,
creatorUserId: user.userId,
},
sender: user.userId,
state_key: STICKER_PICKER_WIDGET_ID,
type: "m.widget",
id: STICKER_PICKER_WIDGET_ID,
},
});
await app.viewRoomByName(ROOM_NAME_1); await app.viewRoomByName(ROOM_NAME_1);
await expect(page).toHaveURL(`/#/room/${roomId1}`); await expect(page).toHaveURL(`/#/room/${room.roomId}`);
await openStickerPicker(app); await openStickerPicker(app);
await sendStickerFromPicker(page); await sendStickerFromPicker(page);
await expectTimelineSticker(page, roomId1); await expectTimelineSticker(page, room.roomId, contentUri);
// Ensure that when we switch to a different room that the sticker // Ensure that when we switch to a different room that the sticker
// goes to the right place // goes to the right place
@ -131,31 +163,40 @@ test.describe("Stickers", () => {
await expect(page).toHaveURL(`/#/room/${roomId2}`); await expect(page).toHaveURL(`/#/room/${roomId2}`);
await openStickerPicker(app); await openStickerPicker(app);
await sendStickerFromPicker(page); await sendStickerFromPicker(page);
await expectTimelineSticker(page, roomId2); await expectTimelineSticker(page, roomId2, contentUri);
}); });
test("should handle a sticker picker widget missing creatorUserId", async ({ page, app, user }) => { test("should handle a sticker picker widget missing creatorUserId", async ({
const roomId1 = await app.client.createRoom({ name: ROOM_NAME_1 }); webserver,
page,
await app.client.setAccountData("m.widgets", { app,
[STICKER_PICKER_WIDGET_ID]: { user,
content: { room,
type: "m.stickerpicker", }) => {
name: STICKER_PICKER_WIDGET_NAME, const { content_uri: contentUri } = await app.client.uploadContent(STICKER_IMAGE, { type: "image/png" });
url: stickerPickerUrl, const widgetHtml = getWidgetHtml(contentUri, "image/png");
// No creatorUserId stickerPickerUrl = webserver.start(widgetHtml);
}, setWidgetAccountData(app, user, stickerPickerUrl, false);
sender: user.userId,
state_key: STICKER_PICKER_WIDGET_ID,
type: "m.widget",
id: STICKER_PICKER_WIDGET_ID,
},
});
await app.viewRoomByName(ROOM_NAME_1); await app.viewRoomByName(ROOM_NAME_1);
await expect(page).toHaveURL(`/#/room/${roomId1}`); await expect(page).toHaveURL(`/#/room/${room.roomId}`);
await openStickerPicker(app); await openStickerPicker(app);
await sendStickerFromPicker(page); await sendStickerFromPicker(page);
await expectTimelineSticker(page, roomId1); await expectTimelineSticker(page, room.roomId, contentUri);
});
test("should render invalid mimetype as a file", async ({ webserver, page, app, user, room }) => {
const { content_uri: contentUri } = await app.client.uploadContent(STICKER_IMAGE, {
type: "application/octet-stream",
});
const widgetHtml = getWidgetHtml(contentUri, "application/octet-stream");
stickerPickerUrl = webserver.start(widgetHtml);
setWidgetAccountData(app, user, stickerPickerUrl);
await app.viewRoomByName(ROOM_NAME_1);
await expect(page).toHaveURL(`/#/room/${room.roomId}`);
await openStickerPicker(app);
await sendStickerFromPicker(page);
await expectFileTile(page, room.roomId, contentUri);
}); });
}); });

View file

@ -345,6 +345,7 @@ export const expect = baseExpect.extend({
if (!options?.showTooltips) { if (!options?.showTooltips) {
css += ` css += `
[data-floating-ui-portal],
[role="tooltip"] { [role="tooltip"] {
visibility: hidden !important; visibility: hidden !important;
} }

View file

@ -20,7 +20,7 @@ import { randB64Bytes } from "../../utils/rand";
// Docker tag to use for synapse docker image. // Docker tag to use for synapse docker image.
// We target a specific digest as every now and then a Synapse update will break our CI. // We target a specific digest as every now and then a Synapse update will break our CI.
// This digest is updated by the playwright-image-updates.yaml workflow periodically. // This digest is updated by the playwright-image-updates.yaml workflow periodically.
const DOCKER_TAG = "develop@sha256:47c62aa9507a24820190eef547861c0d278cc83fe90329c46b9f4329eed88ef4"; const DOCKER_TAG = "develop@sha256:b1b5693fa954ec0124e330dba8a28260ac1cc4d9948a778724a421be9f934284";
async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise<Omit<HomeserverConfig, "dockerUrl">> { async function cfgDirFromTemplate(opts: StartHomeserverOpts): Promise<Omit<HomeserverConfig, "dockerUrl">> {
const templateDir = path.join(__dirname, "templates", opts.template); const templateDir = path.join(__dirname, "templates", opts.template);

View file

@ -102,3 +102,5 @@ experimental_features:
# messages > non-joined historical messages. # messages > non-joined historical messages.
# Can be removed after Synapse enables it by default # Can be removed after Synapse enables it by default
msc4115_membership_on_events: true msc4115_membership_on_events: true
enable_authenticated_media: true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 KiB

After

Width:  |  Height:  |  Size: 503 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 56 KiB

After

Width:  |  Height:  |  Size: 56 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 53 KiB

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 94 KiB

After

Width:  |  Height:  |  Size: 94 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 93 KiB

After

Width:  |  Height:  |  Size: 93 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 101 KiB

After

Width:  |  Height:  |  Size: 101 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -1,4 +0,0 @@
signing_id: releases@riot.im
subprojects:
matrix-js-sdk:
includeByDefault: false

View file

@ -186,7 +186,7 @@ input[type="search"].mx_textinput_icon {
/* FIXME THEME - Tint by CSS rather than referencing a duplicate asset */ /* FIXME THEME - Tint by CSS rather than referencing a duplicate asset */
input[type="text"].mx_textinput_icon.mx_textinput_search, input[type="text"].mx_textinput_icon.mx_textinput_search,
input[type="search"].mx_textinput_icon.mx_textinput_search { input[type="search"].mx_textinput_icon.mx_textinput_search {
background-image: url("$(res)/img/feather-customised/search-input.svg"); background-image: url("@vector-im/compound-design-tokens/icons/search.svg");
} }
/* dont search UI as not all browsers support it, */ /* dont search UI as not all browsers support it, */

View file

@ -282,11 +282,11 @@
@import "./views/rooms/_EmojiButton.pcss"; @import "./views/rooms/_EmojiButton.pcss";
@import "./views/rooms/_EntityTile.pcss"; @import "./views/rooms/_EntityTile.pcss";
@import "./views/rooms/_EventBubbleTile.pcss"; @import "./views/rooms/_EventBubbleTile.pcss";
@import "./views/rooms/_EventPreview.pcss";
@import "./views/rooms/_EventTile.pcss"; @import "./views/rooms/_EventTile.pcss";
@import "./views/rooms/_HistoryTile.pcss"; @import "./views/rooms/_HistoryTile.pcss";
@import "./views/rooms/_IRCLayout.pcss"; @import "./views/rooms/_IRCLayout.pcss";
@import "./views/rooms/_JumpToBottomButton.pcss"; @import "./views/rooms/_JumpToBottomButton.pcss";
@import "./views/rooms/_LegacyRoomHeader.pcss";
@import "./views/rooms/_LinkPreviewGroup.pcss"; @import "./views/rooms/_LinkPreviewGroup.pcss";
@import "./views/rooms/_LinkPreviewWidget.pcss"; @import "./views/rooms/_LinkPreviewWidget.pcss";
@import "./views/rooms/_LiveContentSummary.pcss"; @import "./views/rooms/_LiveContentSummary.pcss";

View file

@ -53,8 +53,6 @@ Please see LICENSE files in the repository root for full details.
.mx_MapError_icon { .mx_MapError_icon {
height: var(--mx-map-error-icon-size); height: var(--mx-map-error-icon-size);
width: var(--mx-map-error-icon-size);
path { color: var(--mx-map-error-icon-color);
fill: var(--mx-map-error-icon-color);
}
} }

View file

@ -32,8 +32,8 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_DeviceExpandDetailsButton_icon { .mx_DeviceExpandDetailsButton_icon {
height: 16px; height: 24px;
width: 16px; width: 24px;
transition: all 0.3s; transition: all 0.3s;
transform: var(--icon-transform); transform: var(--icon-transform);

View file

@ -25,7 +25,7 @@ Please see LICENSE files in the repository root for full details.
width: 18px; width: 18px;
height: 18px; height: 18px;
background: currentColor; background: currentColor;
mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/chevron-down.svg");
mask-size: 100%; mask-size: 100%;
mask-repeat: no-repeat; mask-repeat: no-repeat;
float: right; float: right;

View file

@ -176,7 +176,7 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_LeftPanel_recentsButton::before { .mx_LeftPanel_recentsButton::before {
mask-image: url("$(res)/img/element-icons/clock.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/time.svg");
} }
} }

View file

@ -125,7 +125,7 @@ Please see LICENSE files in the repository root for full details.
padding-left: 34px; /* 28px from above, but +6px to account for the wider icon */ padding-left: 34px; /* 28px from above, but +6px to account for the wider icon */
&::before { &::before {
mask-image: url("$(res)/img/element-icons/retry.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/restart.svg");
} }
} }
} }

View file

@ -62,7 +62,7 @@ Please see LICENSE files in the repository root for full details.
&::before { &::before {
background-color: $info-plinth-fg-color; background-color: $info-plinth-fg-color;
mask: url("$(res)/img/feather-customised/search-input.svg"); mask: url("@vector-im/compound-design-tokens/icons/search.svg");
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-position: center; mask-position: center;
mask-size: 50px; mask-size: 50px;
@ -181,11 +181,6 @@ Please see LICENSE files in the repository root for full details.
} }
} }
/* Rooms with immersive content */
.mx_RoomView_immersive .mx_LegacyRoomHeader_wrapper {
border: unset;
}
.mx_RoomView_inCall { .mx_RoomView_inCall {
.mx_RoomView_statusAreaBox_line { .mx_RoomView_statusAreaBox_line {
margin-top: 2px; margin-top: 2px;

View file

@ -77,7 +77,7 @@ Please see LICENSE files in the repository root for full details.
height: 16px; height: 16px;
width: 16px; width: 16px;
left: 0; left: 0;
background-image: url("$(res)/img/element-icons/warning-badge.svg"); background-image: url("@vector-im/compound-design-tokens/icons/error.svg");
background-size: cover; background-size: cover;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
@ -121,7 +121,7 @@ Please see LICENSE files in the repository root for full details.
background-color: $tertiary-content; background-color: $tertiary-content;
mask-size: 16px; mask-size: 16px;
transform: rotate(270deg); transform: rotate(270deg);
mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/chevron-down.svg");
} }
&.mx_SpaceHierarchy_subspace_toggle_shown::before { &.mx_SpaceHierarchy_subspace_toggle_shown::before {

View file

@ -48,7 +48,7 @@ Please see LICENSE files in the repository root for full details.
mask-size: contain; mask-size: contain;
mask-repeat: no-repeat; mask-repeat: no-repeat;
background-color: $background; background-color: $background;
mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/chevron-down.svg");
transform: rotate(270deg); transform: rotate(270deg);
} }
@ -169,7 +169,7 @@ Please see LICENSE files in the repository root for full details.
mask-size: 20px; mask-size: 20px;
mask-repeat: no-repeat; mask-repeat: no-repeat;
background-color: $tertiary-content; background-color: $tertiary-content;
mask-image: url("$(res)/img/feather-customised/chevron-down.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/chevron-down.svg");
} }
.mx_SpaceButton_icon { .mx_SpaceButton_icon {
@ -207,7 +207,7 @@ Please see LICENSE files in the repository root for full details.
} }
&.mx_SpaceButton_home .mx_SpaceButton_icon::before { &.mx_SpaceButton_home .mx_SpaceButton_icon::before {
mask-image: url("$(res)/img/element-icons/home.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/home-solid.svg");
} }
&.mx_SpaceButton_favourites .mx_SpaceButton_icon::before { &.mx_SpaceButton_favourites .mx_SpaceButton_icon::before {
@ -414,7 +414,7 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_SpacePanel_iconHome::before { .mx_SpacePanel_iconHome::before {
mask-image: url("$(res)/img/element-icons/home.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/home-solid.svg");
} }
.mx_SpacePanel_iconInvite::before { .mx_SpacePanel_iconInvite::before {
@ -422,7 +422,7 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_SpacePanel_iconSettings::before { .mx_SpacePanel_iconSettings::before {
mask-image: url("$(res)/img/element-icons/settings.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/settings-solid.svg");
} }
.mx_SpacePanel_iconLeave::before { .mx_SpacePanel_iconLeave::before {

View file

@ -27,13 +27,14 @@ Please see LICENSE files in the repository root for full details.
&::before { &::before {
position: absolute; position: absolute;
content: ""; content: "";
width: 24px; width: 28px;
height: 24px; height: 28px;
top: 27px; top: 50%;
left: 20px; transform: translateY(-50%);
left: 22px;
mask-position: center; mask-position: center;
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-size: 24px; mask-size: 28px;
background-color: $tertiary-content; background-color: $tertiary-content;
} }
@ -221,7 +222,7 @@ Please see LICENSE files in the repository root for full details.
width: 24px; width: 24px;
background: $tertiary-content; background: $tertiary-content;
mask-size: contain; mask-size: contain;
mask-image: url("$(res)/img/element-icons/settings.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/settings-solid.svg");
} }
} }
} }

View file

@ -169,7 +169,7 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_UserMenu_iconHome::before { .mx_UserMenu_iconHome::before {
mask-image: url("$(res)/img/element-icons/home.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/home-solid.svg");
} }
.mx_UserMenu_iconDnd::before { .mx_UserMenu_iconDnd::before {
@ -185,11 +185,11 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_UserMenu_iconLock::before { .mx_UserMenu_iconLock::before {
mask-image: url("$(res)/img/element-icons/security.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/lock-solid.svg");
} }
.mx_UserMenu_iconSettings::before { .mx_UserMenu_iconSettings::before {
mask-image: url("$(res)/img/element-icons/settings.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/settings-solid.svg");
} }
.mx_UserMenu_iconMessage::before { .mx_UserMenu_iconMessage::before {

View file

@ -43,7 +43,7 @@ Please see LICENSE files in the repository root for full details.
mask-size: contain; mask-size: contain;
mask-repeat: no-repeat; mask-repeat: no-repeat;
background: $secondary-content; background: $secondary-content;
mask-image: url("$(res)/img/globe.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/public.svg");
} }
.mx_DecoratedRoomAvatar_icon_offline::before { .mx_DecoratedRoomAvatar_icon_offline::before {

View file

@ -29,7 +29,7 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_MessageContextMenu_iconReport::before { .mx_MessageContextMenu_iconReport::before {
mask-image: url("$(res)/img/element-icons/warning-badge.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/error.svg");
} }
.mx_MessageContextMenu_iconLink::before { .mx_MessageContextMenu_iconLink::before {
@ -61,7 +61,7 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_MessageContextMenu_iconResend::before { .mx_MessageContextMenu_iconResend::before {
mask-image: url("$(res)/img/element-icons/retry.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/restart.svg");
} }
.mx_MessageContextMenu_iconSource::before { .mx_MessageContextMenu_iconSource::before {

View file

@ -35,7 +35,7 @@
} }
.mx_RoomGeneralContextMenu_iconFiles::before { .mx_RoomGeneralContextMenu_iconFiles::before {
mask-image: url("$(res)/img/element-icons/room/files.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/files.svg");
} }
.mx_RoomGeneralContextMenu_iconPins::before { .mx_RoomGeneralContextMenu_iconPins::before {
@ -47,7 +47,7 @@
} }
.mx_RoomGeneralContextMenu_iconSettings::before { .mx_RoomGeneralContextMenu_iconSettings::before {
mask-image: url("$(res)/img/element-icons/settings.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/settings-solid.svg");
} }
.mx_RoomGeneralContextMenu_iconExport::before { .mx_RoomGeneralContextMenu_iconExport::before {

View file

@ -125,7 +125,7 @@ Please see LICENSE files in the repository root for full details.
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-position: center; mask-position: center;
mask-size: contain; mask-size: contain;
mask-image: url("$(res)/img/element-icons/retry.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/restart.svg");
width: 18px; width: 18px;
height: 18px; height: 18px;
left: 0; left: 0;

View file

@ -36,9 +36,24 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_AnalyticsLearnMore_bullets li { .mx_AnalyticsLearnMore_bullets li {
background: url("$(res)/img/tick-circle.svg") no-repeat;
list-style-type: none; list-style-type: none;
padding: 2px 0px 20px 32px; padding: 2px 0 0 32px;
margin-bottom: 20px;
vertical-align: middle; vertical-align: middle;
position: relative;
&::before {
content: "";
position: absolute;
width: 26px;
height: 26px;
left: 0;
top: 0;
background-color: #0dbd8b;
mask-image: url("@vector-im/compound-design-tokens/icons/check-circle.svg");
mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
}
} }
} }

View file

@ -41,14 +41,13 @@ Please see LICENSE files in the repository root for full details.
.mx_JoinRuleDropdown_invite::before { .mx_JoinRuleDropdown_invite::before {
box-sizing: border-box; box-sizing: border-box;
mask-image: url("$(res)/img/element-icons/lock.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/lock-solid.svg");
mask-size: contain; mask-size: contain;
padding: 1px; padding: 1px;
} }
.mx_JoinRuleDropdown_public::before { .mx_JoinRuleDropdown_public::before {
mask-image: url("$(res)/img/globe.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/public.svg");
mask-size: 12px;
} }
.mx_JoinRuleDropdown_restricted::before { .mx_JoinRuleDropdown_restricted::before {

View file

@ -9,7 +9,7 @@ Please see LICENSE files in the repository root for full details.
/* ========================================================== */ /* ========================================================== */
.mx_RoomSettingsDialog_settingsIcon::before { .mx_RoomSettingsDialog_settingsIcon::before {
mask-image: url("$(res)/img/element-icons/settings.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/settings-solid.svg");
} }
.mx_RoomSettingsDialog_voiceIcon::before { .mx_RoomSettingsDialog_voiceIcon::before {
@ -17,7 +17,7 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_RoomSettingsDialog_securityIcon::before { .mx_RoomSettingsDialog_securityIcon::before {
mask-image: url("$(res)/img/element-icons/security.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/lock-solid.svg");
} }
.mx_RoomSettingsDialog_rolesIcon::before { .mx_RoomSettingsDialog_rolesIcon::before {
@ -56,7 +56,7 @@ Please see LICENSE files in the repository root for full details.
/* show a different AvatarSetting placeholder for RoomProfileSettings which is basically a clone of ProfileSettings */ /* show a different AvatarSetting placeholder for RoomProfileSettings which is basically a clone of ProfileSettings */
.mx_RoomSettingsDialog .mx_AvatarSetting_avatar .mx_AvatarSetting_avatarPlaceholder::before { .mx_RoomSettingsDialog .mx_AvatarSetting_avatar .mx_AvatarSetting_avatarPlaceholder::before {
mask: url("$(res)/img/feather-customised/image.svg"); mask: url("@vector-im/compound-design-tokens/icons/image.svg");
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-size: 36px; mask-size: 36px;
mask-position: center; mask-position: center;

View file

@ -74,7 +74,7 @@ Please see LICENSE files in the repository root for full details.
.mx_TabbedView_tabLabel { .mx_TabbedView_tabLabel {
.mx_SpaceSettingsDialog_generalIcon::before { .mx_SpaceSettingsDialog_generalIcon::before {
mask-image: url("$(res)/img/element-icons/settings.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/settings-solid.svg");
} }
.mx_SpaceSettingsDialog_visibilityIcon::before { .mx_SpaceSettingsDialog_visibilityIcon::before {

View file

@ -508,7 +508,7 @@ Please see LICENSE files in the repository root for full details.
mask-size: contain; mask-size: contain;
&.mx_SpotlightDialog_metaspaceResult_home-space { &.mx_SpotlightDialog_metaspaceResult_home-space {
mask-image: url("$(res)/img/element-icons/home.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/home-solid.svg");
} }
&.mx_SpotlightDialog_metaspaceResult_favourites-space { &.mx_SpotlightDialog_metaspaceResult_favourites-space {

View file

@ -21,7 +21,7 @@ Please see LICENSE files in the repository root for full details.
&.mx_AccessSecretStorageDialog_resetBadge::before { &.mx_AccessSecretStorageDialog_resetBadge::before {
/* The image isn't capable of masking, so we use a background instead. */ /* The image isn't capable of masking, so we use a background instead. */
background-image: url("$(res)/img/element-icons/warning-badge.svg"); background-image: url("@vector-im/compound-design-tokens/icons/error.svg");
background-size: 24px; background-size: 24px;
background-color: transparent; background-color: transparent;
} }
@ -120,7 +120,7 @@ Please see LICENSE files in the repository root for full details.
width: 16px; width: 16px;
left: 0; left: 0;
top: 2px; /* alignment */ top: 2px; /* alignment */
background-image: url("$(res)/img/element-icons/warning-badge.svg"); background-image: url("@vector-im/compound-design-tokens/icons/error.svg");
background-size: contain; background-size: contain;
} }

View file

@ -39,11 +39,13 @@ Please see LICENSE files in the repository root for full details.
} }
.mx_Dropdown_arrow { .mx_Dropdown_arrow {
width: 10px; width: 16px;
height: 6px; height: 16px;
padding-right: 9px; margin-right: 4px;
mask: url("$(res)/img/feather-customised/dropdown-arrow.svg"); mask: url("@vector-im/compound-design-tokens/icons/chevron-down.svg");
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-position: center;
mask-size: 18px;
background: $primary-content; background: $primary-content;
} }

View file

@ -18,10 +18,9 @@ Please see LICENSE files in the repository root for full details.
.mx_EditableItem_delete { .mx_EditableItem_delete {
@mixin customisedCancelButton; @mixin customisedCancelButton;
order: 3; order: 3;
margin-right: 5px;
vertical-align: middle; vertical-align: middle;
width: 14px; width: 28px;
height: 14px; height: 28px;
background-color: $alert; background-color: $alert;
mask-size: 100%; mask-size: 100%;
} }
@ -42,7 +41,7 @@ Please see LICENSE files in the repository root for full details.
.mx_EditableItem_item { .mx_EditableItem_item {
flex: auto 1 0; flex: auto 1 0;
order: 1; order: 1;
width: calc(100% - 14px); /* leave space for the remove button */ width: calc(100% - 28px); /* leave space for the remove button */
overflow-x: hidden; overflow-x: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
} }

View file

@ -51,12 +51,15 @@ Please see LICENSE files in the repository root for full details.
.mx_Field_select::before { .mx_Field_select::before {
content: ""; content: "";
position: absolute; position: absolute;
top: 15px; top: 50%;
right: 10px; transform: translateY(-50%);
width: 10px; right: 4px;
height: 6px; width: 18px;
mask: url("$(res)/img/feather-customised/dropdown-arrow.svg"); height: 18px;
mask: url("@vector-im/compound-design-tokens/icons/chevron-down.svg");
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-position: center;
mask-size: contain;
background-color: $primary-content; background-color: $primary-content;
z-index: 1; z-index: 1;
pointer-events: none; pointer-events: none;

View file

@ -125,7 +125,7 @@ $button-gap: 24px;
} }
.mx_ImageView_button_download::before { .mx_ImageView_button_download::before {
mask-image: url("$(res)/img/image-view/download.svg"); mask-image: url("@vector-im/compound-design-tokens/icons/download.svg");
} }
.mx_ImageView_button_more::before { .mx_ImageView_button_more::before {

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