Merge branch 'develop' of https://github.com/vector-im/element-web into dbkr/stateafter
# Conflicts: # test/unit-tests/components/structures/RoomView-test.tsx # test/unit-tests/components/structures/TimelinePanel-test.tsx
|
@ -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",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
};
|
|
58
.eslintrc.js
|
@ -117,10 +117,6 @@ module.exports = {
|
||||||
"!matrix-js-sdk/src/extensible_events_v1/PollResponseEvent",
|
"!matrix-js-sdk/src/extensible_events_v1/PollResponseEvent",
|
||||||
"!matrix-js-sdk/src/extensible_events_v1/PollEndEvent",
|
"!matrix-js-sdk/src/extensible_events_v1/PollEndEvent",
|
||||||
"!matrix-js-sdk/src/extensible_events_v1/InvalidEventError",
|
"!matrix-js-sdk/src/extensible_events_v1/InvalidEventError",
|
||||||
"!matrix-js-sdk/src/crypto",
|
|
||||||
"!matrix-js-sdk/src/crypto/keybackup",
|
|
||||||
"!matrix-js-sdk/src/crypto/deviceinfo",
|
|
||||||
"!matrix-js-sdk/src/crypto/dehydration",
|
|
||||||
"!matrix-js-sdk/src/oidc",
|
"!matrix-js-sdk/src/oidc",
|
||||||
"!matrix-js-sdk/src/oidc/discovery",
|
"!matrix-js-sdk/src/oidc/discovery",
|
||||||
"!matrix-js-sdk/src/oidc/authorize",
|
"!matrix-js-sdk/src/oidc/authorize",
|
||||||
|
@ -270,6 +266,60 @@ module.exports = {
|
||||||
"react-hooks/rules-of-hooks": ["off"],
|
"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: {
|
||||||
react: {
|
react: {
|
||||||
|
|
33
.github/actions/download-verify-element-tarball/action.yml
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
name: Upload release assets
|
||||||
|
description: Uploads assets to an existing release and optionally signs them
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: GitHub release tag to fetch assets from.
|
||||||
|
required: true
|
||||||
|
out-file-path:
|
||||||
|
description: Path to where the webapp should be extracted to.
|
||||||
|
required: true
|
||||||
|
runs:
|
||||||
|
using: composite
|
||||||
|
steps:
|
||||||
|
- name: Download current version for its old bundles
|
||||||
|
id: current_download
|
||||||
|
uses: robinraju/release-downloader@a96f54c1b5f5e09e47d9504526e96febd949d4c2 # v1
|
||||||
|
with:
|
||||||
|
tag: steps.current_version.outputs.version
|
||||||
|
fileName: element-*.tar.gz*
|
||||||
|
out-file-path: ${{ runner.temp }}/download-verify-element-tarball
|
||||||
|
|
||||||
|
- name: Verify tarball
|
||||||
|
run: gpg --verify element-*.tar.gz.asc element-*.tar.gz
|
||||||
|
working-directory: ${{ runner.temp }}/download-verify-element-tarball
|
||||||
|
|
||||||
|
- name: Extract tarball
|
||||||
|
run: tar xvzf element-*.tar.gz -C webapp --strip-components=1
|
||||||
|
working-directory: ${{ runner.temp }}/download-verify-element-tarball
|
||||||
|
|
||||||
|
- name: Move webapp to out-file-path
|
||||||
|
run: mv ${{ runner.temp }}/download-verify-element-tarball/webapp ${{ inputs.out-file-path }}
|
||||||
|
|
||||||
|
- name: Clean up temp directory
|
||||||
|
run: rm -R ${{ runner.temp }}/download-verify-element-tarball
|
3
.github/labels.yml
vendored
|
@ -232,6 +232,9 @@
|
||||||
- name: "Z-Flaky-Test"
|
- name: "Z-Flaky-Test"
|
||||||
description: "A test is raising false alarms"
|
description: "A test is raising false alarms"
|
||||||
color: "ededed"
|
color: "ededed"
|
||||||
|
- name: "Z-Flaky-Jest-Test"
|
||||||
|
description: "A Jest test is raising false alarms"
|
||||||
|
color: "ededed"
|
||||||
- name: "Z-FOSDEM"
|
- name: "Z-FOSDEM"
|
||||||
description: "Issues in chat.fosdem.org"
|
description: "Issues in chat.fosdem.org"
|
||||||
color: "ededed"
|
color: "ededed"
|
||||||
|
|
2
.github/workflows/backport.yml
vendored
|
@ -7,6 +7,8 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- develop
|
- develop
|
||||||
|
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
backport:
|
backport:
|
||||||
name: Backport
|
name: Backport
|
||||||
|
|
1
.github/workflows/build.yml
vendored
|
@ -10,6 +10,7 @@ env:
|
||||||
# These must be set for fetchdep.sh to get the right branch
|
# These must be set for fetchdep.sh to get the right branch
|
||||||
REPOSITORY: ${{ github.repository }}
|
REPOSITORY: ${{ github.repository }}
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
permissions: {} # No permissions required
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: "Build on ${{ matrix.image }}"
|
name: "Build on ${{ matrix.image }}"
|
||||||
|
|
1
.github/workflows/build_debian.yaml
vendored
|
@ -3,6 +3,7 @@ on:
|
||||||
release:
|
release:
|
||||||
types: [published]
|
types: [published]
|
||||||
concurrency: ${{ github.workflow }}
|
concurrency: ${{ github.workflow }}
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: Build package
|
name: Build package
|
||||||
|
|
5
.github/workflows/build_develop.yml
vendored
|
@ -9,6 +9,7 @@ on:
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.repository_owner }}-${{ github.workflow }}-${{ github.ref_name }}
|
group: ${{ github.repository_owner }}-${{ github.workflow }}-${{ github.ref_name }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: "Build & Deploy develop.element.io"
|
name: "Build & Deploy develop.element.io"
|
||||||
|
@ -16,6 +17,10 @@ jobs:
|
||||||
if: github.repository == 'element-hq/element-web'
|
if: github.repository == 'element-hq/element-web'
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
environment: develop
|
environment: develop
|
||||||
|
permissions:
|
||||||
|
checks: read
|
||||||
|
pages: write
|
||||||
|
deployments: write
|
||||||
env:
|
env:
|
||||||
R2_BUCKET: "element-web-develop"
|
R2_BUCKET: "element-web-develop"
|
||||||
R2_URL: ${{ vars.CF_R2_S3_API }}
|
R2_URL: ${{ vars.CF_R2_S3_API }}
|
||||||
|
|
88
.github/workflows/deploy.yml
vendored
Normal file
|
@ -0,0 +1,88 @@
|
||||||
|
# Manual deploy workflow for deploying to app.element.io & staging.element.io
|
||||||
|
# Runs automatically for staging.element.io when an RC or Release is published
|
||||||
|
# Note: Does *NOT* run automatically for app.element.io so that it gets tested on staging.element.io beforehand
|
||||||
|
name: Build and Deploy ${{ inputs.site || 'staging.element.io' }}
|
||||||
|
on:
|
||||||
|
release:
|
||||||
|
types: [published]
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
site:
|
||||||
|
description: Which site to deploy to
|
||||||
|
required: true
|
||||||
|
default: staging.element.io
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- staging.element.io
|
||||||
|
- app.element.io
|
||||||
|
concurrency: ${{ inputs.site || 'staging.element.io' }}
|
||||||
|
permissions: {}
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
name: "Deploy to Cloudflare Pages"
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
environment: ${{ inputs.site || 'staging.element.io' }}
|
||||||
|
permissions:
|
||||||
|
checks: read
|
||||||
|
deployments: write
|
||||||
|
env:
|
||||||
|
SITE: ${{ inputs.site || 'staging.element.io' }}
|
||||||
|
steps:
|
||||||
|
- name: Load GPG key
|
||||||
|
run: |
|
||||||
|
curl https://packages.element.io/element-release-key.gpg | gpg --import
|
||||||
|
gpg -k "$GPG_FINGERPRINT"
|
||||||
|
env:
|
||||||
|
GPG_FINGERPRINT: ${{ secrets.GPG_FINGERPRINT }}
|
||||||
|
|
||||||
|
- name: Check current version on deployment
|
||||||
|
id: current_version
|
||||||
|
run: |
|
||||||
|
echo "version=$(curl -s https://$SITE/version)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# The current version bundle melding dance is skipped if the version we're deploying is the same
|
||||||
|
# as then we're just doing a re-deploy of the same version with potentially different configs.
|
||||||
|
- name: Download current version for its old bundles
|
||||||
|
id: current_download
|
||||||
|
if: steps.current_version.outputs.version != github.ref_name
|
||||||
|
uses: element-hq/element-web/.github/actions/download-verify-element-tarball@${{ github.ref_name }}
|
||||||
|
with:
|
||||||
|
tag: steps.current_version.outputs.version
|
||||||
|
out-file-path: current_version
|
||||||
|
|
||||||
|
- name: Download target version
|
||||||
|
uses: element-hq/element-web/.github/actions/download-verify-element-tarball@${{ github.ref_name }}
|
||||||
|
with:
|
||||||
|
tag: ${{ github.ref_name }}
|
||||||
|
out-file-path: _deploy
|
||||||
|
|
||||||
|
- name: Merge current bundles into target
|
||||||
|
if: steps.current_download.outcome == 'success'
|
||||||
|
run: cp -vnpr current_version/bundles/* _deploy/bundles/
|
||||||
|
|
||||||
|
- name: Copy config
|
||||||
|
run: cp element.io/app/config.json _deploy/config.json
|
||||||
|
|
||||||
|
- name: Populate 404.html
|
||||||
|
run: echo "404 Not Found" > _deploy/404.html
|
||||||
|
|
||||||
|
- name: Populate _headers
|
||||||
|
run: cp .github/cfp_headers _deploy/_headers
|
||||||
|
|
||||||
|
- name: Wait for other steps to succeed
|
||||||
|
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
||||||
|
with:
|
||||||
|
ref: ${{ github.sha }}
|
||||||
|
running-workflow-name: "Build and Deploy ${{ env.SITE }}"
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
wait-interval: 10
|
||||||
|
check-regexp: ^((?!SonarCloud|SonarQube|issue|board|label|Release|prepare|GitHub Pages).)*$
|
||||||
|
|
||||||
|
- name: Deploy to Cloudflare Pages
|
||||||
|
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1
|
||||||
|
with:
|
||||||
|
apiToken: ${{ secrets.CF_PAGES_TOKEN }}
|
||||||
|
accountId: ${{ secrets.CF_PAGES_ACCOUNT_ID }}
|
||||||
|
projectName: ${{ env.SITE == 'staging.element.io' && 'element-web-staging' || 'element-web' }}
|
||||||
|
directory: _deploy
|
||||||
|
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
|
14
.github/workflows/dockerhub.yaml
vendored
|
@ -7,27 +7,27 @@ on:
|
||||||
# This job can take a while, and we have usage limits, so just publish develop only twice a day
|
# This job can take a while, and we have usage limits, so just publish develop only twice a day
|
||||||
- cron: "0 7/12 * * *"
|
- cron: "0 7/12 * * *"
|
||||||
concurrency: ${{ github.workflow }}-${{ github.ref_name }}
|
concurrency: ${{ github.workflow }}-${{ github.ref_name }}
|
||||||
|
permissions: {}
|
||||||
permissions:
|
|
||||||
id-token: write # needed for signing the images with GitHub OIDC Token
|
|
||||||
jobs:
|
jobs:
|
||||||
buildx:
|
buildx:
|
||||||
name: Docker Buildx
|
name: Docker Buildx
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
environment: dockerhub
|
environment: dockerhub
|
||||||
|
permissions:
|
||||||
|
id-token: write # needed for signing the images with GitHub OIDC Token
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
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
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ jobs:
|
||||||
|
|
||||||
- name: Docker meta
|
- name: Docker meta
|
||||||
id: meta
|
id: meta
|
||||||
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5
|
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96 # v5
|
||||||
with:
|
with:
|
||||||
images: |
|
images: |
|
||||||
vectorim/element-web
|
vectorim/element-web
|
||||||
|
@ -51,7 +51,7 @@ jobs:
|
||||||
|
|
||||||
- name: Build and push
|
- name: Build and push
|
||||||
id: build-and-push
|
id: build-and-push
|
||||||
uses: docker/build-push-action@4f58ea79222b3b9dc2c8bbdd6debcef730109a75 # v6
|
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
push: true
|
push: true
|
||||||
|
|
8
.github/workflows/docs.yml
vendored
|
@ -5,10 +5,7 @@ on:
|
||||||
branches: [develop]
|
branches: [develop]
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
|
|
||||||
permissions:
|
permissions: {}
|
||||||
contents: read
|
|
||||||
pages: write
|
|
||||||
id-token: write
|
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: "pages"
|
group: "pages"
|
||||||
|
@ -100,6 +97,9 @@ jobs:
|
||||||
name: github-pages
|
name: github-pages
|
||||||
url: ${{ steps.deployment.outputs.page_url }}
|
url: ${{ steps.deployment.outputs.page_url }}
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
pages: write
|
||||||
|
id-token: write
|
||||||
needs: build
|
needs: build
|
||||||
steps:
|
steps:
|
||||||
- name: Deploy to GitHub Pages
|
- name: Deploy to GitHub Pages
|
||||||
|
|
|
@ -11,20 +11,23 @@ concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }}
|
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }}
|
||||||
cancel-in-progress: ${{ github.event.workflow_run.event == 'pull_request' }}
|
cancel-in-progress: ${{ github.event.workflow_run.event == 'pull_request' }}
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
jobs:
|
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
|
||||||
deployments: write
|
deployments: write
|
||||||
|
actions: read
|
||||||
steps:
|
steps:
|
||||||
- name: Download HTML report
|
- name: Download HTML report
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run-id: ${{ github.event.workflow_run.id }}
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
name: html-report
|
name: html-report
|
||||||
path: playwright-report
|
path: playwright-report
|
||||||
|
|
7
.github/workflows/end-to-end-tests.yaml
vendored
|
@ -33,10 +33,12 @@ env:
|
||||||
# fetchdep.sh needs to know our PR number
|
# fetchdep.sh needs to know our PR number
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
|
||||||
|
permissions: {} # No permissions required
|
||||||
|
|
||||||
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 +71,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 +145,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
|
||||||
|
|
1
.github/workflows/issue_closed.yml
vendored
|
@ -4,6 +4,7 @@
|
||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
types: [closed]
|
types: [closed]
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
tidy:
|
tidy:
|
||||||
name: Tidy closed issues
|
name: Tidy closed issues
|
||||||
|
|
1
.github/workflows/localazy_download.yaml
vendored
|
@ -3,6 +3,7 @@ on:
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 6 * * 1,3,5" # Every Monday, Wednesday and Friday at 6am UTC
|
- cron: "0 6 * * 1,3,5" # Every Monday, Wednesday and Friday at 6am UTC
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
download:
|
download:
|
||||||
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_download.yaml@main
|
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_download.yaml@main
|
||||||
|
|
1
.github/workflows/localazy_upload.yaml
vendored
|
@ -4,6 +4,7 @@ on:
|
||||||
branches: [develop]
|
branches: [develop]
|
||||||
paths:
|
paths:
|
||||||
- "src/i18n/strings/en_EN.json"
|
- "src/i18n/strings/en_EN.json"
|
||||||
|
permissions: {} # No permissions needed
|
||||||
jobs:
|
jobs:
|
||||||
upload:
|
upload:
|
||||||
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_upload.yaml@main
|
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_upload.yaml@main
|
||||||
|
|
7
.github/workflows/netlify.yaml
vendored
|
@ -9,8 +9,11 @@ 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
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
deployments: write
|
||||||
steps:
|
steps:
|
||||||
- name: 📝 Create Deployment
|
- name: 📝 Create Deployment
|
||||||
uses: bobheadxi/deployments@648679e8e4915b27893bd7dbc35cb504dc915bc8 # v1
|
uses: bobheadxi/deployments@648679e8e4915b27893bd7dbc35cb504dc915bc8 # v1
|
||||||
|
@ -27,7 +30,7 @@ jobs:
|
||||||
- name: 📥 Download artifact
|
- name: 📥 Download artifact
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run-id: ${{ github.event.workflow_run.id }}
|
run-id: ${{ github.event.workflow_run.id }}
|
||||||
name: webapp
|
name: webapp
|
||||||
path: webapp
|
path: webapp
|
||||||
|
|
1
.github/workflows/pending-reviews.yaml
vendored
|
@ -6,6 +6,7 @@ on:
|
||||||
#schedule:
|
#schedule:
|
||||||
# - cron: "*/10 * * * *"
|
# - cron: "*/10 * * * *"
|
||||||
concurrency: ${{ github.workflow }}
|
concurrency: ${{ github.workflow }}
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
bot:
|
bot:
|
||||||
name: Pending reviews bot
|
name: Pending reviews bot
|
||||||
|
|
|
@ -3,9 +3,12 @@ on:
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 6 * * *" # Every day at 6am UTC
|
- cron: "0 6 * * *" # Every day at 6am UTC
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
update:
|
update:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
|
3
.github/workflows/pull_request.yaml
vendored
|
@ -4,8 +4,11 @@ on:
|
||||||
types: [opened, edited, labeled, unlabeled, synchronize]
|
types: [opened, edited, labeled, unlabeled, synchronize]
|
||||||
merge_group:
|
merge_group:
|
||||||
types: [checks_requested]
|
types: [checks_requested]
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
action:
|
action:
|
||||||
uses: matrix-org/matrix-js-sdk/.github/workflows/pull_request.yaml@develop
|
uses: matrix-org/matrix-js-sdk/.github/workflows/pull_request.yaml@develop
|
||||||
|
permissions:
|
||||||
|
pull-requests: write
|
||||||
secrets:
|
secrets:
|
||||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||||
|
|
|
@ -2,10 +2,11 @@ name: Pull Request Base Branch
|
||||||
on:
|
on:
|
||||||
pull_request:
|
pull_request:
|
||||||
types: [opened, edited, synchronize]
|
types: [opened, edited, synchronize]
|
||||||
|
permissions: {} # No permissions required
|
||||||
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:
|
||||||
|
|
3
.github/workflows/release-drafter.yml
vendored
|
@ -4,6 +4,9 @@ on:
|
||||||
branches: [staging]
|
branches: [staging]
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
concurrency: ${{ github.workflow }}
|
concurrency: ${{ github.workflow }}
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
draft:
|
draft:
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
uses: matrix-org/matrix-js-sdk/.github/workflows/release-drafter-workflow.yml@develop
|
uses: matrix-org/matrix-js-sdk/.github/workflows/release-drafter-workflow.yml@develop
|
||||||
|
|
1
.github/workflows/release-gitflow.yml
vendored
|
@ -4,6 +4,7 @@ on:
|
||||||
push:
|
push:
|
||||||
branches: [master]
|
branches: [master]
|
||||||
concurrency: ${{ github.repository }}-${{ github.workflow }}
|
concurrency: ${{ github.repository }}-${{ github.workflow }}
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
merge:
|
merge:
|
||||||
uses: matrix-org/matrix-js-sdk/.github/workflows/release-gitflow.yml@develop
|
uses: matrix-org/matrix-js-sdk/.github/workflows/release-gitflow.yml@develop
|
||||||
|
|
7
.github/workflows/release.yml
vendored
|
@ -11,9 +11,14 @@ on:
|
||||||
- rc
|
- rc
|
||||||
- final
|
- final
|
||||||
concurrency: ${{ github.workflow }}
|
concurrency: ${{ github.workflow }}
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
release:
|
release:
|
||||||
uses: matrix-org/matrix-js-sdk/.github/workflows/release-make.yml@develop
|
uses: matrix-org/matrix-js-sdk/.github/workflows/release-make.yml@develop
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
issues: write
|
||||||
|
pull-requests: read
|
||||||
secrets:
|
secrets:
|
||||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||||
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
|
||||||
|
@ -42,6 +47,8 @@ jobs:
|
||||||
name: Post release checks
|
name: Post release checks
|
||||||
needs: release
|
needs: release
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
checks: read
|
||||||
steps:
|
steps:
|
||||||
- name: Wait for dockerhub
|
- name: Wait for dockerhub
|
||||||
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
|
||||||
|
|
1
.github/workflows/release_prepare.yml
vendored
|
@ -17,6 +17,7 @@ on:
|
||||||
required: true
|
required: true
|
||||||
type: boolean
|
type: boolean
|
||||||
default: true
|
default: true
|
||||||
|
permissions: {} # Uses ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
prepare:
|
prepare:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
5
.github/workflows/sonarqube.yml
vendored
|
@ -7,11 +7,16 @@ on:
|
||||||
concurrency:
|
concurrency:
|
||||||
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
|
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
sonarqube:
|
sonarqube:
|
||||||
name: 🩻 SonarQube
|
name: 🩻 SonarQube
|
||||||
if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'merge_group'
|
if: github.event.workflow_run.conclusion == 'success' && github.event.workflow_run.event != 'merge_group'
|
||||||
uses: matrix-org/matrix-js-sdk/.github/workflows/sonarcloud.yml@develop
|
uses: matrix-org/matrix-js-sdk/.github/workflows/sonarcloud.yml@develop
|
||||||
|
permissions:
|
||||||
|
actions: read
|
||||||
|
statuses: write
|
||||||
|
id-token: write # sonar
|
||||||
secrets:
|
secrets:
|
||||||
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
|
||||||
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||||
|
|
12
.github/workflows/static_analysis.yaml
vendored
|
@ -16,6 +16,8 @@ env:
|
||||||
REPOSITORY: ${{ github.repository }}
|
REPOSITORY: ${{ github.repository }}
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
|
||||||
|
permissions: {} # No permissions required
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
ts_lint:
|
ts_lint:
|
||||||
name: "Typescript Syntax Check"
|
name: "Typescript Syntax Check"
|
||||||
|
@ -37,6 +39,8 @@ jobs:
|
||||||
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
|
||||||
|
permissions:
|
||||||
|
pull-requests: read
|
||||||
with:
|
with:
|
||||||
hardcoded-words: "Element"
|
hardcoded-words: "Element"
|
||||||
allowed-hardcoded-keys: |
|
allowed-hardcoded-keys: |
|
||||||
|
@ -50,7 +54,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
|
||||||
|
|
||||||
|
@ -123,6 +127,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"
|
||||||
|
|
||||||
|
|
3
.github/workflows/sync-labels.yml
vendored
|
@ -8,6 +8,9 @@ on:
|
||||||
- develop
|
- develop
|
||||||
paths:
|
paths:
|
||||||
- .github/labels.yml
|
- .github/labels.yml
|
||||||
|
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
sync-labels:
|
sync-labels:
|
||||||
uses: element-hq/element-meta/.github/workflows/sync-labels.yml@develop
|
uses: element-hq/element-meta/.github/workflows/sync-labels.yml@develop
|
||||||
|
|
10
.github/workflows/tests.yml
vendored
|
@ -26,10 +26,12 @@ env:
|
||||||
# fetchdep.sh needs to know our PR number
|
# fetchdep.sh needs to know our PR number
|
||||||
PR_NUMBER: ${{ github.event.pull_request.number }}
|
PR_NUMBER: ${{ github.event.pull_request.number }}
|
||||||
|
|
||||||
|
permissions: {}
|
||||||
|
|
||||||
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,14 +95,16 @@ 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
|
||||||
|
permissions:
|
||||||
|
statuses: write
|
||||||
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
|
||||||
|
|
||||||
- name: Skip SonarCloud in merge queue
|
- name: Skip SonarCloud in merge queue
|
||||||
if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true'
|
if: github.event_name == 'merge_group' || inputs.disable_coverage == 'true'
|
||||||
uses: Sibz/github-status-action@faaa4d96fecf273bd762985e0e7f9f933c774918 # v1
|
uses: guibranco/github-status-action-v2@66088c44e212a906c32a047529a213d81809ec1c
|
||||||
with:
|
with:
|
||||||
authToken: ${{ secrets.GITHUB_TOKEN }}
|
authToken: ${{ secrets.GITHUB_TOKEN }}
|
||||||
state: success
|
state: success
|
||||||
|
|
2
.github/workflows/triage-assigned.yml
vendored
|
@ -4,6 +4,8 @@ on:
|
||||||
issues:
|
issues:
|
||||||
types: [assigned]
|
types: [assigned]
|
||||||
|
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
web-app-team:
|
web-app-team:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
2
.github/workflows/triage-incoming.yml
vendored
|
@ -4,6 +4,8 @@ on:
|
||||||
issues:
|
issues:
|
||||||
types: [opened]
|
types: [opened]
|
||||||
|
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
automate-project-columns:
|
automate-project-columns:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
2
.github/workflows/triage-labelled.yml
vendored
|
@ -8,6 +8,8 @@ on:
|
||||||
ELEMENT_BOT_TOKEN:
|
ELEMENT_BOT_TOKEN:
|
||||||
required: true
|
required: true
|
||||||
|
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
apply_Z-Labs_label:
|
apply_Z-Labs_label:
|
||||||
name: Add Z-Labs label for features behind labs flags
|
name: Add Z-Labs label for features behind labs flags
|
||||||
|
|
|
@ -3,6 +3,7 @@ on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [review_requested]
|
types: [review_requested]
|
||||||
|
|
||||||
|
permissions: {} # Uses ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
add_design_pr_to_project:
|
add_design_pr_to_project:
|
||||||
name: Move PRs asking for design review to the design board
|
name: Move PRs asking for design review to the design board
|
||||||
|
|
|
@ -2,6 +2,7 @@ name: Close stale flaky issues
|
||||||
on:
|
on:
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "30 1 * * *"
|
- cron: "30 1 * * *"
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
close:
|
close:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
4
.github/workflows/triage-unlabelled.yml
vendored
|
@ -3,11 +3,13 @@ name: Move unlabelled from needs info columns to triaged
|
||||||
on:
|
on:
|
||||||
issues:
|
issues:
|
||||||
types: [unlabeled]
|
types: [unlabeled]
|
||||||
|
permissions: {}
|
||||||
jobs:
|
jobs:
|
||||||
Move_Unabeled_Issue_On_Project_Board:
|
Move_Unabeled_Issue_On_Project_Board:
|
||||||
name: Move no longer X-Needs-Info issues to Triaged
|
name: Move no longer X-Needs-Info issues to Triaged
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
permissions:
|
||||||
|
repository-projects: read
|
||||||
if: >
|
if: >
|
||||||
${{
|
${{
|
||||||
!contains(github.event.issue.labels.*.name, 'X-Needs-Info') }}
|
!contains(github.event.issue.labels.*.name, 'X-Needs-Info') }}
|
||||||
|
|
1
.github/workflows/update-jitsi.yml
vendored
|
@ -4,6 +4,7 @@ on:
|
||||||
workflow_dispatch: {}
|
workflow_dispatch: {}
|
||||||
schedule:
|
schedule:
|
||||||
- cron: "0 3 * * 0" # 3am every Sunday
|
- cron: "0 3 * * 0" # 3am every Sunday
|
||||||
|
permissions: {} # We use ELEMENT_BOT_TOKEN instead
|
||||||
jobs:
|
jobs:
|
||||||
update:
|
update:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
|
|
1
.github/workflows/update-topics.yaml
vendored
|
@ -15,6 +15,7 @@ on:
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
concurrency: ${{ github.workflow }}
|
concurrency: ${{ github.workflow }}
|
||||||
|
permissions: {} # No permissions required
|
||||||
jobs:
|
jobs:
|
||||||
bot:
|
bot:
|
||||||
name: Release topic update
|
name: Release topic update
|
||||||
|
|
|
@ -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"]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
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", "stylelint-value-no-unknown-custom-properties"],
|
||||||
rules: {
|
rules: {
|
||||||
"comment-empty-line-before": null,
|
"comment-empty-line-before": null,
|
||||||
"declaration-empty-line-before": null,
|
"declaration-empty-line-before": null,
|
||||||
|
@ -46,5 +46,33 @@ module.exports = {
|
||||||
"number-max-precision": null,
|
"number-max-precision": null,
|
||||||
"no-invalid-double-slash-comments": true,
|
"no-invalid-double-slash-comments": true,
|
||||||
"media-feature-range-notation": null,
|
"media-feature-range-notation": null,
|
||||||
|
"csstools/value-no-unknown-custom-properties": [
|
||||||
|
true,
|
||||||
|
{
|
||||||
|
importFrom: [
|
||||||
|
{ from: "res/css/_common.pcss", type: "css" },
|
||||||
|
{ from: "res/themes/light/css/_light.pcss", type: "css" },
|
||||||
|
// Right now our styles share vars all over the place, this is not ideal but acceptable for now
|
||||||
|
{ from: "res/css/views/rooms/_EventTile.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/rooms/_IRCLayout.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/rooms/_EventBubbleTile.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/rooms/_ReadReceiptGroup.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/rooms/_EditMessageComposer.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/right_panel/_BaseCard.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/messages/_MessageTimestamp.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/messages/_EventTileBubble.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/messages/_MessageActionBar.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/voip/LegacyCallView/_LegacyCallViewButtons.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/elements/_ToggleSwitch.pcss", type: "css" },
|
||||||
|
{ from: "res/css/views/settings/tabs/_SettingsTab.pcss", type: "css" },
|
||||||
|
{ from: "res/css/structures/_RoomView.pcss", type: "css" },
|
||||||
|
// Compound vars
|
||||||
|
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-common-base.css",
|
||||||
|
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-common-semantic.css",
|
||||||
|
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-theme-light-base-mq.css",
|
||||||
|
"node_modules/@vector-im/compound-design-tokens/assets/web/css/cpd-theme-light-semantic-mq.css",
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
28
CHANGELOG.md
|
@ -1,3 +1,31 @@
|
||||||
|
Changes in [1.11.86](https://github.com/element-hq/element-web/releases/tag/v1.11.86) (2024-11-19)
|
||||||
|
==================================================================================================
|
||||||
|
## ✨ Features
|
||||||
|
|
||||||
|
* Deduplicate icons using Compound Design Tokens ([#28419](https://github.com/element-hq/element-web/pull/28419)). Contributed by @t3chguy.
|
||||||
|
* Let widget driver send error details ([#28357](https://github.com/element-hq/element-web/pull/28357)). Contributed by @AndrewFerr.
|
||||||
|
* Deduplicate icons using Compound Design Tokens ([#28381](https://github.com/element-hq/element-web/pull/28381)). Contributed by @t3chguy.
|
||||||
|
* Auto approvoce `io.element.call.reaction` capability for element call widgets ([#28401](https://github.com/element-hq/element-web/pull/28401)). Contributed by @toger5.
|
||||||
|
* Show message type prefix in thread root \& reply previews ([#28361](https://github.com/element-hq/element-web/pull/28361)). Contributed by @t3chguy.
|
||||||
|
* Support sending encrypted to device messages from widgets ([#28315](https://github.com/element-hq/element-web/pull/28315)). Contributed by @hughns.
|
||||||
|
|
||||||
|
## 🐛 Bug Fixes
|
||||||
|
|
||||||
|
* Feed events to widgets as they are decrypted (even if out of order) ([#28376](https://github.com/element-hq/element-web/pull/28376)). Contributed by @robintown.
|
||||||
|
* Handle authenticated media when downloading from ImageView ([#28379](https://github.com/element-hq/element-web/pull/28379)). Contributed by @t3chguy.
|
||||||
|
* Ignore `m.3pid_changes` for Identity service 3PID changes ([#28375](https://github.com/element-hq/element-web/pull/28375)). Contributed by @t3chguy.
|
||||||
|
* Fix markdown escaping wrongly passing html through ([#28363](https://github.com/element-hq/element-web/pull/28363)). Contributed by @t3chguy.
|
||||||
|
* Remove "Upgrade your encryption" flow in `CreateSecretStorageDialog` ([#28290](https://github.com/element-hq/element-web/pull/28290)). Contributed by @florianduros.
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
Changes in [1.11.84](https://github.com/element-hq/element-web/releases/tag/v1.11.84) (2024-11-05)
|
||||||
==================================================================================================
|
==================================================================================================
|
||||||
## ✨ Features
|
## ✨ Features
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
// Stub out FontManager for tests as it doesn't validate anything we don't already know given
|
|
||||||
// our fixed test environment and it requires the installation of node-canvas.
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
fixupColorFonts: () => Promise.resolve(),
|
|
||||||
};
|
|
|
@ -32,13 +32,12 @@ const config: Config = {
|
||||||
"decoderWorker\\.min\\.wasm": "<rootDir>/__mocks__/empty.js",
|
"decoderWorker\\.min\\.wasm": "<rootDir>/__mocks__/empty.js",
|
||||||
"waveWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
|
"waveWorker\\.min\\.js": "<rootDir>/__mocks__/empty.js",
|
||||||
"context-filter-polyfill": "<rootDir>/__mocks__/empty.js",
|
"context-filter-polyfill": "<rootDir>/__mocks__/empty.js",
|
||||||
"FontManager.ts": "<rootDir>/__mocks__/FontManager.js",
|
|
||||||
"workers/(.+)Factory": "<rootDir>/__mocks__/workerFactoryMock.js",
|
"workers/(.+)Factory": "<rootDir>/__mocks__/workerFactoryMock.js",
|
||||||
"^!!raw-loader!.*": "jest-raw-loader",
|
"^!!raw-loader!.*": "jest-raw-loader",
|
||||||
"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
|
@ -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;
|
54
package.json
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "element-web",
|
"name": "element-web",
|
||||||
"version": "1.11.84",
|
"version": "1.11.86",
|
||||||
"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,10 +71,9 @@
|
||||||
"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.30001684",
|
||||||
"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"
|
||||||
},
|
},
|
||||||
|
@ -89,14 +85,14 @@
|
||||||
"@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.4.0",
|
||||||
"@vector-im/matrix-wysiwyg": "2.37.13",
|
"@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",
|
||||||
|
@ -118,24 +114,25 @@
|
||||||
"jsrsasign": "^11.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.4",
|
||||||
"linkify-react": "4.1.3",
|
"linkify-react": "4.1.4",
|
||||||
"linkify-string": "4.1.3",
|
"linkify-string": "4.1.4",
|
||||||
"linkifyjs": "4.1.3",
|
"linkifyjs": "4.1.4",
|
||||||
"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",
|
||||||
|
@ -155,11 +152,9 @@
|
||||||
"@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",
|
||||||
|
@ -211,15 +204,12 @@
|
||||||
"@types/react-dom": "18.3.1",
|
"@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.2",
|
|
||||||
"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",
|
||||||
|
@ -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",
|
||||||
|
@ -288,6 +276,7 @@
|
||||||
"stylelint": "^16.1.0",
|
"stylelint": "^16.1.0",
|
||||||
"stylelint-config-standard": "^36.0.0",
|
"stylelint-config-standard": "^36.0.0",
|
||||||
"stylelint-scss": "^6.0.0",
|
"stylelint-scss": "^6.0.0",
|
||||||
|
"stylelint-value-no-unknown-custom-properties": "^6.0.1",
|
||||||
"terser-webpack-plugin": "^5.3.9",
|
"terser-webpack-plugin": "^5.3.9",
|
||||||
"ts-node": "^10.9.1",
|
"ts-node": "^10.9.1",
|
||||||
"ts-prune": "^0.10.3",
|
"ts-prune": "^0.10.3",
|
||||||
|
@ -298,6 +287,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": {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM mcr.microsoft.com/playwright:v1.48.2-jammy
|
FROM mcr.microsoft.com/playwright:v1.49.0-jammy
|
||||||
|
|
||||||
WORKDIR /work
|
WORKDIR /work
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,9 @@ test.describe("Cryptography", function () {
|
||||||
await page.locator(".mx_AuthPage").getByRole("button", { name: "I'll verify later" }).click();
|
await page.locator(".mx_AuthPage").getByRole("button", { name: "I'll verify later" }).click();
|
||||||
await app.viewRoomByName("Test room");
|
await app.viewRoomByName("Test room");
|
||||||
|
|
||||||
|
// In this case, the call to cryptoApi.isEncryptionEnabledInRoom is taking a long time to resolve
|
||||||
|
await page.waitForTimeout(1000);
|
||||||
|
|
||||||
// There should be two historical events in the timeline
|
// There should be two historical events in the timeline
|
||||||
const tiles = await page.locator(".mx_EventTile").all();
|
const tiles = await page.locator(".mx_EventTile").all();
|
||||||
expect(tiles.length).toBeGreaterThanOrEqual(2);
|
expect(tiles.length).toBeGreaterThanOrEqual(2);
|
||||||
|
|
|
@ -16,6 +16,7 @@ import {
|
||||||
logOutOfElement,
|
logOutOfElement,
|
||||||
verify,
|
verify,
|
||||||
} from "./utils";
|
} from "./utils";
|
||||||
|
import { bootstrapCrossSigningForClient } from "../../pages/client.ts";
|
||||||
|
|
||||||
test.describe("Cryptography", function () {
|
test.describe("Cryptography", function () {
|
||||||
test.use({
|
test.use({
|
||||||
|
@ -307,5 +308,30 @@ test.describe("Cryptography", function () {
|
||||||
const penultimate = page.locator(".mx_EventTile").filter({ hasText: "test encrypted from verified" });
|
const penultimate = page.locator(".mx_EventTile").filter({ hasText: "test encrypted from verified" });
|
||||||
await expect(penultimate.locator(".mx_EventTile_e2eIcon")).not.toBeVisible();
|
await expect(penultimate.locator(".mx_EventTile_e2eIcon")).not.toBeVisible();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("should show correct shields on events sent by users with changed identity", async ({
|
||||||
|
page,
|
||||||
|
app,
|
||||||
|
bot: bob,
|
||||||
|
homeserver,
|
||||||
|
}) => {
|
||||||
|
// Verify Bob
|
||||||
|
await verify(app, bob);
|
||||||
|
|
||||||
|
// Bob logs in a new device and resets cross-signing
|
||||||
|
const bobSecondDevice = await createSecondBotDevice(page, homeserver, bob);
|
||||||
|
await bootstrapCrossSigningForClient(await bobSecondDevice.prepareClient(), bob.credentials, true);
|
||||||
|
|
||||||
|
/* should show an error for a message from a previously verified device */
|
||||||
|
await bobSecondDevice.sendMessage(testRoomId, "test encrypted from user that was previously verified");
|
||||||
|
const last = page.locator(".mx_EventTile_last");
|
||||||
|
await expect(last).toContainText("test encrypted from user that was previously verified");
|
||||||
|
const lastE2eIcon = last.locator(".mx_EventTile_e2eIcon");
|
||||||
|
await expect(lastE2eIcon).toHaveClass(/mx_EventTile_e2eIcon_warning/);
|
||||||
|
await lastE2eIcon.focus();
|
||||||
|
await expect(await app.getTooltipForElement(lastE2eIcon)).toContainText(
|
||||||
|
"Sender's verified identity has changed",
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -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:d1a89bd0fcdc2bf2900dac30696d53bb9e44da1231faacd5c2d3b9f539ce9586";
|
const DOCKER_TAG = "develop@sha256:b261d81d9a3615a7716fc92423ee5689b0b450ed49f87a4887e49ecab7aefe45";
|
||||||
|
|
||||||
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);
|
||||||
|
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.3 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 975 KiB After Width: | Height: | Size: 975 KiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1 MiB |
Before Width: | Height: | Size: 1.2 MiB After Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 563 KiB After Width: | Height: | Size: 503 KiB |
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 28 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 198 KiB After Width: | Height: | Size: 198 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 5.2 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 4.7 KiB |
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 43 KiB After Width: | Height: | Size: 43 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 37 KiB |
Before Width: | Height: | Size: 51 KiB After Width: | Height: | Size: 51 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 47 KiB |
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
Before Width: | Height: | Size: 94 KiB After Width: | Height: | Size: 94 KiB |
Before Width: | Height: | Size: 93 KiB After Width: | Height: | Size: 93 KiB |
Before Width: | Height: | Size: 101 KiB After Width: | Height: | Size: 101 KiB |
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
@ -1,4 +0,0 @@
|
||||||
signing_id: releases@riot.im
|
|
||||||
subprojects:
|
|
||||||
matrix-js-sdk:
|
|
||||||
includeByDefault: false
|
|
|
@ -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, */
|
||||||
|
|
|
@ -319,6 +319,7 @@
|
||||||
@import "./views/rooms/_ThirdPartyMemberInfo.pcss";
|
@import "./views/rooms/_ThirdPartyMemberInfo.pcss";
|
||||||
@import "./views/rooms/_ThreadSummary.pcss";
|
@import "./views/rooms/_ThreadSummary.pcss";
|
||||||
@import "./views/rooms/_TopUnreadMessagesBar.pcss";
|
@import "./views/rooms/_TopUnreadMessagesBar.pcss";
|
||||||
|
@import "./views/rooms/_UserIdentityWarning.pcss";
|
||||||
@import "./views/rooms/_VoiceRecordComposerTile.pcss";
|
@import "./views/rooms/_VoiceRecordComposerTile.pcss";
|
||||||
@import "./views/rooms/_WhoIsTypingTile.pcss";
|
@import "./views/rooms/_WhoIsTypingTile.pcss";
|
||||||
@import "./views/rooms/wysiwyg_composer/_EditWysiwygComposer.pcss";
|
@import "./views/rooms/wysiwyg_composer/_EditWysiwygComposer.pcss";
|
||||||
|
|
|
@ -11,7 +11,8 @@ Please see LICENSE files in the repository root for full details.
|
||||||
font-size: $font-12px;
|
font-size: $font-12px;
|
||||||
width: 100%; /* make mx_AppPermission fill width of mx_AppTileBody so that scroll bar appears on the edge */
|
width: 100%; /* make mx_AppPermission fill width of mx_AppTileBody so that scroll bar appears on the edge */
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
.mx_AppPermission_bolder {
|
.mx_AppPermission_bolder,
|
||||||
|
.mx_AppPermission_content_bolder {
|
||||||
font-weight: var(--cpd-font-weight-semibold);
|
font-weight: var(--cpd-font-weight-semibold);
|
||||||
}
|
}
|
||||||
.mx_AppPermission_content {
|
.mx_AppPermission_content {
|
||||||
|
@ -21,10 +22,6 @@ Please see LICENSE files in the repository root for full details.
|
||||||
margin-block: 12px;
|
margin-block: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_AppPermission_content_bolder {
|
|
||||||
font-weight: var(--font-semi-bold);
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_TextWithTooltip_target--helpIcon {
|
.mx_TextWithTooltip_target--helpIcon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: $font-14px; /* align with characters on the same line */
|
height: $font-14px; /* align with characters on the same line */
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ Please see LICENSE files in the repository root for full details.
|
||||||
/** Fixme - factor this out with the main header **/
|
/** Fixme - factor this out with the main header **/
|
||||||
|
|
||||||
.mx_RightPanel_threadsButton::before {
|
.mx_RightPanel_threadsButton::before {
|
||||||
mask-image: url("$(res)/img/element-icons/room/thread.svg");
|
mask-image: url("@vector-im/compound-design-tokens/icons/threads-solid.svg");
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RightPanel_notifsButton::before {
|
.mx_RightPanel_notifsButton::before {
|
||||||
|
@ -36,7 +36,7 @@ Please see LICENSE files in the repository root for full details.
|
||||||
}
|
}
|
||||||
|
|
||||||
.mx_RightPanel_roomSummaryButton::before {
|
.mx_RightPanel_roomSummaryButton::before {
|
||||||
mask-image: url("$(res)/img/element-icons/room/room-summary.svg");
|
mask-image: url("@vector-im/compound-design-tokens/icons/info-solid.svg");
|
||||||
mask-position: center;
|
mask-position: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -207,62 +207,3 @@ Please see LICENSE files in the repository root for full details.
|
||||||
min-height: 42px;
|
min-height: 42px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@keyframes mx_Indicator_pulse {
|
|
||||||
0% {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
|
||||||
|
|
||||||
70% {
|
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: scale(0.95);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes mx_Indicator_pulse_shadow {
|
|
||||||
0% {
|
|
||||||
opacity: 0.7;
|
|
||||||
}
|
|
||||||
|
|
||||||
70% {
|
|
||||||
transform: scale(2.2);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.mx_Indicator {
|
|
||||||
position: absolute;
|
|
||||||
right: -3px;
|
|
||||||
top: -3px;
|
|
||||||
width: var(--RoomHeader-indicator-dot-size);
|
|
||||||
height: var(--RoomHeader-indicator-dot-size);
|
|
||||||
border-radius: 50%;
|
|
||||||
transform: scale(1);
|
|
||||||
background: var(--RoomHeader-indicator-pulseColor);
|
|
||||||
box-shadow: 0 0 0 0 var(--RoomHeader-indicator-pulseColor);
|
|
||||||
animation: mx_Indicator_pulse 2s infinite;
|
|
||||||
animation-iteration-count: 1;
|
|
||||||
|
|
||||||
&::after {
|
|
||||||
content: "";
|
|
||||||
position: absolute;
|
|
||||||
width: inherit;
|
|
||||||
height: inherit;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
transform: scale(1);
|
|
||||||
transform-origin: center center;
|
|
||||||
animation-name: mx_Indicator_pulse_shadow;
|
|
||||||
animation-duration: inherit;
|
|
||||||
animation-iteration-count: inherit;
|
|
||||||
border-radius: 50%;
|
|
||||||
background: inherit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|