Compare commits

..

2 Commits

Author SHA1 Message Date
Richard van der Hoff
f4749b8424 fix numbering 2023-09-22 10:30:43 +01:00
Richard van der Hoff
67401eeb27 Remove the code style rule about casts to bool 2023-09-22 10:11:18 +01:00
51 changed files with 2121 additions and 4623 deletions

View File

@@ -2,7 +2,7 @@ name: Build
on:
pull_request: {}
push:
branches: [develop, master]
branches: [master]
# develop pushes and repository_dispatch handled in build_develop.yaml
env:
# These must be set for fetchdep.sh to get the right branch
@@ -10,25 +10,8 @@ env:
PR_NUMBER: ${{ github.event.pull_request.number }}
jobs:
build:
name: "Build on ${{ matrix.image }}"
# We build on all 3 platforms to ensure we don't have any OS-specific build incompatibilities
strategy:
fail-fast: false
matrix:
image:
- ubuntu-latest
- windows-latest
- macos-latest
isDevelop:
- ${{ github.event_name == 'push' && github.ref_name == 'develop' }}
# Skip the ubuntu-latest build for the develop branch as the dedicated CD build_develop workflow handles that
exclude:
- isDevelop: true
image: ubuntu-latest
runs-on: ${{ matrix.image }}
defaults:
run:
shell: bash
name: "Build"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
@@ -36,9 +19,6 @@ jobs:
with:
cache: "yarn"
# Workaround for yarn install timeouts, especially on Windows
- run: yarn config set network-timeout 300000
- name: Install Dependencies
run: "./scripts/layered.sh"

View File

@@ -6,37 +6,26 @@ concurrency: ${{ github.workflow }}
jobs:
build:
name: Build package
if: github.event.release.prerelease == false
environment: packages.element.io
runs-on: ubuntu-latest
env:
R2_INCOMING_BUCKET: ${{ vars.R2_INCOMING_BUCKET }}
R2_URL: ${{ vars.CF_R2_S3_API }}
VERSION: ${{ github.ref_name }}
steps:
- uses: actions/checkout@v4
- name: Download package
run: |
wget "https://github.com/vector-im/element-web/releases/download/$VERSION/element-$VERSION.tar.gz"
wget "https://github.com/vector-im/element-web/releases/download/$VERSION/element-$VERSION.tar.gz.asc"
- name: Check GPG signature
run: |
wget "https://packages.element.io/element-release-key.gpg"
gpg --import element-release-key.gpg
gpg --fingerprint "$FINGERPRINT"
gpg --verify "element-$VERSION.tar.gz.asc" "element-$VERSION.tar.gz"
env:
FINGERPRINT: ${{ vars.GPG_FINGERPRINT }}
- name: Prepare
run: |
mkdir -p /tmp/element-web-debian/DEBIAN
cp -R debian/ /tmp/element-web-debian/DEBIAN/
mkdir -p /tmp/element-web-debian/usr/share/element-web/
tar -xf "element-$VERSION.tar.gz" -C /tmp/element-web-debian/usr/share/element-web --strip-components=1
cp config.sample.json /tmp/element-web-debian/usr/share/element-web/config.json
wget https://github.com/vector-im/element-web/releases/download/$VERSION/element-$VERSION.tar.gz
mv element-* /tmp/element-web-debian/usr/share/element-web
mv debian/usr/share/element-web/config.sample.json /tmp/element-web-debian/usr/share/element-web/config.json
env:
VERSION: ${{ github.ref_name }}
- name: Build deb package
run: |
@@ -52,8 +41,7 @@ jobs:
retention-days: 14
#- name: Upload incoming deb
# if: github.event.release.prerelease == false
# run: aws s3 cp element-web.deb "s3://$R2_INCOMING_BUCKET" --endpoint-url "$R2_URL" --region auto
# run: aws s3 cp element-io-archive-keyring.deb "s3://$R2_INCOMING_BUCKET" --endpoint-url "$R2_URL" --region auto
# env:
# AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
# AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
@@ -61,7 +49,7 @@ jobs:
#reprepro:
# needs: build
# name: Run reprepro
# if: github.event.release.prerelease == false
# if: inputs.deploy && github.event.release.prerelease == false
# uses: ./.github/workflows/reprepro.yaml
# secrets: inherit
# with:

View File

@@ -18,22 +18,22 @@ jobs:
fetch-depth: 0 # needed for docker-package to be able to calculate the version
- name: Set up QEMU
uses: docker/setup-qemu-action@68827325e0b33c7199eb31dd4e31fbe9023e06e3 # v3
uses: docker/setup-qemu-action@2b82ce82d56a2a04d2637cd93a637ae1b359c0a7 # v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@f95db51fddba0c2d1ec667646a06c2ce06100226 # v3
uses: docker/setup-buildx-action@885d1462b80bc1c1c7f0b00334ad271f09369c55 # v2
with:
install: true
- name: Login to Docker Hub
uses: docker/login-action@343f7c4344506bcbf9b4de18042ae17996df046d # v3
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc # v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@96383f45573cb7f253c731d3b3ab81c87ef81934 # v5
uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175 # v4
with:
images: |
vectorim/element-web
@@ -44,7 +44,7 @@ jobs:
latest=${{ contains(github.ref_name, '-rc.') && 'false' || 'auto' }}
- name: Build and push
uses: docker/build-push-action@0565240e2d4ab88bba5387d719585280857ece09 # v5
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825 # v4
with:
context: .
push: true

View File

@@ -1,115 +0,0 @@
name: Deploy documentation
on:
push:
branches: [develop]
workflow_dispatch: {}
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
build:
name: GitHub Pages
runs-on: ubuntu-latest
steps:
- name: Fetch element-desktop
uses: actions/checkout@v4
with:
repository: vector-im/element-desktop
path: element-desktop
- name: Fetch element-web
uses: actions/checkout@v4
with:
path: element-web
- name: Fetch matrix-react-sdk
uses: actions/checkout@v4
with:
repository: matrix-org/matrix-react-sdk
path: matrix-react-sdk
- name: Fetch matrix-js-sdk
uses: actions/checkout@v4
with:
repository: matrix-org/matrix-js-sdk
path: matrix-js-sdk
- uses: actions/setup-node@v3
with:
cache: "yarn"
cache-dependency-path: element-web/yarn.lock
- name: Generate automations docs
working-directory: element-web
run: |
yarn install --frozen-lockfile
yarn ts-node ./scripts/gen-workflow-mermaid.ts ../element-desktop ../element-web ../matrix-react-sdk ../matrix-js-sdk > docs/automations.md
echo "- [Automations](automations.md)" >> docs/SUMMARY.md
- name: Setup mdBook
uses: peaceiris/actions-mdbook@v1
with:
mdbook-version: "0.4.10"
- name: Install mdbook extensions
run: cargo install mdbook-combiner mdbook-mermaid
- name: Prepare docs
run: |
mkdir docs
mv element-desktop/README.md element-desktop/docs/
mv element-desktop/docs "docs/Element Desktop"
mv element-web/README.md element-web/docs/
mv element-web/docs/lib docs/
mv element-web/docs "docs/Element Web"
mv matrix-react-sdk/README.md matrix-react-sdk/docs/
mv matrix-react-sdk/docs "docs/Matrix React SDK"
mv matrix-js-sdk/README.md matrix-js-sdk/docs/
mv matrix-js-sdk/docs "docs/Matrix JS SDK"
sed -i -e 's/\.\.\/README.md/README.md/' docs/**/SUMMARY.md
mdbook-combiner -m docs
sed -i -E 's/^\t# (.+)$/- [\1]()/gm;t' SUMMARY.md
sed -i -E 's/^- \[(.+)]\(<>\)$/---\n# \1/gm;t' SUMMARY.md
sed -i -E 's/\t- \[Introduction]/- [Introduction]/gm;t' SUMMARY.md
cat <<EOF > docs/SUMMARY.md
# Summary
- [Introduction](<Element Web/README.md>)
EOF
cat SUMMARY.md >> docs/SUMMARY.md
mv element-web/book.toml .
- name: Build docs
run: mdbook build
- name: Upload artifact
uses: actions/upload-pages-artifact@v2
with:
path: ./book
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2

View File

@@ -3,7 +3,7 @@ on:
push:
branches: [develop]
paths:
- "src/i18n/strings/en_EN.json"
- "src/strings/i18n/en_EN.json"
jobs:
upload:
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_upload.yaml@main

View File

@@ -1,81 +0,0 @@
name: Cut branches
on:
workflow_dispatch:
inputs:
element-desktop:
description: Prepare element-desktop
required: true
type: boolean
default: true
element-web:
description: Prepare element-web
required: true
type: boolean
default: true
matrix-react-sdk:
description: Prepare matrix-react-sdk
required: true
type: boolean
default: true
matrix-js-sdk:
description: Prepare matrix-js-sdk
required: true
type: boolean
default: true
jobs:
prepare:
runs-on: ubuntu-latest
steps:
- name: Checkout Element Desktop
uses: actions/checkout@v4
if: inputs.element-desktop
with:
repository: vector-im/element-desktop
path: element-desktop
ref: staging
fetch-depth: 0
fetch-tags: true
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- name: Checkout Element Web
uses: actions/checkout@v4
if: inputs.element-web
with:
repository: vector-im/element-web
path: element-web
ref: staging
fetch-depth: 0
fetch-tags: true
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- name: Checkout Matrix React SDK
uses: actions/checkout@v4
if: inputs.matrix-react-sdk
with:
repository: matrix-org/matrix-react-sdk
path: matrix-react-sdk
ref: staging
fetch-depth: 0
fetch-tags: true
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- name: Checkout Matrix JS SDK
uses: actions/checkout@v4
if: inputs.matrix-js-sdk
with:
repository: matrix-org/matrix-js-sdk
path: matrix-js-sdk
ref: staging
fetch-depth: 0
fetch-tags: true
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- name: Resolve repos
run: |
echo "REPOS=$(ls . | tr '\n' ' ')" >> $GITHUB_ENV
- name: Merge develop
run: |
git config --global user.email "releases@riot.im"
git config --global user.name "RiotRobot"
for REPO in $REPOS; do git -C "$REPO" merge origin/develop; done
- name: Push staging
run: for REPO in $REPOS; do git -C "$REPO" push origin staging; done

View File

@@ -27,7 +27,7 @@ jobs:
- name: Get number of CPU cores
id: cpu-cores
uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2
uses: SimenB/github-actions-cpu-cores@410541432439795d30db6501fb1d8178eb41e502 # v1
- name: Run tests with coverage
run: "yarn coverage --ci --max-workers ${{ steps.cpu-cores.outputs.count }}"

View File

@@ -10,7 +10,7 @@ jobs:
if: |
contains(github.event.issue.assignees.*.login, 't3chguy') ||
contains(github.event.issue.assignees.*.login, 'andybalaam') ||
contains(github.event.issue.assignees.*.login, 'MidhunSureshR')
contains(github.event.issue.assignees.*.login, 'justjanne')
steps:
- uses: actions/add-to-project@main
with:

View File

@@ -20,8 +20,7 @@ jobs:
contains(github.event.issue.labels.*.name, 'A-Video-Rooms') ||
contains(github.event.issue.labels.*.name, 'A-Message-Starring') ||
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor') ||
contains(github.event.issue.labels.*.name, 'A-Element-Call') ||
contains(github.event.issue.labels.*.name, 'A-Element-R')
contains(github.event.issue.labels.*.name, 'A-Element-Call')
steps:
- uses: actions/github-script@v6
with:
@@ -100,6 +99,45 @@ jobs:
project-url: https://github.com/orgs/vector-im/projects/48
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features1:
name: Add labelled issues to PS features team 1
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Polls') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
(contains(github.event.issue.labels.*.name, 'A-Voice-Messages') &&
!contains(github.event.issue.labels.*.name, 'A-Broadcast')) ||
(contains(github.event.issue.labels.*.name, 'A-Session-Mgmt') &&
contains(github.event.issue.labels.*.name, 'A-User-Settings'))
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/vector-im/projects/56
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features2:
name: Add labelled issues to PS features team 2
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-DM-Start') ||
contains(github.event.issue.labels.*.name, 'A-Broadcast')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/vector-im/projects/58
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features3:
name: Add labelled issues to PS features team 3
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/vector-im/projects/57
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
voip:
name: Add labelled issues to VoIP project board
runs-on: ubuntu-latest
@@ -121,42 +159,3 @@ jobs:
with:
project-url: https://github.com/orgs/vector-im/projects/57
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
tech_debt:
name: Add labelled issues to tech debt project
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Developer-Experience') ||
contains(github.event.issue.labels.*.name, 'A-Documentation') ||
contains(github.event.issue.labels.*.name, 'A-Packaging') ||
contains(github.event.issue.labels.*.name, 'A-Technical-Debt') ||
contains(github.event.issue.labels.*.name, 'A-Testing') ||
contains(github.event.issue.labels.*.name, 'Z-Flaky-Test')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/vector-im/projects/101
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
element_r:
name: Add Element R issues to Crypto Team board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Element-R')
steps:
- id: add_to_project
uses: actions/add-to-project@v0.5.0
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: set_fields
uses: titoportas/update-project-fields@020b5aa9db8f9501d4b16d6417c2132ff26e6279 # v0.1.0
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
item-id: ${{ steps.add_to_project.outputs.itemId }} # Use the item-id output of the previous step
field-keys: Workstream,module
field-values: Element-R,web
env:
PROJECT_URL: https://github.com/orgs/vector-im/projects/76

View File

@@ -62,14 +62,7 @@ jobs:
headers,
});
if (!res.ok) {
console.log(roomId, "failed to fetch", await res.text());
return;
}
const data = await res.json();
console.log(roomId, "got event", data);
const topic = data.topic.replace(regex, releaseTopic);
if (topic === data.topic) {
console.log(roomId, "nothing to do");

View File

@@ -0,0 +1,8 @@
name: Upgrade Dependencies
on:
workflow_dispatch: {}
jobs:
upgrade:
uses: matrix-org/matrix-js-sdk/.github/workflows/upgrade_dependencies.yml@develop
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

2
.gitignore vendored
View File

@@ -27,5 +27,3 @@ electron/pub
# Auto-generated file
/src/modules.ts
/build_config.yaml
/book
/index.html

View File

@@ -22,7 +22,6 @@ electron/pub
# Raises an error because it contains a template var breaking the script tag
src/vector/index.html
src/vector/modernizr.js
/docs/lib
# This file is owned, parsed, and generated by allchange, which doesn't comply with prettier
/CHANGELOG.md

View File

@@ -1,125 +1,3 @@
Changes in [1.11.48](https://github.com/vector-im/element-web/releases/tag/v1.11.48) (2023-11-07)
=================================================================================================
## ✨ Features
* Correctly fill window.matrixChat even when a Wrapper module is active ([\#26395](https://github.com/vector-im/element-web/pull/26395)). Contributed by @dhenneke.
* Knock on a ask-to-join room if a module wants to join the room when navigating to a room ([\#11787](https://github.com/matrix-org/matrix-react-sdk/pull/11787)). Contributed by @dhenneke.
* Element-R: Include crypto info in sentry ([\#11798](https://github.com/matrix-org/matrix-react-sdk/pull/11798)). Contributed by @florianduros.
* Element-R: Include crypto info in rageshake ([\#11797](https://github.com/matrix-org/matrix-react-sdk/pull/11797)). Contributed by @florianduros.
* Element-R: Add current version of the rust-sdk and vodozemac ([\#11785](https://github.com/matrix-org/matrix-react-sdk/pull/11785)). Contributed by @florianduros.
* Fix unfederated invite dialog ([\#9618](https://github.com/matrix-org/matrix-react-sdk/pull/9618)). Fixes vector-im/element-meta#1466 and #22102. Contributed by @owi92.
* New right panel visual language ([\#11664](https://github.com/matrix-org/matrix-react-sdk/pull/11664)).
* OIDC: add friendly errors ([\#11184](https://github.com/matrix-org/matrix-react-sdk/pull/11184)). Fixes #25665. Contributed by @kerryarchibald.
## 🐛 Bug Fixes
* Fix rightpanel hiding scrollbar ([\#11831](https://github.com/matrix-org/matrix-react-sdk/pull/11831)). Contributed by @kerryarchibald.
* Fix multi-tab session lock on Firefox not being cleared ([\#11800](https://github.com/matrix-org/matrix-react-sdk/pull/11800)). Fixes #26165. Contributed by @ManuelHu.
* Deserialise spoilers back into slash command form ([\#11805](https://github.com/matrix-org/matrix-react-sdk/pull/11805)). Fixes #26344.
* Fix Incorrect message scaling for verification request ([\#11793](https://github.com/matrix-org/matrix-react-sdk/pull/11793)). Fixes #24304. Contributed by @capGoblin.
* Fix: Unable to restore a soft-logged-out session established via SSO ([\#11794](https://github.com/matrix-org/matrix-react-sdk/pull/11794)). Fixes #25957. Contributed by @kerryarchibald.
* Use configurable github issue links more consistently ([\#11796](https://github.com/matrix-org/matrix-react-sdk/pull/11796)).
* Fix io.element.late_event received_ts vs received_at ([\#11789](https://github.com/matrix-org/matrix-react-sdk/pull/11789)).
* Make invitation dialog scrollable when infos are too long ([\#11753](https://github.com/matrix-org/matrix-react-sdk/pull/11753)). Contributed by @nurjinjafar.
* Fix spoiler text-align ([\#11790](https://github.com/matrix-org/matrix-react-sdk/pull/11790)). Contributed by @ajbura.
* Fix: Right panel keeps showing chat when unmaximizing widget. ([\#11697](https://github.com/matrix-org/matrix-react-sdk/pull/11697)). Fixes #26265. Contributed by @manancodes.
* Fix margin of invite to room button ([\#11780](https://github.com/matrix-org/matrix-react-sdk/pull/11780)). Fixes #26410.
* Update base64 import ([\#11784](https://github.com/matrix-org/matrix-react-sdk/pull/11784)).
* Set max size for Element logo in search warning ([\#11779](https://github.com/matrix-org/matrix-react-sdk/pull/11779)). Fixes #26408.
* Fix: emoji size in room header topic, remove obsolete emoji style ([\#11757](https://github.com/matrix-org/matrix-react-sdk/pull/11757)). Fixes #26326. Contributed by @kerryarchibald.
* Fix: Bubble layout design is broken ([\#11763](https://github.com/matrix-org/matrix-react-sdk/pull/11763)). Fixes #25818. Contributed by @manancodes.
Changes in [1.11.47](https://github.com/vector-im/element-web/releases/tag/v1.11.47) (2023-10-24)
=================================================================================================
## 🦖 Deprecations
* Deprecate customisations in favour of Module API ([\#25736](https://github.com/vector-im/element-web/pull/25736)). Fixes #25733.
## ✨ Features
* vector-im/element-x-ios/issues/1824 - Convert the apple-app-site-association file to a newer format… ([\#26307](https://github.com/vector-im/element-web/pull/26307)). Contributed by @stefanceriu.
* Iterate `io.element.late_event` decoration ([\#11760](https://github.com/matrix-org/matrix-react-sdk/pull/11760)). Fixes #26384.
* Render timeline separator for late event groups ([\#11739](https://github.com/matrix-org/matrix-react-sdk/pull/11739)).
* OIDC: revoke tokens on logout ([\#11718](https://github.com/matrix-org/matrix-react-sdk/pull/11718)). Fixes #25394. Contributed by @kerryarchibald.
* Show `io.element.late_event` in MessageTimestamp when known ([\#11733](https://github.com/matrix-org/matrix-react-sdk/pull/11733)).
* Show all labs flags if developerMode enabled ([\#11746](https://github.com/matrix-org/matrix-react-sdk/pull/11746)). Fixes #24571 and #8498.
* Use Compound tooltips on MessageTimestamp to improve UX of date time discovery ([\#11732](https://github.com/matrix-org/matrix-react-sdk/pull/11732)). Fixes #25913.
* Consolidate 4s passphrase input fields and use stable IDs ([\#11743](https://github.com/matrix-org/matrix-react-sdk/pull/11743)). Fixes #26228.
* Disable upgraderoom command without developer mode enabled ([\#11744](https://github.com/matrix-org/matrix-react-sdk/pull/11744)). Fixes #17620.
* Avoid rendering app download buttons if disabled in config ([\#11741](https://github.com/matrix-org/matrix-react-sdk/pull/11741)). Fixes #26309.
* OIDC: refresh tokens ([\#11699](https://github.com/matrix-org/matrix-react-sdk/pull/11699)). Fixes #25839. Contributed by @kerryarchibald.
* OIDC: register ([\#11727](https://github.com/matrix-org/matrix-react-sdk/pull/11727)). Fixes #25393. Contributed by @kerryarchibald.
* Use stable get_login_token and remove unstable MSC3882 support ([\#11001](https://github.com/matrix-org/matrix-react-sdk/pull/11001)). Contributed by @hughns.
## 🐛 Bug Fixes
* Set max size for Element logo in search warning ([\#11779](https://github.com/matrix-org/matrix-react-sdk/pull/11779)). Fixes #26408.
* Avoid error when DMing oneself ([\#11754](https://github.com/matrix-org/matrix-react-sdk/pull/11754)). Fixes #7242.
* Fix: Message shield alignment is not right. ([\#11703](https://github.com/matrix-org/matrix-react-sdk/pull/11703)). Fixes #26142. Contributed by @manancodes.
* fix logging full event ([\#11755](https://github.com/matrix-org/matrix-react-sdk/pull/11755)). Fixes #26376.
* OIDC: use delegated auth account URL from `OidcClientStore` ([\#11723](https://github.com/matrix-org/matrix-react-sdk/pull/11723)). Fixes #26305. Contributed by @kerryarchibald.
* Fix: Members list shield alignment is not right. ([\#11700](https://github.com/matrix-org/matrix-react-sdk/pull/11700)). Fixes #26261. Contributed by @manancodes.
* Fix: <detail> HTML elements clickable area too wide. ([\#11666](https://github.com/matrix-org/matrix-react-sdk/pull/11666)). Fixes #25454. Contributed by @manancodes.
* Fix untranslated headings in the devtools dialog ([\#11734](https://github.com/matrix-org/matrix-react-sdk/pull/11734)).
* Fixes invite dialog alignment and pill color contrast ([\#11722](https://github.com/matrix-org/matrix-react-sdk/pull/11722)). Contributed by @gabrc52.
* Prevent select element in General settings overflowing in a room with very long room-id ([\#11597](https://github.com/matrix-org/matrix-react-sdk/pull/11597)). Contributed by @ABHIXIT2.
* Fix: Clicking on members pile does nothing. ([\#11657](https://github.com/matrix-org/matrix-react-sdk/pull/11657)). Fixes #26164. Contributed by @manancodes.
* Fix: Wierd shadow below room avatar in dark mode. ([\#11678](https://github.com/matrix-org/matrix-react-sdk/pull/11678)). Fixes #26153. Contributed by @manancodes.
* Fix start_sso / start_cas URLs failing to redirect to a authentication prompt ([\#11681](https://github.com/matrix-org/matrix-react-sdk/pull/11681)). Contributed by @Half-Shot.
Changes in [1.11.46](https://github.com/vector-im/element-web/releases/tag/v1.11.46) (2023-10-10)
=================================================================================================
## ✨ Features
* Use .well-known to discover a default rendezvous server for use with Sign in with QR ([\#11655](https://github.com/matrix-org/matrix-react-sdk/pull/11655)). Contributed by @hughns.
* Message layout will update according to the selected style ([\#10170](https://github.com/matrix-org/matrix-react-sdk/pull/10170)). Fixes #21782. Contributed by @manancodes.
* Implement MSC4039: Add an MSC for a new Widget API action to upload files into the media repository ([\#11311](https://github.com/matrix-org/matrix-react-sdk/pull/11311)). Contributed by @dhenneke.
* Render space pills with square corners to match new avatar ([\#11632](https://github.com/matrix-org/matrix-react-sdk/pull/11632)). Fixes #26056.
* Linkify room topic ([\#11631](https://github.com/matrix-org/matrix-react-sdk/pull/11631)). Fixes #26185.
* Show knock rooms in the list ([\#11573](https://github.com/matrix-org/matrix-react-sdk/pull/11573)). Contributed by @maheichyk.
## 🐛 Bug Fixes
* Bump matrix-web-i18n dependency to 3.1.3 ([\#26287](https://github.com/vector-im/element-web/pull/26287))
* Fix: Avatar shrinks with long names ([\#11698](https://github.com/matrix-org/matrix-react-sdk/pull/11698)). Fixes #26252. Contributed by @manancodes.
* Update custom translations to support nested fields in structured JSON ([\#11685](https://github.com/matrix-org/matrix-react-sdk/pull/11685)).
* Fix: Edited message remove button is hard to reach. ([\#11674](https://github.com/matrix-org/matrix-react-sdk/pull/11674)). Fixes #24917. Contributed by @manancodes.
* Fix: Theme selector radio button not aligned in center with the text ([\#11676](https://github.com/matrix-org/matrix-react-sdk/pull/11676)). Fixes #25460. Contributed by @manancodes.
* Fix: Unread notification dot aligned ([\#11658](https://github.com/matrix-org/matrix-react-sdk/pull/11658)). Fixes #25285. Contributed by @manancodes.
* Fix: sync intentional mentions push rules with legacy rules ([\#11667](https://github.com/matrix-org/matrix-react-sdk/pull/11667)). Fixes #26227. Contributed by @kerryarchibald.
* Revert "Fix regression around FacePile with overflow (#11527)" ([\#11634](https://github.com/matrix-org/matrix-react-sdk/pull/11634)). Fixes #26209.
* Fix: Alignment Fixed ([\#11648](https://github.com/matrix-org/matrix-react-sdk/pull/11648)). Fixes #26169. Contributed by @manancodes.
* Fix: onFinished added which closes the menu ([\#11647](https://github.com/matrix-org/matrix-react-sdk/pull/11647)). Fixes #25556. Contributed by @manancodes.
* Don't start key backups when opening settings ([\#11640](https://github.com/matrix-org/matrix-react-sdk/pull/11640)).
* Fix add to space avatar text centering ([\#11643](https://github.com/matrix-org/matrix-react-sdk/pull/11643)). Fixes #26154.
* fix avatar styling in lightbox ([\#11641](https://github.com/matrix-org/matrix-react-sdk/pull/11641)). Fixes #26196.
Changes in [1.11.45](https://github.com/vector-im/element-web/releases/tag/v1.11.45) (2023-09-29)
=================================================================================================
## 🐛 Bug Fixes
* Fix Emoji font on Safari 17 ([\#11673](https://github.com/matrix-org/matrix-react-sdk/pull/11673)).
Changes in [1.11.44](https://github.com/vector-im/element-web/releases/tag/v1.11.44) (2023-09-26)
=================================================================================================
## ✨ Features
* Make video & voice call buttons pin conference widget if unpinned ([\#11576](https://github.com/matrix-org/matrix-react-sdk/pull/11576)). Fixes vector-im/customer-retainer#72.
* OIDC: persist refresh token ([\#11249](https://github.com/matrix-org/matrix-react-sdk/pull/11249)). Contributed by @kerryarchibald.
* ElementR: Cross user verification ([\#11364](https://github.com/matrix-org/matrix-react-sdk/pull/11364)). Fixes #25752. Contributed by @florianduros.
* Default intentional mentions ([\#11602](https://github.com/matrix-org/matrix-react-sdk/pull/11602)).
* Notify users about denied access on ask-to-join rooms ([\#11480](https://github.com/matrix-org/matrix-react-sdk/pull/11480)). Contributed by @nurjinjafar.
* Allow setting knock room directory visibility ([\#11529](https://github.com/matrix-org/matrix-react-sdk/pull/11529)). Contributed by @charlynguyen.
## 🐛 Bug Fixes
* Revert "Fix regression around FacePile with overflow (#11527)" ([\#11634](https://github.com/matrix-org/matrix-react-sdk/pull/11634)). Fixes #26209.
* Escape placeholder before injecting it into the style ([\#11607](https://github.com/matrix-org/matrix-react-sdk/pull/11607)).
* Move ViewUser action callback to RoomView ([\#11495](https://github.com/matrix-org/matrix-react-sdk/pull/11495)). Fixes #26040.
* Fix room timeline search toggling behaviour edge case ([\#11605](https://github.com/matrix-org/matrix-react-sdk/pull/11605)). Fixes #26105.
* Avoid rendering view-message link in RoomKnocksBar unnecessarily ([\#11598](https://github.com/matrix-org/matrix-react-sdk/pull/11598)). Contributed by @charlynguyen.
* Use knock rooms sync to reflect the knock state ([\#11596](https://github.com/matrix-org/matrix-react-sdk/pull/11596)). Fixes #26043 and #26044. Contributed by @charlynguyen.
* Fix avatar in right panel not using the correct font ([\#11593](https://github.com/matrix-org/matrix-react-sdk/pull/11593)). Fixes #26061. Contributed by @MidhunSureshR.
* Add waits in Spotlight Cypress tests, hoping this unflakes them ([\#11590](https://github.com/matrix-org/matrix-react-sdk/pull/11590)). Fixes #26053, #26140 #26139 and #26138. Contributed by @andybalaam.
* Fix vertical alignment of default avatar font ([\#11582](https://github.com/matrix-org/matrix-react-sdk/pull/11582)). Fixes #26081.
* Fix avatars in public room & space search being flex shrunk ([\#11580](https://github.com/matrix-org/matrix-react-sdk/pull/11580)). Fixes #26133.
* Fix EventTile avatars being rendered with a size of 0 instead of hidden ([\#11558](https://github.com/matrix-org/matrix-react-sdk/pull/11558)). Fixes #26075.
Changes in [1.11.43](https://github.com/vector-im/element-web/releases/tag/v1.11.43) (2023-09-15)
=================================================================================================

View File

@@ -204,7 +204,7 @@ and we'll try to fix it :)
In order to have a concrete record that your contribution is intentional
and you agree to license it under the same terms as the project's license, we've
adopted the same lightweight approach that the Linux Kernel
(https://www.kernel.org/doc/html/latest/process/submitting-patches.html), Docker
(https://www.kernel.org/doc/Documentation/SubmittingPatches), Docker
(https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other
projects use: the DCO (Developer Certificate of Origin:
http://developercertificate.org/). This is a simple declaration that you wrote

View File

@@ -1,32 +0,0 @@
# Documentation for possible options in this file is at
# https://rust-lang.github.io/mdBook/format/config.html
[book]
title = "Element Web & Desktop"
authors = ["New Vector Ltd.", "The Matrix.org Foundation C.I.C."]
language = "en"
multilingual = false
# The directory that documentation files are stored in
src = "docs"
[build]
# Prevent markdown pages from being automatically generated when they're
# linked to in SUMMARY.md
create-missing = false
[output.html]
# Remove the numbers that appear before each item in the sidebar, as they can
# get quite messy as we nest deeper
no-section-label = true
# The source code URL of the repository
git-repository-url = "https://github.com/vector-im/element-web"
# The path that the docs are hosted on
site-url = "/element-web/"
additional-js = ["docs/lib/mermaid.min.js", "docs/lib/mermaid-init.js"]
[preprocessor]
[preprocessor.mermaid]
command = "mdbook-mermaid"

View File

@@ -113,30 +113,17 @@ Unless otherwise specified, the following applies to all code:
}
```
14. If a variable's type should be boolean, make sure it really is one.
```typescript
const isRealUser = !!userId && ...; // good
const isRealUser = Boolean(userId) && Boolean(userName); // also good
const isRealUser = Boolean(userId) && isReal; // also good (where isReal is another boolean variable)
const isRealUser = Boolean(userId && userName); // also fine
const isRealUser = Boolean(userId || userName); // good: same as &&
const isRealUser = userId && ...; // bad: isRealUser is userId's type, not a boolean
if (userId) // fine: userId is evaluated for truthiness, not stored as a boolean
```
15. Use `switch` statements when checking against more than a few enum-like values.
16. Use `const` for constants, `let` for mutability.
17. Describe types exhaustively (ensure noImplictAny would pass).
14. Use `switch` statements when checking against more than a few enum-like values.
15. Use `const` for constants, `let` for mutability.
16. Describe types exhaustively (ensure noImplictAny would pass).
1. Notable exceptions are arrow functions used as parameters, when a void return type is
obvious, and when declaring and assigning a variable in the same line.
18. Declare member visibility (public/private/protected).
19. Private members are private and not prefixed unless required for naming conflicts.
17. Declare member visibility (public/private/protected).
18. Private members are private and not prefixed unless required for naming conflicts.
1. Convention is to use an underscore or the word "internal" to denote conflicted member names.
2. "Conflicted" typically refers to a getter which wants the same name as the underlying variable.
20. Prefer readonly members over getters backed by a variable, unless an internal setter is required.
21. Prefer Interfaces for object definitions, and types for parameter-value-only declarations.
19. Prefer readonly members over getters backed by a variable, unless an internal setter is required.
20. Prefer Interfaces for object definitions, and types for parameter-value-only declarations.
1. Note that an explicit type is optional if not expected to be used outside of the function call,
unlike in this example:
@@ -153,9 +140,9 @@ Unless otherwise specified, the following applies to all code:
}
```
22. Variables/properties which are `public static` should also be `readonly` when possible.
23. Interface and type properties are terminated with semicolons, not commas.
24. Prefer arrow formatting when declaring functions for interfaces/types:
21. Variables/properties which are `public static` should also be `readonly` when possible.
22. Interface and type properties are terminated with semicolons, not commas.
23. Prefer arrow formatting when declaring functions for interfaces/types:
```typescript
interface Test {
@@ -163,13 +150,13 @@ Unless otherwise specified, the following applies to all code:
}
```
25. Prefer a type definition over an inline type. For example, define an interface.
26. Always prefer to add types or declare a type over the use of `any`. Prefer inferred types
24. Prefer a type definition over an inline type. For example, define an interface.
25. Always prefer to add types or declare a type over the use of `any`. Prefer inferred types
when they are not `any`.
1. When using `any`, a comment explaining why must be present.
27. `import` should be used instead of `require`, as `require` does not have types.
28. Export only what can be reused.
29. Prefer a type like `Optional<X>` (`type Optional<T> = T | null | undefined`) instead
26. `import` should be used instead of `require`, as `require` does not have types.
27. Export only what can be reused.
28. Prefer a type like `Optional<X>` (`type Optional<T> = T | null | undefined`) instead
of truly optional parameters.
1. A notable exception is when the likelihood of a bug is minimal, such as when a function
@@ -187,12 +174,12 @@ Unless otherwise specified, the following applies to all code:
}
```
30. There should be approximately one interface, class, or enum per file unless the file is named
29. There should be approximately one interface, class, or enum per file unless the file is named
"types.ts", "global.d.ts", or ends with "-types.ts".
1. The file name should match the interface, class, or enum name.
31. Bulk functions can be declared in a single file, though named as "foo-utils.ts" or "utils/foo.ts".
32. Imports are grouped by external module imports first, then by internal imports.
33. File ordering is not strict, but should generally follow this sequence:
30. Bulk functions can be declared in a single file, though named as "foo-utils.ts" or "utils/foo.ts".
31. Imports are grouped by external module imports first, then by internal imports.
32. File ordering is not strict, but should generally follow this sequence:
1. Licence header
2. Imports
3. Constants
@@ -207,16 +194,16 @@ Unless otherwise specified, the following applies to all code:
5. Protected and abstract functions
6. Public/private functions
7. Public/protected/private static functions
34. Variable names should be noticeably unique from their types. For example, "str: string" instead
33. Variable names should be noticeably unique from their types. For example, "str: string" instead
of "string: string".
35. Use double quotes to enclose strings. You may use single quotes if the string contains double quotes.
34. Use double quotes to enclose strings. You may use single quotes if the string contains double quotes.
```typescript
const example1 = "simple string";
const example2 = 'string containing "double quotes"';
```
36. Prefer async-await to promise-chaining
35. Prefer async-await to promise-chaining
```typescript
async function () {

View File

@@ -1,39 +0,0 @@
# Summary
- [Introduction](../README.md)
# Usage
- [Betas](betas.md)
- [Labs](labs.md)
# Setup
- [Config](config.md)
- [Custom home page](custom-home.md)
- [Kubernetes](kubernetes.md)
- [Jitsi](jitsi.md)
- [Encryption](e2ee.md)
# Build
- [Customisations](customisations.md)
- [Modules](modules.md)
- [Native Node modules](native-node-modules.md)
# Contribution
- [Choosing an issue](choosing-an-issue.md)
- [Translation](translating.md)
- [Netlify builds](pr-previews.md)
- [Code review](review.md)
# Development
- [App load order](app-load.md)
- [Translation](translating-dev.md)
- [Theming](theming.md)
- [Memory profiling](memory-profiles-and-leaks.md)
- [Jitsi](jitsi-dev.md)
- [Feature flags](feature-flags.md)
- [OIDC and delegated authentication](oidc.md)

View File

@@ -4,67 +4,78 @@
been kept untouched for posterity.
Old slow flow:
```mermaid
flowchart TD
A1(((load_modernizr))) --> B
A2((rageshake)) --> B
B(((skin))) --> C
C(((olm))) --> D
D{mobile} --> E
E((config)) --> F
F((i18n)) --> G
style F stroke:lime
G(((theme))) --> H
H(((modernizr))) --> app
style H stroke:red
```
![image](https://user-images.githubusercontent.com/2403652/73848963-00a2a080-4821-11ea-97d4-1200fc2638f3.png)
Current more parallel flow:
![image](https://user-images.githubusercontent.com/2403652/83146440-303a2900-a0ee-11ea-806b-4f53f039b957.png)
```mermaid
flowchart TD
subgraph index.ts
style index.ts stroke:orange
<details><summary>Code</summary>
<p>
<pre><code>
digraph G {
node [shape=box];
A[/rageshake/] --> B{mobile}
B-- No -->C1(.)
B-- Yes -->C2((redirect))
C1 --> D[/olm/] --> R
C1 --> E[platform] --> F[/config/]
F --> G1[/skin/]
F --> R
G1 --> H
G1 --> R
F --> G2[/theme/]
G2 --> H
G2 --> R
F --> G3[/i18n/]
G3 --> H
G3 --> R
H{modernizr}-- No --> J((incompatible))-- user ignore --> R
H-- Yes --> R
subgraph cluster_0 {
color=orange;
node [style=filled];
label = "index.ts";
linkStyle 0,7,9,11,12,14,15 stroke:blue;
linkStyle 4,8,10,13,16 stroke:red;
end
entrypoint, s0, ready [shape=point];
rageshake, config, i18n, theme, skin, olm [shape=parallelogram];
mobile [shape=diamond, label="mobile"];
modernizr [shape=diamond];
redirect, incompatible [shape=egg];
R>ready] --> 2A
style R stroke:gray
entrypoint -> rageshake;
rageshake -> mobile [color=blue];
mobile -> s0 [label="No"];
mobile -> redirect [label="Yes"];
subgraph init.tsx
style init.tsx stroke:lime
2A[loadApp] --> 2B[matrixchat]
end
s0 -> platform;
s0 -> olm;
platform -> config;
```
config -> i18n [color=blue];
config -> theme [color=blue];
config -> skin [color=blue];
i18n -> modernizr [color=blue];
theme -> modernizr [color=blue];
skin -> modernizr [color=blue];
modernizr -> ready [label="Yes"];
modernizr -> incompatible [label="No"];
incompatible -> ready [label="user ignore"];
olm -> ready [color=red];
config -> ready [color=red];
skin -> ready [color=red];
theme -> ready [color=red];
i18n -> ready [color=red];
}
subgraph cluster_1 {
color = green;
node [style=filled];
label = "init.tsx";
ready -> loadApp;
loadApp -> matrixchat;
}
}
</code></pre>
</p>
</details>
Key:
- Parallelogram: async/await task
- Box: sync task
- Diamond: conditional branch
- Circle: user interaction
- Egg: user interaction
- Blue arrow: async task is allowed to settle but allowed to fail
- Red arrow: async task success is asserted
@@ -75,34 +86,4 @@ Notes:
- Everything is awaited to be settled before the Modernizr check, to allow it to make use of things like i18n if they are successful.
Underlying dependencies:
```mermaid
flowchart TD
A((rageshake))
B{mobile}
C((config))
D(((olm)))
E((i18n))
F(((load_modernizr)))
G(((modernizr)))
H(((skin)))
I(((theme)))
X[app]
A --> G
A --> B
A-- assert -->X
F --> G --> X
G --> H --> X
C --> I --> X
C --> E --> X
E --> G
B --> C-- assert -->X
B --> D --> X
style X stroke:red
style G stroke:red
style E stroke:lime
linkStyle 0,11 stroke:yellow;
linkStyle 2,13 stroke:red;
```
![image](https://user-images.githubusercontent.com/2403652/73848977-08624500-4821-11ea-9830-bb0317c41086.png)

View File

@@ -54,8 +54,8 @@ One of the following options **must** be supplied:
being optional.
If both `default_server_config` and `default_server_name` are used, Element will try to look up the connection
information using `.well-known`, and if that fails, take `default_server_config` as the homeserver connection
information.
infomation using `.well-known`, and if that fails, take `default_server_config` as the homeserver connection
infomation.
## Labs flags
@@ -139,7 +139,7 @@ complete re-branding/private labeling, a more personalised experience can be ach
configuration found in the well-known location is used instead.
10. `welcome_user_id`: An optional user ID to start a DM with after creating an account. Defaults to nothing (no DM created).
11. `custom_translations_url`: An optional URL to allow overriding of translatable strings. The JSON file must be in a format of
`{"affected|translation|key": {"languageCode": "new string"}}`. See https://github.com/matrix-org/matrix-react-sdk/pull/7886 for details.
`{"affected string": {"languageCode": "new string"}}`. See https://github.com/matrix-org/matrix-react-sdk/pull/7886 for details.
12. `branding`: Options for configuring various assets used within the app. Described in more detail down below.
13. `embedded_pages`: Further optional URLs for various assets used within the app. Described in more detail down below.
14. `disable_3pid_login`: When `false` (default), **enables** the options to log in with email address or phone number. Set to
@@ -355,8 +355,6 @@ If you run your own rageshake server to collect bug reports, the following optio
2. `uisi_autorageshake_app`: If a user has enabled the "automatically send debug logs on decryption errors" flag, this option will be sent
alongside the rageshake so the rageshake server can filter them by app name. By default, this will be `element-auto-uisi`
(in contrast to other rageshakes submitted by the app, which use `element-web`).
3. `existing_issues_url`: URL for where to find existing issues.
4. `new_issue_url`: URL for where to submit new issues.
If you would like to use [Sentry](https://sentry.io/) for rageshake data, add a `sentry` object to your config with the following values:

View File

@@ -36,7 +36,7 @@ When `force_disable` is true:
- any `io.element.e2ee.default` value will be disregarded.
Note: If the server is configured to forcibly enable encryption for some or all rooms,
this behaviour will be overridden.
this behaviour will be overriden.
# Secure backup

View File

@@ -128,16 +128,12 @@ Enables rendering of MD / HTML in room topics.
Configures Element to use a new cryptography implementation based on the [matrix-rust-sdk](https://github.com/matrix-org/matrix-rust-sdk).
This setting is (currently) _sticky_ to a user's session: it only takes effect when the user logs in to a new session. Likewise, even after disabling the setting in `config.json`, the Rust implementation will remain in use until users log out.
This setting is (currently) _sticky_ to a user's session: it only takes effect when the user logs in to a new session. Likewise, even after disabling the setting in `config.json`, the Rust implemention will remain in use until users log out.
## New room header & details (`feature_new_room_decoration_ui`) [In Development]
Refactors visually the room header and room sidebar
## Enable the notifications panel in the room header (`feature_notifications`)
Unreliable in encrypted rooms.
## Knock rooms (`feature_ask_to_join`) [In Development]
Enables knock feature for rooms. This allows users to ask to join a room.

View File

@@ -1 +0,0 @@
mermaid.initialize({ startOnLoad:true });

1648
docs/lib/mermaid.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -1,43 +0,0 @@
# OIDC and delegated authentication
## Compatibility/OIDC-aware mode
[MSC2965: OIDC provider discovery](https://github.com/matrix-org/matrix-spec-proposals/pull/2965)
[MSC3824: OIDC aware clients](https://github.com/matrix-org/matrix-spec-proposals/pull/3824)
This mode uses an SSO flow to gain a `loginToken` from the authentication provider, then continues with SSO login.
Element Web uses [MSC2965: OIDC provider discovery](https://github.com/matrix-org/matrix-spec-proposals/pull/2965) to discover the configured provider.
Wherever valid MSC2965 configuration is discovered, OIDC-aware login flow will be the only option offered.
## (🧪Experimental) OIDC-native flow
Can be enabled by a config-level-only setting in `config.json`
```json
{
"features": {
"feature_oidc_native_flow": true
}
}
```
See https://areweoidcyet.com/client-implementation-guide/ for implementation details.
Element Web uses [MSC2965: OIDC provider discovery](https://github.com/matrix-org/matrix-spec-proposals/pull/2965) to discover the configured provider.
Where OIDC native login flow is enabled and valid MSC2965 configuration is discovered, OIDC native login flow will be the only login option offered.
Element Web will attempt to [dynamically register](https://openid.net/specs/openid-connect-registration-1_0.html) with the configured OP.
Then, authentication will be completed [as described here](https://areweoidcyet.com/client-implementation-guide/).
#### Statically configured OIDC clients
Clients that are already registered with the OP can configure their `client_id` in `config.json`.
Where static configuration exists for the OP dynamic client registration will not be attempted.
```json
{
"oidc_static_clients": {
"https://dummyoidcprovider.com/": {
"client_id": "abc123"
}
}
}
```

View File

@@ -70,7 +70,7 @@ There you can also require all translations to be redone if the meaning of the s
1. Add it to the array in `_t` for example `_t(TKEY, {variable: this.variable})`
1. Add the variable inside the string. The syntax for variables is `%(variable)s`. Please note the _s_ at the end. The name of the variable has to match the previous used name.
- You can use the special `count` variable to choose between multiple versions of the same string, in order to get the correct pluralization. E.g. `_t('You have %(count)s new messages', { count: 2 })` would show 'You have 2 new messages', while `_t('You have %(count)s new messages', { count: 1 })` would show 'You have one new message' (assuming a singular version of the string has been added to the translation file. See above). Passing in `count` is much preferred over having an if-statement choose the correct string to use, because some languages have much more complicated plural rules than english (e.g. they might need a completely different form if there are three things rather than two).
- You can use the special `count` variable to choose between multiple versions of the same string, in order to get the correct pluralization. E.g. `_t('You have %(count)s new messages', { count: 2 })` would show 'You have 2 new messages', while `_t('You have %(count)s new messages', { count: 1 })` would show 'You have one new message' (assuming a singular version of the string has been added to the translation file. See above). Passing in `count` is much prefered over having an if-statement choose the correct string to use, because some languages have much more complicated plural rules than english (e.g. they might need a completely different form if there are three things rather than two).
- If you want to translate text that includes e.g. hyperlinks or other HTML you have to also use tag substitution, e.g. `_t('<a>Click here!</a>', {}, { 'a': (sub) => <a>{sub}</a> })`. If you don't do the tag substitution you will end up showing literally '<a>' rather than making a hyperlink.
- You can also use React components with normal variable substitution if you want to insert HTML markup, e.g. `_t('Your email address is %(emailAddress)s', { emailAddress: <i>{userEmailAddress}</i> })`.

View File

@@ -1,5 +1,7 @@
# How to translate Element
# 🚨 Translations are currently frozen as we are migrating Translation Management Systems! 🚨
## Requirements
- Web Browser

View File

@@ -48,11 +48,10 @@
},
"privacy_policy_url": "https://element.io/cookie-policy",
"features": {
"feature_video_rooms": true,
"feature_rust_crypto": true
"feature_video_rooms": true
},
"element_call": {
"url": "https://call.element.dev"
"url": "https://element-call-livekit.netlify.app"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
}

View File

@@ -25,7 +25,10 @@ const config: Config = {
},
testMatch: ["<rootDir>/test/**/*-test.[tj]s?(x)"],
setupFiles: ["jest-canvas-mock"],
setupFilesAfterEnv: ["<rootDir>/node_modules/matrix-react-sdk/test/setupTests.ts"],
setupFilesAfterEnv: [
"<rootDir>/node_modules/matrix-react-sdk/test/setupTests.ts",
"<rootDir>/test/setup/setupLanguage.ts",
],
moduleNameMapper: {
"\\.(css|scss|pcss)$": "<rootDir>/__mocks__/cssMock.js",
"\\.(gif|png|ttf|woff2)$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/imageMock.js",

View File

@@ -1,6 +1,6 @@
{
"name": "element-web",
"version": "1.11.48",
"version": "1.11.43",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"repository": {
@@ -41,14 +41,14 @@
"build:res": "ts-node scripts/copy-res.ts",
"build:genfiles": "yarn build:res && yarn build:jitsi && yarn build:module_system",
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
"build:bundle": "webpack --progress --mode production",
"build:bundle-stats": "webpack --progress --mode production --json > webpack-stats.json",
"build:bundle": "webpack --progress --bail --mode production",
"build:bundle-stats": "webpack --progress --bail --mode production --json > webpack-stats.json",
"build:module_system": "tsc --project ./tsconfig.module_system.json && node ./lib/module_system/scripts/install.js",
"dist": "scripts/package.sh",
"start": "yarn build:module_system && 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 --https\"",
"start:res": "yarn build:jitsi && ts-node scripts/copy-res.ts -w",
"start:js": "webpack serve --output-path webapp --mode development",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --mode development --disable-host-check --hot",
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
"lint:js": "yarn lint:js:src && yarn lint:js:module_system",
"lint:js:src": "eslint --max-warnings 0 src test && prettier --check .",
@@ -66,18 +66,18 @@
"analyse:webpack-bundles": "webpack-bundle-analyzer webpack-stats.json webapp"
},
"resolutions": {
"@types/react-dom": "17.0.21",
"@types/react": "17.0.68"
"@types/react-dom": "17.0.19",
"@types/react": "17.0.58"
},
"dependencies": {
"@matrix-org/olm": "3.2.15",
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.14.tgz",
"@matrix-org/react-sdk-module-api": "^2.1.0",
"gfm.css": "^1.1.2",
"jsrsasign": "^10.5.25",
"katex": "^0.16.0",
"lodash": "^4.17.21",
"matrix-js-sdk": "30.0.0",
"matrix-react-sdk": "3.84.0",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop",
"matrix-widget-api": "^1.3.1",
"react": "17.0.2",
"react-dom": "17.0.2",
@@ -101,7 +101,7 @@
"@babel/preset-typescript": "^7.12.7",
"@babel/register": "^7.12.10",
"@babel/runtime": "^7.12.5",
"@casualbot/jest-sonar-reporter": "2.2.7",
"@casualbot/jest-sonar-reporter": "^2.2.5",
"@principalstudio/html-webpack-inject-preload": "^1.2.7",
"@sentry/webpack-plugin": "^2.0.0",
"@svgr/webpack": "^5.5.0",
@@ -111,10 +111,11 @@
"@types/jsrsasign": "^10.5.4",
"@types/loader-utils": "^2.0.4",
"@types/lodash": "^4.14.197",
"@types/modernizr": "^3.5.3",
"@types/node": "^16",
"@types/node-fetch": "^2.6.4",
"@types/react": "17.0.68",
"@types/react-dom": "17.0.21",
"@types/react": "17.0.58",
"@types/react-dom": "17.0.19",
"@types/ua-parser-js": "^0.7.36",
"@typescript-eslint/eslint-plugin": "^5.45.0",
"@typescript-eslint/parser": "^5.45.0",
@@ -124,20 +125,19 @@
"chokidar": "^3.5.1",
"concurrently": "^8.0.0",
"cpx": "1.5.0",
"cronstrue": "^2.41.0",
"css-loader": "^4",
"dotenv": "^16.0.2",
"eslint": "8.51.0",
"eslint": "8.48.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-deprecate": "0.8.4",
"eslint-plugin-deprecate": "0.7.0",
"eslint-plugin-import": "^2.26.0",
"eslint-plugin-matrix-org": "^1.0.0",
"eslint-plugin-react": "^7.28.0",
"eslint-plugin-react-hooks": "^4.3.0",
"eslint-plugin-unicorn": "^48.0.0",
"extract-text-webpack-plugin": "^4.0.0-beta.0",
"fake-indexeddb": "^5.0.0",
"fake-indexeddb": "^4.0.0",
"fetch-mock-jest": "^1.5.1",
"file-loader": "^6.0.0",
"fs-extra": "^11.0.0",
@@ -150,14 +150,14 @@
"json-loader": "^0.5.7",
"loader-utils": "^3.0.0",
"matrix-mock-request": "^2.5.0",
"matrix-web-i18n": "^3.1.3",
"matrix-web-i18n": "^3.1.1",
"mini-css-extract-plugin": "^1",
"minimist": "^1.2.6",
"mkdirp": "^3.0.0",
"modernizr": "^3.12.0",
"node-fetch": "^2.6.7",
"optimize-css-assets-webpack-plugin": "^6.0.0",
"postcss": "^8.4.31",
"postcss": "^8.4.16",
"postcss-easings": "^2.0.0",
"postcss-hexrgba": "2.0.1",
"postcss-import": "^12.0.1",
@@ -180,14 +180,14 @@
"terser-webpack-plugin": "^4.0.0",
"ts-node": "^10.9.1",
"ts-prune": "^0.10.3",
"typescript": "5.2.2",
"webpack": "^4.47.0",
"typescript": "5.1.6",
"webpack": "^4.46.0",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^4.10.0",
"webpack-dev-server": "^4.15.1",
"webpack-cli": "^3.3.12",
"webpack-dev-server": "^3.11.2",
"worker-loader": "^3.0.0",
"worklet-loader": "^2.0.0",
"yaml": "^2.3.3"
"yaml": "^2.0.1"
},
"@casualbot/jest-sonar-reporter": {
"outputDirectory": "coverage",

View File

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

View File

@@ -77,11 +77,6 @@
"url": "https://play.google.com/store/apps/details?id=im.vector.app",
"id": "im.vector.app"
},
{
"platform": "f-droid",
"url": "https://f-droid.org/repository/browse/?fdid=im.vector.app",
"id": "im.vector.app"
},
{
"platform": "itunes",
"url": "https://apps.apple.com/app/vector/id1083446067"

View File

@@ -1,635 +0,0 @@
#!/usr/bin/env -S npx ts-node
import fs from "node:fs";
import path from "node:path";
import YAML from "yaml";
import parseArgs from "minimist";
import cronstrue from "cronstrue";
import { partition } from "lodash";
const argv = parseArgs<{
debug: boolean;
on: string | string[];
}>(process.argv.slice(2), {
string: ["on"],
boolean: ["debug"],
});
/**
* Generates unique ID strings (incremental base36) representing the given inputs.
*/
class IdGenerator<T> {
private id = 0;
private map = new Map<T, string>();
public get(s: T): string {
if (this.map.has(s)) return this.map.get(s)!;
const id = "ID" + this.id.toString(36).toLowerCase();
this.map.set(s, id);
this.id++;
return id;
}
public debug(): void {
console.log("```");
console.log(this.map);
console.log("```");
}
}
/**
* Type representing a node on a graph with additional metadata
*/
interface Node {
// Workflows are keyed by project/name??id
// Jobs are keyed by id
// Triggers are keyed by id
id: string;
name: string;
shape:
| "round edges"
| "stadium"
| "subroutine"
| "cylinder"
| "circle"
| "flag"
| "rhombus"
| "hexagon"
| "parallelogram"
| "parallelogram_alt"
| "trapezoid"
| "trapezoid_alt"
| "double_circle";
link?: string;
}
/**
* Type representing a directed edge on a graph with an optional label
*/
type Edge<T> = [source: T, destination: T, label?: string];
class Graph<T extends Node> {
public nodes = new Map<string, T>();
public edges: Edge<T>[] = [];
public addNode(node: T): void {
if (!this.nodes.has(node.id)) {
this.nodes.set(node.id, node);
}
}
public removeNode(node: T): Edge<T>[] {
if (!this.nodes.has(node.id)) return [];
this.nodes.delete(node.id);
const [removedEdges, keptEdges] = partition(
this.edges,
([source, destination]) => source === node || destination === node,
);
this.edges = keptEdges;
return removedEdges;
}
public addEdge(source: T, destination: T, label?: string): void {
if (this.edges.some(([_source, _destination]) => _source === source && _destination === destination)) return;
this.edges.push([source, destination, label]);
}
// Removes nodes without any edges
public cull(): void {
const seenNodes = new Set<Node>();
graph.edges.forEach(([source, destination]) => {
seenNodes.add(source);
seenNodes.add(destination);
});
graph.nodes.forEach((node) => {
if (!seenNodes.has(node)) {
graph.nodes.delete(node.id);
}
});
}
public get roots(): Set<T> {
const roots = new Set(this.nodes.values());
this.edges.forEach(([source, destination]) => {
roots.delete(destination);
});
return roots;
}
private componentsRecurse(root: T, visited: Set<T>): T[] {
if (visited.has(root)) return [root];
visited.add(root);
const neighbours = [root];
this.edges.forEach(([source, destination]) => {
if (source === root) {
neighbours.push(...this.componentsRecurse(destination, visited));
} else if (destination === root) {
neighbours.push(...this.componentsRecurse(source, visited));
}
});
return neighbours;
}
public get components(): Graph<T>[] {
const graphs: Graph<T>[] = [];
const visited = new Set<T>();
this.nodes.forEach((node) => {
if (visited.has(node)) return;
const graph = new Graph<T>();
graphs.push(graph);
const nodes = this.componentsRecurse(node, visited);
nodes.forEach((node) => {
graph.addNode(node);
this.edges.forEach((edge) => {
if (edge[0] === node || edge[1] === node) {
graph.addEdge(...edge);
}
});
});
});
return graphs;
}
}
/**
* Type representing a GitHub project
*/
interface Project {
url: string;
name: string;
path: string;
workflows: Map<string, Workflow>;
}
/**
* Type representing a GitHub Actions Workflow
*/
interface Workflow extends Node {
path: string;
project: Project;
jobs: Job[];
on: WorkflowYaml["on"];
}
/**
* Type representing a job within a GitHub Actions Workflow
*/
interface Job extends Node {
jobId: string; // id relative to workflow
needs?: string[];
strategy?: {
matrix: {
[key: string]: string[];
} & {
include?: Record<string, string>[];
exclude?: Record<string, string>[];
};
};
}
/**
* Type representing the YAML structure of a GitHub Actions Workflow file
*/
interface WorkflowYaml {
name: string;
on: {
workflow_run?: {
workflows: string[];
}; // Magic
workflow_call?: {}; // Reusable
workflow_dispatch?: {}; // Manual
pull_request?: {};
merge_group?: {};
push?: {
tags?: string[];
branches?: string[];
};
schedule?: { cron: string }[];
release?: {};
//
label?: {};
issues?: {};
};
jobs: {
[job: string]: {
name?: string;
needs?: string | string[];
strategy?: Job["strategy"];
};
};
}
/**
* Type representing a trigger of a GitHub Actions Workflow
*/
type Trigger = Node;
// TODO workflow_call reusables
/* eslint-disable @typescript-eslint/naming-convention */
const TRIGGERS: {
[key in keyof WorkflowYaml["on"]]: (
data: NonNullable<WorkflowYaml["on"][key]>,
workflow: Workflow,
) => Trigger | Trigger[];
} = {
workflow_dispatch: () => ({
id: "on:workflow_dispatch",
name: "Manual",
shape: "circle",
}),
issues: (_, { project }) => ({ id: `on:issues/${project.name}`, name: `${project.name} Issues`, shape: "circle" }),
label: (_, { project }) => ({ id: "on:label", name: "on: Label", shape: "circle" }),
release: (_, { project }) => ({
id: `on:release/${project.name}`,
name: `${project.name} Release`,
shape: "circle",
}),
push: (data, { project }) => {
const nodes: Trigger[] = [];
data.tags?.forEach((tag) => {
const name = `Push ${project.name}<br>tag ${tag}`;
nodes.push({ id: `on:push/${project.name}/tag/${tag}`, name, shape: "circle" });
});
data.branches?.forEach((branch) => {
const name = `Push ${project.name}<br>${branch}`;
nodes.push({ id: `on:push/${project.name}/branch/${branch}`, name, shape: "circle" });
});
return nodes;
},
schedule: (data) =>
data.map(({ cron }) => ({
id: `on:schedule/${cron}`,
name: cronstrue.toString(cron).replaceAll(", ", "<br>"),
shape: "circle",
})),
pull_request: (_, { project }) => ({
id: `on:pull_request/${project.name}`,
name: `Pull Request<br>${project.name}`,
shape: "circle",
}),
// TODO should we be just dropping these?
workflow_run: (data) => data.workflows.map((parent) => workflows.get(parent)).filter(Boolean) as Workflow[],
};
/* eslint-enable @typescript-eslint/naming-convention */
const triggers = new Map<string, Trigger>(); // keyed by trigger id
const projects = new Map<string, Project>(); // keyed by project name
const workflows = new Map<string, Workflow>(); // keyed by workflow name
function getTriggerNodes<K extends keyof WorkflowYaml["on"]>(key: K, workflow: Workflow): Trigger[] {
if (!TRIGGERS[key]) return [];
if ((typeof argv.on === "string" || Array.isArray(argv.on)) && !toArray(argv.on).includes(key)) {
return [];
}
const data = workflow.on[key]!;
const nodes = toArray(TRIGGERS[key]!(data, workflow));
return nodes.map((node) => {
if (triggers.has(node.id)) return triggers.get(node.id)!;
triggers.set(node.id, node);
return node;
});
}
function readFile(...pathSegments: string[]): string {
return fs.readFileSync(path.join(...pathSegments), { encoding: "utf-8" });
}
function readJson<T extends object>(...pathSegments: string[]): T {
return JSON.parse(readFile(...pathSegments));
}
function readYaml<T extends object>(...pathSegments: string[]): T {
return YAML.parse(readFile(...pathSegments));
}
function toArray<T>(v: T | T[]): T[] {
return Array.isArray(v) ? v : [v];
}
function cartesianProduct<T>(sets: T[][]): T[][] {
return sets.reduce<T[][]>(
(results, ids) =>
results
.map((result) => ids.map((id) => [...result, id]))
.reduce((nested, result) => [...nested, ...result]),
[[]],
);
}
function shallowCompare(obj1: Record<string, any>, obj2: Record<string, any>): boolean {
return (
Object.keys(obj1).length === Object.keys(obj2).length &&
Object.keys(obj1).every((key) => obj1[key] === obj2[key])
);
}
// Data ingest
for (const projectPath of argv._) {
const {
name,
repository: { url },
} = readJson<{ name: string; repository: { url: string } }>(projectPath, "package.json");
const workflowsPath = path.join(projectPath, ".github", "workflows");
const project: Project = {
name,
url,
path: projectPath,
workflows: new Map(),
};
for (const file of fs.readdirSync(workflowsPath).filter((f) => f.endsWith(".yml") || f.endsWith(".yaml"))) {
const data = readYaml<WorkflowYaml>(workflowsPath, file);
const name = data.name ?? file;
const workflow: Workflow = {
id: `${project.name}/${name}`,
name,
shape: "hexagon",
path: path.join(workflowsPath, file),
project,
link: `${project.url}/blob/develop/.github/workflows/${file}`,
on: data.on,
jobs: [],
};
for (const jobId in data.jobs) {
const job = data.jobs[jobId];
workflow.jobs.push({
id: `${workflow.name}/${jobId}`,
jobId,
name: job.name ?? jobId,
strategy: job.strategy,
needs: job.needs ? toArray(job.needs) : undefined,
shape: "subroutine",
link: `${project.url}/blob/develop/.github/workflows/${file}`,
});
}
project.workflows.set(name, workflow);
workflows.set(name, workflow);
}
projects.set(name, project);
}
class MermaidFlowchartPrinter {
private static INDENT = 4;
private currentIndent = 0;
private text = "";
public readonly idGenerator = new IdGenerator();
private print(text: string): void {
this.text += " ".repeat(this.currentIndent) + text + "\n";
}
public finish(): void {
this.indent(-1);
if (this.markdown) this.print("```\n");
console.log(this.text);
}
private indent(delta = 1): void {
this.currentIndent += delta * MermaidFlowchartPrinter.INDENT;
}
public constructor(direction: "TD" | "TB" | "BT" | "RL" | "LR", title?: string, private readonly markdown = false) {
if (this.markdown) {
this.print("```mermaid");
}
// Print heading
if (title) {
this.print("---");
this.print(`title: ${title}`);
this.print("---");
}
this.print(`flowchart ${direction}`);
this.indent();
}
public subgraph(id: string, name: string, fn: () => void): void {
this.print(`subgraph ${this.idGenerator.get(id)}["${name}"]`);
this.indent();
fn();
this.indent(-1);
this.print("end");
}
public node(node: Node): void {
const id = this.idGenerator.get(node.id);
const name = node.name.replaceAll('"', "'");
switch (node.shape) {
case "round edges":
this.print(`${id}("${name}")`);
break;
case "stadium":
this.print(`${id}(["${name}"])`);
break;
case "subroutine":
this.print(`${id}[["${name}"]]`);
break;
case "cylinder":
this.print(`${id}[("${name}")]`);
break;
case "circle":
this.print(`${id}(("${name}"))`);
break;
case "flag":
this.print(`${id}>"${name}"]`);
break;
case "rhombus":
this.print(`${id}{"${name}"}`);
break;
case "hexagon":
this.print(`${id}{{"${name}"}}`);
break;
case "parallelogram":
this.print(`${id}[/"${name}"/]`);
break;
case "parallelogram_alt":
this.print(`${id}[\\"${name}"\\]`);
break;
case "trapezoid":
this.print(`${id}[/"${name}"\\]`);
break;
case "trapezoid_alt":
this.print(`${id}[\\"${name}"/]`);
break;
case "double_circle":
this.print(`${id}((("${name}")))`);
break;
}
if (node.link) {
this.print(`click ${id} href "${node.link}" "Click to open workflow"`);
}
}
public edge(source: Node, destination: Node, text?: string): void {
const sourceId = this.idGenerator.get(source.id);
const destinationId = this.idGenerator.get(destination.id);
if (text) {
this.print(`${sourceId}-- ${text} -->${destinationId}`);
} else {
this.print(`${sourceId} --> ${destinationId}`);
}
}
}
const graph = new Graph<Workflow | Node>();
for (const workflow of workflows.values()) {
if (
(typeof argv.on === "string" || Array.isArray(argv.on)) &&
!toArray(argv.on).some((trigger) => trigger in workflow.on)
) {
continue;
}
graph.addNode(workflow);
Object.keys(workflow.on).forEach((trigger) => {
const nodes = getTriggerNodes(trigger as keyof WorkflowYaml["on"], workflow);
nodes.forEach((node) => {
graph.addNode(node);
graph.addEdge(node, workflow, "project" in node ? "workflow_run" : undefined);
});
});
}
// TODO separate disconnected nodes into their own graph
graph.cull();
// This is an awful hack to make the output graphs much better by allowing the splitting of certain nodes //
const bifurcatedNodes = [triggers.get("on:workflow_dispatch")].filter(Boolean) as Node[];
const removedEdgeMap = new Map<Node, Edge<any>[]>();
for (const node of bifurcatedNodes) {
removedEdgeMap.set(node, graph.removeNode(node));
}
const components = graph.components;
for (const node of bifurcatedNodes) {
const removedEdges = removedEdgeMap.get(node)!;
components.forEach((graph) => {
removedEdges.forEach((edge) => {
if (graph.nodes.has(edge[1].id)) {
graph.addNode(node);
graph.addEdge(...edge);
}
});
});
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////
if (argv.debug) {
debugGraph("global", graph);
}
components.forEach((graph) => {
const title = [...graph.roots]
.map((root) => root.name)
.join(" & ")
.replaceAll("<br>", " ");
const printer = new MermaidFlowchartPrinter("LR", title, true);
graph.nodes.forEach((node) => {
if ("project" in node) {
// TODO unsure about this edge
// if (node.jobs.length === 1) {
// printer.node(node);
// return;
// }
// TODO handle job.if on github.event_name
const subgraph = new Graph<Job>();
for (const job of node.jobs) {
subgraph.addNode(job);
if (job.needs) {
toArray(job.needs).forEach((req) => {
subgraph.addEdge(node.jobs.find((job) => job.jobId === req)!, job, "needs");
});
}
}
printer.subgraph(node.id, node.name, () => {
subgraph.edges.forEach(([source, destination, text]) => {
printer.edge(source, destination, text);
});
subgraph.nodes.forEach((job) => {
if (!job.strategy?.matrix) {
printer.node(job);
return;
}
let variations = cartesianProduct(
Object.keys(job.strategy.matrix)
.filter((key) => key !== "include" && key !== "exclude")
.map((matrixKey) => {
return job.strategy!.matrix[matrixKey].map((value) => ({ [matrixKey]: value }));
}),
)
.map((variation) => Object.assign({}, ...variation))
.filter((variation) => Object.keys(variation).length > 0);
if (job.strategy.matrix.include) {
variations.push(...job.strategy.matrix.include);
}
job.strategy.matrix.exclude?.forEach((exclusion) => {
variations = variations.filter((variation) => {
return !shallowCompare(exclusion, variation);
});
});
// TODO validate edge case
if (variations.length === 0) {
printer.node(job);
return;
}
const jobName = job.name.replace(/\${{.+}}/g, "").replace(/(?:\(\)| )+/g, " ");
printer.subgraph(job.id, jobName, () => {
variations.forEach((variation, i) => {
let variationName = job.name;
if (variationName.includes("${{ matrix.")) {
Object.keys(variation).map((key) => {
variationName = variationName.replace(`\${{ matrix.${key} }}`, variation[key]);
});
} else {
variationName = `${variationName} (${Object.values(variation).join(", ")})`;
}
printer.node({ ...job, id: `${job.id}-variation-${i}`, name: variationName });
});
});
});
});
return;
}
printer.node(node);
});
graph.edges.forEach(([sourceName, destinationName, text]) => {
printer.edge(sourceName, destinationName, text);
});
printer.finish();
if (argv.debug) {
printer.idGenerator.debug();
debugGraph("subgraph", graph);
}
});
function debugGraph(name: string, graph: Graph<any>): void {
console.log("```");
console.log(`## ${name}`);
console.log(new Map(graph.nodes));
console.log(graph.edges.map((edge) => ({ source: edge[0].id, destination: edge[1].id, text: edge[2] })));
console.log("```");
console.log("");
}

View File

@@ -40,7 +40,12 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
<p>
<strong>iOS</strong> (iPhone or iPad)
</p>
<a href={iosCustomUrl} target="_blank" rel="noreferrer noopener" className="mx_ClearDecoration">
<a
href={iosCustomUrl || "https://apps.apple.com/app/vector/id1083446067"}
target="_blank"
rel="noreferrer noopener"
className="mx_ClearDecoration"
>
<img height="48" src="themes/element/img/download/apple.svg" alt="Apple App Store" />
</a>
</>
@@ -58,7 +63,7 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
// undefined or string
android.push(
<a
href={andCustomUrl}
href={andCustomUrl || "https://play.google.com/store/apps/details?id=im.vector.app"}
target="_blank"
rel="noreferrer noopener"
className="mx_ClearDecoration"
@@ -72,7 +77,7 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
// undefined or string
android.push(
<a
href={fdroidCustomUrl}
href={fdroidCustomUrl || "https://f-droid.org/repository/browse/?fdid=im.vector.app"}
target="_blank"
rel="noreferrer noopener"
className="mx_ClearDecoration"

38
src/i18n/strings/bg.json Normal file
View File

@@ -0,0 +1,38 @@
{
"action": {
"create_account": "Създай профил",
"dismiss": "Затвори",
"explore_rooms": "Открий стаи",
"open": "Отвори",
"sign_in": "Вписване"
},
"auth": {
"sso_complete_in_browser_dialog_title": "Отидете в браузъра за да завършите влизането"
},
"download_completed": "Свалянето завърши",
"error": {
"app_launch_unexpected_error": "Неочаквана грешка при подготвянето на приложението. Вижте конзолата за подробности.",
"cannot_load_config": "Неуспешно зареждане на конфигурационния файл: презаредете страницата за да опитате пак.",
"invalid_configuration_no_server": "Невалидна конфигурация: не е указан сървър по подразбиране.",
"invalid_json": "Вашата Element конфигурация съдържа невалиден JSON. Коригирайте проблема и презаредете страницата.",
"invalid_json_detail": "Грешката от парсъра е: %(message)s",
"invalid_json_generic": "Невалиден JSON",
"misconfigured": "Вашият Element не е конфигуриран правилно"
},
"failed_to_start": "Неуспешно стартиране",
"go_to_element_io": "Отиди на element.io",
"incompatible_browser": {
"browser_links": "Инсталирайте <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink> или <safariLink>Safari</safariLink> за най-добра работа.",
"continue_warning": "Разбирам рисковете и желая да продължа",
"feature_warning": "Може да продължите да използвате сегашния си браузър, но някои или всички функции може да се окажат неработещи, или пък външния вид на приложението да изглежда неправилен.",
"features": "%(brand)s използва модерни функции на браузъра, които не се поддържат от Вашия.",
"summary": "Браузърът ви не може да изпълни %(brand)s",
"title": "Неподдържан браузър"
},
"powered_by_matrix": "Базирано на Matrix",
"powered_by_matrix_with_logo": "Децентрализиран, криптиран чат &amp; сътрудничество, захранено от $matrixlogo",
"unknown_device": "Непознато устройство",
"use_brand_on_mobile": "Използвайте %(brand)s на мобилен телефон",
"web_default_device_name": "%(appName)s: %(browserName)s под %(osName)s",
"welcome_to_element": "Добре дошли в Element"
}

View File

@@ -16,7 +16,7 @@
"cannot_load_config": "Nie udało się załadować pliku konfiguracyjnego: odśwież stronę, aby spróbować ponownie.",
"invalid_configuration_mixed_server": "Nieprawidłowa konfiguracja: nie można określić default_hs_url wraz z default_server_name lub default_server_config",
"invalid_configuration_no_server": "Błędna konfiguracja: nie wybrano domyślnego serwera.",
"invalid_json": "Twoja konfiguracja Element zawiera nieprawidłowy JSON. Rozwiąż problem i odśwież stronę.",
"invalid_json": "Twoja konfiguracja Elementa zawiera nieprawidłowy JSON. Rozwiąż problem i odśwież stronę.",
"invalid_json_detail": "Wiadomość od parsera to: %(message)s",
"invalid_json_generic": "Błędny JSON",
"misconfigured": "Twój Element jest nieprawidłowo skonfigurowany"

37
src/i18n/strings/tr.json Normal file
View File

@@ -0,0 +1,37 @@
{
"action": {
"create_account": "Hesap Oluştur",
"dismiss": "Kapat",
"explore_rooms": "Odaları keşfet",
"open": "Aç",
"sign_in": "Giriş Yap"
},
"auth": {
"sso_complete_in_browser_dialog_title": "Oturum açmayı tamamlamak için tarayıcınıza gidin"
},
"download_completed": "İndirme Tamamlandı",
"error": {
"app_launch_unexpected_error": "Uygulama hazırlanırken beklenmeyen bir hata oldu. Detaylar için konsola bakın.",
"cannot_load_config": "Yapılandırma (config) dosyası yüklenemedi: lütfen yeniden denemek için sayfayı yenileyin.",
"invalid_configuration_no_server": "Hatalı ayarlar: varsayılan sunucu belirlenmemiş.",
"invalid_json": "Element uygulamasının ayarları hatalı JSON içeriyor. Lütfen hatayı düzeltip sayfayı yenileyin.",
"invalid_json_detail": "Ayrıştırıcıdan gelen mesaj: %(message)s",
"invalid_json_generic": "Hatalı JSON",
"misconfigured": "Element uygulaması hatalı ayarlanmış"
},
"failed_to_start": "Başlatılamadı",
"go_to_element_io": "element.io adresine git",
"incompatible_browser": {
"browser_links": "Daha iyi bir deneyim için lütfen <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink> ya da <safariLink>Safari</safariLink> tarayıcılarından birini yükleyin.",
"continue_warning": "Riskleri anlıyorum ve devam etmek istiyorum",
"feature_warning": "Şu anda kullanmış olduğunuz tarayıcınızı kullanmaya devam edebilirsiniz ancak uygulamanın sunduğu bazı ya da bütün özellikler çalışmayabilir ve deneyiminizi kötü yönde etkileyebilir.",
"features": "%(brand)s, kullandığınız tarayıcı tarafından desteklenmeyen, gelişmiş tarayıcı özellikleri kullanıyor.",
"summary": "Tarayıcınız %(brand)s uygulamasını çalıştıramıyor",
"title": "Desteklenmeyen tarayıcı"
},
"powered_by_matrix": "Gücünü Matrix'ten alır",
"powered_by_matrix_with_logo": "$matrixLogo tarafından merkeziyetsiz, şifrelenmiş sohbet &amp; iş birliği",
"unknown_device": "Bilinmeyen aygıt",
"use_brand_on_mobile": "Mobilde %(brand)s kullan",
"welcome_to_element": "Element'e hoş geldiniz"
}

View File

@@ -39,7 +39,7 @@ import type EN from "./i18n/strings/en_EN.json";
* which we know will be injected by webpack.
*/
export type TranslationKey = Leaves<typeof EN & typeof ReactEN, "|", string | { other: string }, 4>;
export type TranslationKey = Leaves<typeof EN & typeof ReactEN, "|", string | { other: string }>;
export class UserFriendlyError extends ReactUserFriendlyError {
public constructor(message: TranslationKey, substitutionVariablesAndCause?: IVariables & ErrorOptions) {

View File

@@ -65,7 +65,7 @@ function onTokenLoginCompleted(): void {
window.history.replaceState(null, "", url.href);
}
export async function loadApp(fragParams: {}, matrixChatRef: React.Ref<MatrixChat>): Promise<ReactElement> {
export async function loadApp(fragParams: {}): Promise<ReactElement> {
initRouting();
const platform = PlatformPeg.get();
@@ -117,7 +117,6 @@ export async function loadApp(fragParams: {}, matrixChatRef: React.Ref<MatrixCha
return (
<wrapperOpts.Wrapper>
<MatrixChat
ref={matrixChatRef}
onNewScreen={onNewScreen}
config={config}
realQueryParams={params}

View File

@@ -30,7 +30,6 @@ import SdkConfig from "matrix-react-sdk/src/SdkConfig";
import { setTheme } from "matrix-react-sdk/src/theme";
import { logger } from "matrix-js-sdk/src/logger";
import { ModuleRunner } from "matrix-react-sdk/src/modules/ModuleRunner";
import MatrixChat from "matrix-react-sdk/src/components/structures/MatrixChat";
import ElectronPlatform from "./platform/ElectronPlatform";
import PWAPlatform from "./platform/PWAPlatform";
@@ -148,10 +147,7 @@ export async function loadApp(fragParams: {}): Promise<void> {
/* webpackPreload: true */
"./app"
);
function setWindowMatrixChat(matrixChat: MatrixChat): void {
window.matrixChat = matrixChat;
}
ReactDOM.render(await module.loadApp(fragParams, setWindowMatrixChat), document.getElementById("matrixchat"));
window.matrixChat = ReactDOM.render(await module.loadApp(fragParams), document.getElementById("matrixchat"));
}
export async function showError(title: string, messages?: string[]): Promise<void> {

View File

@@ -47,7 +47,7 @@ describe("Loading server config", function () {
},
},
});
await loadApp({}, null);
await loadApp({});
expect((SdkConfig.get("validated_server_config") || {}).hsUrl).toBe("https://matrix-client.matrix.org");
});
@@ -55,7 +55,7 @@ describe("Loading server config", function () {
SdkConfig.put({
default_server_name: "matrix.org",
});
await loadApp({}, null);
await loadApp({});
expect((SdkConfig.get("validated_server_config") || {}).hsUrl).toBe("https://matrix-client.matrix.org");
});
@@ -72,7 +72,7 @@ describe("Loading server config", function () {
},
},
});
await loadApp({}, null);
await loadApp({});
expect((SdkConfig.get("validated_server_config") || {}).hsUrl).toBe("https://matrix-client.matrix.org");
},
);

View File

@@ -22,7 +22,6 @@ import fetchMock from "fetch-mock-jest";
import { render, RenderResult, screen } from "@testing-library/react";
import { ModuleRunner } from "matrix-react-sdk/src/modules/ModuleRunner";
import { WrapperLifecycle, WrapperOpts } from "@matrix-org/react-sdk-module-api/lib/lifecycles/WrapperLifecycle";
import MatrixChat from "matrix-react-sdk/src/components/structures/MatrixChat";
import WebPlatform from "../../src/vector/platform/WebPlatform";
import { loadApp } from "../../src/vector/app";
@@ -69,8 +68,7 @@ describe("Wrapper", () => {
}
});
const ref = React.createRef<MatrixChat>();
const matrixChatResult: RenderResult = render(await loadApp({}, ref));
const matrixChatResult: RenderResult = render(await loadApp({}));
// at this point, we're trying to do a guest registration;
// we expect a spinner
@@ -85,8 +83,5 @@ describe("Wrapper", () => {
expect(header.nextSibling).toBe(matrixChat);
expect(matrixChat.nextSibling).toBe(footer);
// Should still hold a reference to the MatrixChat component
expect(ref.current).toBeInstanceOf(MatrixChat);
});
});

View File

@@ -25,6 +25,6 @@ fetchMock.config.overwriteRoutes = false;
export function setupLanguageMock() {
reactSetupLanguageMock();
fetchMock.get("end:en_EN.json", _.merge({}, en, reactEn), { overwriteRoutes: true });
fetchMock.get("end:en_EN.json", _.merge(en, reactEn), { overwriteRoutes: true });
}
setupLanguageMock();

View File

@@ -18,13 +18,8 @@ import * as React from "react";
import { render } from "@testing-library/react";
import ErrorView from "../../../../src/async-components/structures/ErrorView";
import { setupLanguageMock } from "../../../setup/setupLanguage";
describe("<ErrorView />", () => {
beforeEach(() => {
setupLanguageMock();
});
it("should match snapshot", () => {
const { asFragment } = render(<ErrorView title="TITLE" messages={["MSG1", "MSG2"]} />);
expect(asFragment()).toMatchSnapshot();

View File

@@ -18,13 +18,8 @@ import * as React from "react";
import { render } from "@testing-library/react";
import VectorAuthFooter from "../../../../../src/components/views/auth/VectorAuthFooter";
import { setupLanguageMock } from "../../../../setup/setupLanguage";
describe("<VectorAuthFooter />", () => {
beforeEach(() => {
setupLanguageMock();
});
it("should match snapshot", () => {
const { asFragment } = render(<VectorAuthFooter />);
expect(asFragment()).toMatchSnapshot();

View File

@@ -18,13 +18,8 @@ import * as React from "react";
import { render } from "@testing-library/react";
import VectorAuthPage from "../../../../../src/components/views/auth/VectorAuthPage";
import { setupLanguageMock } from "../../../../setup/setupLanguage";
describe("<VectorAuthPage />", () => {
beforeEach(() => {
setupLanguageMock();
});
it("should match snapshot", () => {
const { asFragment } = render(<VectorAuthPage />);
expect(asFragment()).toMatchSnapshot();

View File

@@ -26,7 +26,6 @@ import DesktopCapturerSourcePicker from "matrix-react-sdk/src/components/views/e
import { mocked } from "jest-mock";
import ElectronPlatform from "../../../../src/vector/platform/ElectronPlatform";
import { setupLanguageMock } from "../../../setup/setupLanguage";
jest.mock("matrix-react-sdk/src/rageshake/rageshake", () => ({
flush: jest.fn(),
@@ -52,7 +51,6 @@ describe("ElectronPlatform", () => {
window.electron = mockElectron;
jest.clearAllMocks();
Object.defineProperty(window, "navigator", { value: { userAgent: defaultUserAgent }, writable: true });
setupLanguageMock();
});
const getElectronEventHandlerCall = (eventType: string): [type: string, handler: Function] | undefined =>

View File

@@ -19,14 +19,12 @@ import { UpdateCheckStatus } from "matrix-react-sdk/src/BasePlatform";
import { MatrixClientPeg } from "matrix-react-sdk/src/MatrixClientPeg";
import WebPlatform from "../../../../src/vector/platform/WebPlatform";
import { setupLanguageMock } from "../../../setup/setupLanguage";
fetchMock.config.overwriteRoutes = true;
describe("WebPlatform", () => {
beforeEach(() => {
jest.clearAllMocks();
setupLanguageMock();
});
it("returns human readable name", () => {

View File

@@ -12,7 +12,7 @@
"outDir": "./lib",
"declaration": true,
"jsx": "react",
"lib": ["es2021", "dom", "dom.iterable"],
"lib": ["es2020", "dom", "dom.iterable"],
"strict": true
},
"include": [

View File

@@ -143,9 +143,6 @@ module.exports = (env, argv) => {
return {
...development,
bail: true,
node: {
// Mock out the NodeFS module: The opus decoder imports this wrongly.
fs: "empty",
@@ -728,23 +725,14 @@ module.exports = (env, argv) => {
// configuration for the webpack-dev-server
devServer: {
static: {
// Where to serve static assets from
directory: "./webapp",
},
// serve unwebpacked assets from webapp.
contentBase: ["./webapp"],
devMiddleware: {
// Only output errors, warnings, or new compilations.
// This hides the massive list of modules.
stats: "minimal",
},
// Enable Hot Module Replacement without page refresh as a fallback in
// case of build failures
hot: "only",
// Disable host check
allowedHosts: "all",
// Only output errors, warnings, or new compilations.
// This hides the massive list of modules.
stats: "minimal",
hotOnly: true,
inline: true,
},
};
};

3366
yarn.lock

File diff suppressed because it is too large Load Diff