Compare commits

..

25 commits

Author SHA1 Message Date
Travis Ralston
0996956308 Add webpack config to override UI components with customisation 2021-12-16 18:20:31 +01:00
Travis Ralston
86a4d70bcf Webpack config for widget customisation endpoint 2021-12-16 18:20:28 +01:00
Tom
e2a4d7a568 Replacing the education translations with more generic ones. This is _still_ not a sustainable approach. 2021-12-16 18:17:31 +01:00
Tom
12fb012b6f Adding missing translations 2021-12-16 18:16:58 +01:00
Tom
118bd8f4fa Replacing the education translations with more generic ones. This is _still_ not a sustainable approach. 2021-12-16 18:16:54 +01:00
Ben Banfield-Zanin
2f9122d456 s/JS_SDK_REF/JS_SDK_BRANCH/ 2021-12-16 18:13:04 +01:00
Tom
c9ac4d2bf2 Update .gitlab-ci.yml 2021-12-16 18:13:04 +01:00
Arun Neelicattu
5e13a30065 ci: use toml/changes branch for react-sdk testing 2021-12-16 18:13:04 +01:00
Tom
ba11162cee Testing bundling all the translation changes into eleweb. Not a long term solution. 2021-12-16 18:13:01 +01:00
Arun Babu Neelicattu
341d41965f Revert "ci: build container without cache"
This reverts commit 19c33f988d13ec1705187c8c60d848960af7a56c.
2021-12-16 18:12:10 +01:00
Arun Neelicattu
186b4cb3f8 ci: build container without cache 2021-12-16 18:12:10 +01:00
Tom
b338f3f9bb Translate the static jitsi file to German 2021-12-16 18:12:10 +01:00
Travis Ralston
0f31e9f23a Fix build? 2021-12-16 18:12:10 +01:00
Travis Ralston
8944b48e2d Pin js-sdk 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
e69e3ae90f I hate bash 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
72596694af Attempt to make master build latest again 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
3faccf182e Do spaces help? 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
70743d0b9a Use some bashisms? 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
b1a29294e6 Attempt to use nice ref names when possible 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
3547e468c2 Document what the tag will be 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
159adcc87f Remove SDK directories after use 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
40936b3bf6 Blank script tags aren't allowed 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
f41b1c831c Add stub script 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
2bfff82b30 Improve the pipeline to attempt to distinguish branches for react-sdk 2021-12-16 18:12:10 +01:00
Ben Banfield-Zanin
b09fa73160 Gitlab pipeline 2021-12-16 18:10:21 +01:00
329 changed files with 26813 additions and 35588 deletions

View file

@ -21,9 +21,3 @@ insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.{yml,yaml}]
indent_size = 4
[package.json]
indent_size = 2

View file

@ -1,5 +1,2 @@
src/vector/modernizr.js
# Legacy skinning file that some people might still have
src/component-index.js
# Auto-generated file
src/modules.ts

View file

@ -1,72 +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",
},
{
name: "matrix-react-sdk",
message: "Please use matrix-react-sdk/src/index instead",
},
{
name: "matrix-react-sdk/",
message: "Please use matrix-react-sdk/src/index instead",
},
],
patterns: [
{
group: ["matrix-js-sdk/lib", "matrix-js-sdk/lib/", "matrix-js-sdk/lib/**"],
message: "Please use matrix-js-sdk/src/* instead",
},
{
group: ["matrix-react-sdk/lib", "matrix-react-sdk/lib/", "matrix-react-sdk/lib/**"],
message: "Please use matrix-react-sdk/src/* instead",
},
],
},
],
},
},
],
};

View file

@ -1,95 +1,30 @@
module.exports = {
plugins: ["matrix-org"],
extends: ["plugin:matrix-org/babel", "plugin:matrix-org/react"],
parserOptions: {
project: ["./tsconfig.json"],
},
extends: [
"plugin:matrix-org/babel",
"plugin:matrix-org/react",
],
env: {
browser: true,
node: true,
},
rules: {
// Things we do that break the ideal style
quotes: "off",
"quotes": "off",
},
settings: {
react: {
version: "detect",
},
},
overrides: [
{
files: ["src/**/*.{ts,tsx}", "test/**/*.{ts,tsx}", "scripts/*.ts"],
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",
overrides: [{
files: ["src/**/*.{ts,tsx}"],
extends: [
"plugin:matrix-org/typescript",
"plugin:matrix-org/react",
],
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",
},
{
name: "matrix-react-sdk",
message: "Please use matrix-react-sdk/src/index instead",
},
{
name: "matrix-react-sdk/",
message: "Please use matrix-react-sdk/src/index instead",
},
],
patterns: [
{
group: ["matrix-js-sdk/lib", "matrix-js-sdk/lib/", "matrix-js-sdk/lib/**"],
message: "Please use matrix-js-sdk/src/* instead",
},
{
group: ["matrix-react-sdk/lib", "matrix-react-sdk/lib/", "matrix-react-sdk/lib/**"],
message: "Please use matrix-react-sdk/src/* instead",
},
],
},
],
},
// We disable this while we're transitioning
"@typescript-eslint/no-explicit-any": "off",
},
{
files: ["test/**/*.{ts,tsx}"],
rules: {
// We don't need super strict typing in test utilities
"@typescript-eslint/explicit-function-return-type": "off",
"@typescript-eslint/explicit-member-accessibility": "off",
"@typescript-eslint/ban-ts-comment": "off",
"@typescript-eslint/no-floating-promises": "off",
},
},
],
}],
};

View file

@ -1,2 +0,0 @@
# prettier
7921a6cbf86b035d2b0c1daecb4c24beaf5a5abc

6
.github/CODEOWNERS vendored
View file

@ -1,5 +1 @@
* @element-hq/element-web-reviewers
/.github/workflows/** @element-hq/element-web-team
/package.json @element-hq/element-web-team
/yarn.lock @element-hq/element-web-team
/src/i18n/strings
* @vector-im/element-web

View file

@ -2,75 +2,74 @@ name: Bug report for the Element desktop app (not in a browser)
description: File a bug report if you are using the desktop Element application.
labels: [T-Defect]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please report security issues by email to security@matrix.org
- type: textarea
id: reproduction-steps
attributes:
label: Steps to reproduce
description: Please attach screenshots, videos or logs if you can.
placeholder: Tell us what you see!
value: |
1. Where are you starting? What can you see?
2. What do you click?
3. More steps…
validations:
required: true
- type: textarea
id: result
attributes:
label: Outcome
placeholder: Tell us what went wrong
value: |
#### What did you expect?
Please report security issues by email to security@matrix.org
- type: textarea
id: reproduction-steps
attributes:
label: Steps to reproduce
description: Please attach screenshots, videos or logs if you can.
placeholder: Tell us what you see!
value: |
1. Where are you starting? What can you see?
2. What do you click?
3. More steps…
validations:
required: true
- type: textarea
id: result
attributes:
label: Outcome
placeholder: Tell us what went wrong
value: |
#### What did you expect?
#### What happened instead?
validations:
required: true
- type: input
id: os
attributes:
label: Operating system
placeholder: Windows, macOS, Ubuntu, Arch Linux…
validations:
required: false
- type: input
id: version
attributes:
label: Application version
description: You can find the version information in Settings -> Help & About.
placeholder: e.g. Element version 1.7.34, olm version 3.2.3
validations:
required: false
- type: input
id: source
attributes:
label: How did you install the app?
description: Where did you install the app from? Please give a link or a description.
placeholder: e.g. From https://element.io/get-started
validations:
required: false
- type: input
id: homeserver
attributes:
label: Homeserver
description: |
Which server is your account registered on? If it is a local or non-public homeserver, please tell us what is the homeserver implementation (ex: Synapse/Dendrite/etc.) and the version.
placeholder: e.g. matrix.org or Synapse 1.50.0rc1
validations:
required: false
- type: dropdown
id: rageshake
attributes:
label: Will you send logs?
description: |
Did you know that you can send a /rageshake command from your application to submit logs for this issue? Trigger the defect, then type `/rageshake` into the message input area followed by a description of the problem and send the command. You will be able to add a link to this defect report and submit anonymous logs to the developers.
options:
- "Yes"
- "No"
validations:
required: true
#### What happened instead?
validations:
required: true
- type: input
id: os
attributes:
label: Operating system
placeholder: Windows, macOS, Ubuntu, Arch Linux…
validations:
required: false
- type: input
id: version
attributes:
label: Application version
description: You can find the version information in Settings -> Help & About.
placeholder: e.g. Element version 1.7.34, olm version 3.2.3
validations:
required: false
- type: input
id: source
attributes:
label: How did you install the app?
description: Where did you install the app from? Please give a link or a description.
placeholder: e.g. From https://element.io/get-started
validations:
required: false
- type: input
id: homeserver
attributes:
label: Homeserver
description: Which server is your account registered on?
placeholder: e.g. matrix.org
validations:
required: false
- type: dropdown
id: rageshake
attributes:
label: Will you send logs?
description: |
Did you know that you can send a /rageshake command from your application to submit logs for this issue? Trigger the defect, then type `/rageshake` into the message input area followed by a description of the problem and send the command. You will be able to add a link to this defect report and submit anonymous logs to the developers.
options:
- 'Yes'
- 'No'
validations:
required: true

View file

@ -2,83 +2,82 @@ name: Bug report for Element Web (in browser)
description: File a bug report if you are using Element in a web browser like Firefox, Chrome, Edge, and so on.
labels: [T-Defect]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report!
Please report security issues by email to security@matrix.org
- type: textarea
id: reproduction-steps
attributes:
label: Steps to reproduce
description: Please attach screenshots, videos or logs if you can.
placeholder: Tell us what you see!
value: |
1. Where are you starting? What can you see?
2. What do you click?
3. More steps…
validations:
required: true
- type: textarea
id: result
attributes:
label: Outcome
placeholder: Tell us what went wrong
value: |
#### What did you expect?
Please report security issues by email to security@matrix.org
- type: textarea
id: reproduction-steps
attributes:
label: Steps to reproduce
description: Please attach screenshots, videos or logs if you can.
placeholder: Tell us what you see!
value: |
1. Where are you starting? What can you see?
2. What do you click?
3. More steps…
validations:
required: true
- type: textarea
id: result
attributes:
label: Outcome
placeholder: Tell us what went wrong
value: |
#### What did you expect?
#### What happened instead?
validations:
required: true
- type: input
id: os
attributes:
label: Operating system
placeholder: Windows, macOS, Ubuntu, Arch Linux…
validations:
required: false
- type: input
id: browser
attributes:
label: Browser information
description: Which browser are you using? Which version?
placeholder: e.g. Chromium Version 92.0.4515.131
validations:
required: false
- type: input
id: webapp-url
attributes:
label: URL for webapp
description: Which URL are you using to access the webapp? If a private server, tell us what version of Element Web you are using.
placeholder: e.g. develop.element.io, app.element.io
validations:
required: false
- type: input
id: version
attributes:
label: Application version
description: You can find the version information in Settings -> Help & About.
placeholder: e.g. Element version 1.7.34, olm version 3.2.3
validations:
required: false
- type: input
id: homeserver
attributes:
label: Homeserver
description: |
Which server is your account registered on? If it is a local or non-public homeserver, please tell us what is the homeserver implementation (ex: Synapse/Dendrite/etc.) and the version.
placeholder: e.g. matrix.org or Synapse 1.50.0rc1
validations:
required: false
- type: dropdown
id: rageshake
attributes:
label: Will you send logs?
description: |
Did you know that you can send a /rageshake command from the web application to submit logs for this issue? Trigger the defect, then type `/rageshake` into the message input area followed by a description of the problem and send the command. You will be able to add a link to this defect report and submit anonymous logs to the developers.
options:
- "Yes"
- "No"
validations:
required: true
#### What happened instead?
validations:
required: true
- type: input
id: os
attributes:
label: Operating system
placeholder: Windows, macOS, Ubuntu, Arch Linux…
validations:
required: false
- type: input
id: browser
attributes:
label: Browser information
description: Which browser are you using? Which version?
placeholder: e.g. Chromium Version 92.0.4515.131
validations:
required: false
- type: input
id: webapp-url
attributes:
label: URL for webapp
description: Which URL are you using to access the webapp? If a private server, tell us what version of Element Web you are using.
placeholder: e.g. develop.element.io, app.element.io
validations:
required: false
- type: input
id: version
attributes:
label: Application version
description: You can find the version information in Settings -> Help & About.
placeholder: e.g. Element version 1.7.34, olm version 3.2.3
validations:
required: false
- type: input
id: homeserver
attributes:
label: Homeserver
description: Which server is your account registered on?
placeholder: e.g. matrix.org
validations:
required: false
- type: dropdown
id: rageshake
attributes:
label: Will you send logs?
description: |
Did you know that you can send a /rageshake command from the web application to submit logs for this issue? Trigger the defect, then type `/rageshake` into the message input area followed by a description of the problem and send the command. You will be able to add a link to this defect report and submit anonymous logs to the developers.
options:
- 'Yes'
- 'No'
validations:
required: true

View file

@ -1,5 +0,0 @@
blank_issues_enabled: false
contact_links:
- name: Questions & support
url: https://matrix.to/#/#element-web:matrix.org
about: Please ask and answer questions here.

View file

@ -2,35 +2,35 @@ name: Enhancement request
description: Do you have a suggestion or feature request?
labels: [T-Enhancement]
body:
- type: markdown
attributes:
value: |
Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/element-hq/element-meta/discussions/new?category=ideas).
- type: textarea
id: usecase
attributes:
label: Your use case
description: What would you like to be able to do? Please feel welcome to include screenshots or mock ups.
placeholder: Tell us what you would like to do!
value: |
#### What would you like to do?
- type: markdown
attributes:
value: |
Thank you for taking the time to propose a new feature or make a suggestion.
- type: textarea
id: usecase
attributes:
label: Your use case
description: What would you like to be able to do? Please feel welcome to include screenshots or mock ups.
placeholder: Tell us what you would like to do!
value: |
#### What would you like to do?
#### Why would you like to do it?
#### Why would you like to do it?
#### How would you like to achieve it?
validations:
required: true
- type: textarea
id: alternative
attributes:
label: Have you considered any alternatives?
placeholder: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context
placeholder: Is there anything else you'd like to add?
validations:
required: false
#### How would you like to achieve it?
validations:
required: true
- type: textarea
id: alternative
attributes:
label: Have you considered any alternatives?
placeholder: A clear and concise description of any alternative solutions or features you've considered.
validations:
required: false
- type: textarea
id: additional-context
attributes:
label: Additional context
placeholder: Is there anything else you'd like to add?
validations:
required: false

View file

@ -1,8 +1,11 @@
<!-- Thanks for submitting a PR! Please ensure the following requirements are met in order for us to review your PR -->
<!-- Please read https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md before submitting your pull request -->
## Checklist
<!-- Include a Sign-Off as described in https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md#sign-off -->
- [ ] Tests written for new code (and old code if feasible).
- [ ] New or updated `public`/`exported` symbols have accurate [TSDoc](https://tsdoc.org/) documentation.
- [ ] Linter and other CI checks pass.
- [ ] Sign-off given on the changes (see [CONTRIBUTING.md](https://github.com/element-hq/element-web/blob/develop/CONTRIBUTING.md)).
<!-- To specify text for the changelog entry (otherwise the PR title will be used):
Notes:
Changelog entries will also appear in element-desktop. For PRs that *only* affect the desktop version:
Notes: none
element-desktop notes: <notes>
-->

16
.github/cfp_headers vendored
View file

@ -1,16 +0,0 @@
/*
! Access-Control-Allow-Origin
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
Content-Security-Policy: frame-ancestors 'self'
Strict-Transport-Security: max-age=31536000; includeSubDomains; preload
/version
Content-Type: text/plain
/apple-app-site-association
Content-Type: application/json
/.well-known/assetlinks.json
Content-Type: application/json

266
.github/labels.yml vendored
View file

@ -1,266 +0,0 @@
- name: "A-Aliases"
color: "bfd4f2"
- name: "A-Authentication"
color: "bfd4f2"
- name: "A-Autocomplete"
color: "bfd4f2"
- name: "A-Breadcrumbs"
color: "bfd4f2"
- name: "A-Bridge"
color: "bfd4f2"
- name: "A-Broadcast"
description: "Broadcast-style voice messages"
color: "bfd4f2"
- name: "A-Create-Room"
description: "Create room flow, user suggestions, etc."
color: "bfd4f2"
- name: "A-DevTools"
description: "/devtools, show hidden events, etc."
color: "bfd4f2"
- name: "A-Dialogs"
color: "bfd4f2"
- name: "A-Disambiguation"
color: "bfd4f2"
- name: "A-DM-Start"
description: "Creating a DM with another user"
color: "bfd4f2"
- name: "A-E2EE-Dehydration"
color: "8CC59A"
- name: "A-Electron"
color: "bfd4f2"
- name: "A-Element-Call"
description: "Group calls via Element Call"
color: "bfd4f2"
- name: "A-Element-R"
description: "Issues affecting the port of Element's crypto layer to Rust"
color: "bfd4f2"
- name: "A-ELS"
description: "Event List Summary (and Membership ELS, MELS)"
color: "bfd4f2"
- name: "A-Emotes"
color: "bfd4f2"
- name: "A-EMS"
description: "Issues related to EMS"
color: "bfd4f2"
- name: "A-Error-Message"
color: "bfd4f2"
- name: "A-Federation"
color: "bfd4f2"
- name: "A-Feedback-Reporting"
description: "Reporting process for bugs, debug logs (rageshakes), suggestions"
color: "bfd4f2"
- name: "A-File-Download"
color: "bfd4f2"
- name: "A-File-Panel"
color: "bfd4f2"
- name: "A-Identity-Server"
color: "bfd4f2"
- name: "A-Indexing"
description: "Indexing messages via Seshat"
color: "bfd4f2"
- name: "A-IRC-Layout"
color: "bfd4f2"
- name: "A-Jump-To-Date"
description: "Jump to date headers or slash command"
color: "bfd4f2"
- name: "A-Lazy-Loading"
color: "bfd4f2"
- name: "A-Light-Box"
description: "UI when viewing an image"
color: "bfd4f2"
- name: "A-Location-Sharing"
color: "bfd4f2"
- name: "A-Logout"
description: "Logout, sign out, etc."
color: "bfd4f2"
- name: "A-Maths"
description: "Render LaTeX maths in messages"
color: "bfd4f2"
- name: "A-Memory"
description: "Memory leaks, leak hunting tools"
color: "bfd4f2"
- name: "A-Message-Forwarding"
color: "bfd4f2"
- name: "A-Message-Pinning"
color: "bfd4f2"
- name: "A-Message-Previews"
color: "bfd4f2"
- name: "A-Message-Starring"
description: "Saving favourite messages for later"
color: "bfd4f2"
- name: "A-Modules"
description: "Module system related"
color: "bfd4f2"
- name: "A-New-Search-Experience"
description: "The new search dialog available in Labs"
color: "bfd4f2"
- name: "A-Packaging"
description: "Packaging, signing, releasing"
color: "bfd4f2"
- name: "A-Peeking"
color: "bfd4f2"
- name: "A-Picture-in-Picture"
color: "bfd4f2"
- name: "A-Power-Levels"
description: "The permissions that users have in rooms and spaces"
color: "bfd4f2"
- name: "A-Replies"
description: "reply"
color: "bfd4f2"
- name: "A-Session-Mgmt"
description: "Session / device names, management UI, etc."
color: "bfd4f2"
- name: "A-Share"
color: "bfd4f2"
- name: "A-Shortcuts"
description: "Keyboard shortcuts"
color: "bfd4f2"
- name: "A-Sliding-Sync"
description: "Also known as Sync v3 - https://github.com/matrix-org/sliding-sync"
color: "bfd4f2"
- name: "A-Soft-Logout"
description: "https://github.com/element-hq/element-web/issues/10224"
color: "bfd4f2"
- name: "A-Spaces-Settings"
color: "bfd4f2"
- name: "A-SSO"
color: "bfd4f2"
- name: "A-Status-Bar"
description: "Unsent messages warning and 'Connectivity to the server has been lost'"
color: "bfd4f2"
- name: "A-Storage"
description: "Storage layer of the app, including IndexedDB, local storage, etc."
color: "bfd4f2"
- name: "A-Technical-Debt"
color: "bfd4f2"
- name: "A-Testing"
description: "Testing, code coverage, etc."
color: "bfd4f2"
- name: "A-Themes-Custom"
description: "Custom theme variables or support"
color: "bfd4f2"
- name: "A-Themes-Official"
description: "Official themes (light, dark)"
color: "bfd4f2"
- name: "A-Theming"
color: "bfd4f2"
- name: "A-Timeline-Jumpy-Scroll"
description: "Stable timeline dream ✨"
color: "bfd4f2"
- name: "A-Timesheet-1"
description: "Log any time spent on this into the A-Timesheet-1 project"
color: "5319E7"
- name: "A-Toast"
color: "bfd4f2"
- name: "A-Tooltips"
description: "Anything related to tooltips"
color: "bfd4f2"
- name: "A-UI-Customisation"
description: "UIFeatures etc. for customising entire parts of the UI"
color: "bfd4f2"
- name: "A-URL-Previews"
color: "bfd4f2"
- name: "A-User-Menu"
description: "The top left main menu with the user's name and avatar"
color: "bfd4f2"
- name: "A-User-Search"
description: "The start DM or invite to room dialogs (things dealing with `/user_directory/search`)"
color: "bfd4f2"
- name: "A-Video-Rooms"
description: "Persistent group calls"
color: "bfd4f2"
- name: "A-Voice-Messages"
color: "bfd4f2"
- name: "A-Welcome-Page"
color: "bfd4f2"
- name: "backport staging"
description: "Label to automatically backport PR to staging branch"
color: "B60205"
- name: "Dependencies"
description: "Pull requests that update a dependency file"
color: "0366d6"
- name: "Hacktoberfest"
description: "Issues which are suitable for Hacktoberfest PRs: https://hacktoberfest.digitalocean.com/"
color: "ff7518"
- name: "P4"
description: "[OBSOLETE LABEL] Interesting — Not yet scheduled, will accept patches"
color: "d1e5f0"
- name: "spam"
color: "B60205"
- name: "Sponsored"
color: "ffc8f4"
- name: "T-Deprecation"
description: "A pull request that makes something deprecated"
color: "98e6ae"
- name: "T-Other"
description: "Questions, user support, anything else"
color: "98e6ae"
- name: "Team: App"
color: "FFA500"
- name: "X-Blocked"
color: "ff7979"
- name: "X-Cannot-Reproduce"
color: "ff7979"
- name: "X-Command"
description: "Created using the !github command"
color: "ff7979"
- name: "X-Community-Supported-Platform"
description: "This issue occurs in a platform not directly supported by us, but by a community project elsewhere"
color: "ff7979"
- name: "X-Upcoming-Release-Blocker"
description: "This does not affect the current release cycle but will affect the next one"
color: "e99695"
- name: "Z-Actions"
color: "ededed"
- name: "Z-Cache-Confusion"
description: "Related to internal cache (clearing helps / causes the issue)"
color: "ededed"
- name: "Z-Community-PR"
description: "Issue is solved by a community member's PR"
color: "ededed"
- name: "Z-Element-R-Blocker"
description: "A blocker for enabling Element R by default"
color: "ededed"
- name: "Z-Experimental"
color: "ededed"
- name: "Z-Fixed by Element Call"
description: "Issues which can be closed when we move to Element Call"
color: "ededed"
- name: "Z-Fixed-By-OIDC"
description: "Issues which can be closed when we move to OIDC"
color: "ededed"
- name: "Z-Flaky-Test"
description: "A test is raising false alarms"
color: "ededed"
- name: "Z-FOSDEM"
description: "Issues in chat.fosdem.org"
color: "ededed"
- name: "Z-Gitter"
description: "Issues relating to or coming out of the Gitter migration, feature parity, etc"
color: "ededed"
- name: "Z-Legacy-Crypto"
description: "Issues affecting the legacy crypto stack"
color: "EEEEEE"
- name: "Z-Maximised-Widgets"
color: "ededed"
- name: "Z-Papercuts"
description: "Visible. Impactful. Predictable to action."
color: "ededed"
- name: "Z-Power-Users"
color: "ededed"
- name: "Z-Rageshake"
description: "Has attached rageshake (not for log submission process)"
color: "ededed"
- name: "Z-RICE"
color: "ededed"
- name: "Z-Soft-Crash"
description: "React soft crash caught by an error boundary"
color: "ededed"
- name: "Z-Spec-Compliance"
description: "An area where Element doesn't correctly implement the spec"
color: "ededed"
- name: "Z-t3chguy"
color: "ededed"
- name: "Z-Flaky-Test-Disabled"
description: "The flaking test has been disabled"
color: "ededed"

View file

@ -1,3 +0,0 @@
_extends: matrix-org/matrix-react-sdk
version-resolver:
default: patch

View file

@ -1,4 +0,0 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>matrix-org/renovate-config-element-web"]
}

View file

@ -1,30 +0,0 @@
name: Backport
on:
pull_request_target:
types:
- closed
- labeled
branches:
- develop
jobs:
backport:
name: Backport
runs-on: ubuntu-latest
# Only react to merged PRs for security reasons.
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
if: >
github.event.pull_request.merged
&& (
github.event.action == 'closed'
|| (
github.event.action == 'labeled'
&& contains(github.event.label.name, 'backport')
)
)
steps:
- uses: tibdex/backport@9565281eda0731b1d20c4025c43339fb0a23812e # v2
with:
labels_template: "<%= JSON.stringify([...labels, 'X-Release-Blocker']) %>"
# We can't use GITHUB_TOKEN here or CI won't run on the new PR
github_token: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,49 +0,0 @@
name: Build
on:
pull_request: {}
push:
branches: [develop, master]
merge_group:
types: [checks_requested]
# develop pushes and repository_dispatch handled in build_develop.yaml
env:
# These must be set for fetchdep.sh to get the right branch
REPOSITORY: ${{ github.repository }}
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
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
# Workaround for yarn install timeouts, especially on Windows
- run: yarn config set network-timeout 300000
- name: Install Dependencies
run: "./scripts/layered.sh"
- name: Build
run: "yarn build"

View file

@ -1,78 +0,0 @@
name: Build Debian package
on:
release:
types: [published]
concurrency: ${{ github.workflow }}
jobs:
build:
name: Build package
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/element-hq/element-web/releases/download/$VERSION/element-$VERSION.tar.gz"
wget "https://github.com/element-hq/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 debian/tmp/DEBIAN
find debian -maxdepth 1 -type f -exec cp "{}" debian/tmp/DEBIAN/ \;
mkdir -p debian/tmp/usr/share/element-web/ debian/tmp/etc/element-web/
tar -xf "element-$VERSION.tar.gz" -C debian/tmp/usr/share/element-web --strip-components=1 --no-same-owner --no-same-permissions
mv debian/tmp/usr/share/element-web/config.sample.json debian/tmp/etc/element-web/config.json
ln -s /etc/element-web/config.json debian/tmp/usr/share/element-web/config.json
- name: Write changelog
run: |
VERSION=$(cat package.json | jq -r .version)
TIME=$(date -d "$PUBLISHED_AT" -R)
{
echo "element-web ($VERSION) default; urgency=medium"
echo "$BODY" | sed 's/^##/\n */g;s/^\*/ */g' | perl -pe 's/\[.+?]\((.+?)\)/\1/g'
echo ""
echo " -- $ACTOR <support@element.io> $TIME"
} > debian/tmp/DEBIAN/changelog
env:
ACTOR: ${{ github.actor }}
VERSION: ${{ github.event.release.tag_name }}
BODY: ${{ github.event.release.body }}
PUBLISHED_AT: ${{ github.event.release.published_at }}
- name: Build deb package
run: |
VERSION=$(cat package.json | jq -r .version)
dpkg-gencontrol -v"$VERSION" -ldebian/tmp/DEBIAN/changelog
dpkg-deb -Zxz --root-owner-group --build debian/tmp element-web.deb
- uses: actions/upload-artifact@v4
with:
name: element-web.deb
path: element-web.deb
retention-days: 14
- name: Publish to packages.element.io
if: github.event.release.prerelease == false
uses: element-hq/packages.element.io@master
with:
file: element-web.deb
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
bucket-api: ${{ vars.CF_R2_S3_API }}
bucket-key-id: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
bucket-access-key: ${{ secrets.CF_R2_TOKEN }}

View file

@ -1,126 +0,0 @@
# Separate to the main build workflow for access to develop
# environment secrets, largely similar to build.yaml.
name: Build and Deploy develop
on:
push:
branches: [develop]
repository_dispatch:
types: [element-web-notify]
concurrency:
group: ${{ github.repository_owner }}-${{ github.workflow }}-${{ github.ref_name }}
cancel-in-progress: true
jobs:
build:
name: "Build & Deploy develop.element.io"
# Only respect triggers from our develop branch, ignore that of forks
if: github.repository == 'element-hq/element-web'
runs-on: ubuntu-latest
environment: develop
env:
R2_BUCKET: "element-web-develop"
R2_URL: ${{ vars.CF_R2_S3_API }}
R2_PUBLIC_URL: "https://element-web-develop.element.io"
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
- name: Install Dependencies
run: "./scripts/layered.sh"
- name: Build, Package & Upload sourcemaps
run: "./scripts/ci_package.sh"
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_ORG: element
SENTRY_PROJECT: riot-web
# We only deploy the latest bundles to Cloudflare Pages and use _redirects to fallback to R2 for
# older ones. This redirect means that 'self' is insufficient in the CSP,
# and we have to add the R2 URL.
# Once Cloudflare redirects support proxying mode we will be able to ditch this.
# See Proxying in support table at https://developers.cloudflare.com/pages/platform/redirects
CSP_EXTRA_SOURCE: ${{ env.R2_PUBLIC_URL }}
- run: mv dist/element-*.tar.gz dist/develop.tar.gz
- uses: actions/upload-artifact@v4
with:
name: webapp
path: dist/develop.tar.gz
retention-days: 1
- name: Extract webapp
run: |
mkdir _deploy
tar xf dist/develop.tar.gz -C _deploy --strip-components=1
- name: Copy config
run: cp element.io/develop/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
# Redirect requests for the develop tarball and the historical bundles to R2
# We find the latest 100 bundle.css files and add their bundles to the redirects file
# S3 has no sane way to get the age of a directory as they don't really exist
- name: Populate _redirects
run: |
{
echo "/develop.tar.gz $R2_PUBLIC_URL/develop.tar.gz 301"
aws s3api --region auto --endpoint-url $R2_URL list-objects-v2 --bucket $R2_BUCKET \
--query "sort_by(Contents[?ends_with(Key, '/bundle.css')], &LastModified)[-100:].Key" \
--prefix "bundles/" | jq -r '.[]' | grep -oE '[^\"].*\/\s*' | while read -r path ; do
echo "/${path}* $R2_PUBLIC_URL/${path}:splat 301"
done
} | tee _deploy/_redirects
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
# We may be trying to deploy the same webapp bundles again, we need to ensure that the live bundles
# are not present in the _redirects file and instead accessed directly from Cloudflare Pages.
- name: Trim _redirects
working-directory: _deploy
run: |
find bundles -type d -mindepth 1 -maxdepth 1 -exec sed -i "\:{}:d" _redirects \;
- name: Wait for other steps to succeed
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
with:
ref: ${{ github.sha }}
running-workflow-name: "Build & Deploy develop.element.io"
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
check-regexp: ^((?!SonarCloud|SonarQube|issue|board|label|Release|prepare|GitHub Pages).)*$
# We keep the latest develop.tar.gz on R2 instead of relying on the github artifact uploaded earlier
# as the expires after 24h and requires auth to download.
# Element Desktop's fetch script uses this tarball to fetch latest develop to build Nightlies.
- name: Deploy to R2
run: |
aws s3 cp dist/develop.tar.gz s3://$R2_BUCKET/develop.tar.gz --endpoint-url $R2_URL --region=auto
aws s3 cp _deploy/ s3://$R2_BUCKET/ --recursive --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 }}
- name: Deploy to Cloudflare Pages
id: cfp
uses: cloudflare/pages-action@f0a1cd58cd66095dee69bfa18fa5efd1dde93bca # v1
with:
apiToken: ${{ secrets.CF_PAGES_TOKEN }}
accountId: ${{ secrets.CF_PAGES_ACCOUNT_ID }}
projectName: element-web-develop
directory: _deploy
gitHubToken: ${{ secrets.GITHUB_TOKEN }}
- run: |
echo "Deployed to ${{ steps.cfp.outputs.url }}" >> $GITHUB_STEP_SUMMARY

View file

@ -1,94 +0,0 @@
name: Dockerhub
on:
workflow_dispatch: {}
push:
tags: [v*]
schedule:
# This job can take a while, and we have usage limits, so just publish develop only twice a day
- cron: "0 7/12 * * *"
concurrency: ${{ github.workflow }}-${{ github.ref_name }}
permissions:
id-token: write # needed for signing the images with GitHub OIDC Token
jobs:
buildx:
name: Docker Buildx
runs-on: ubuntu-latest
environment: dockerhub
strategy:
fail-fast: false
matrix:
include:
- variant: vanilla
# Variant we ship to aid ESS in providing a build on the OpenCoDE platform including specific modules
- variant: opendesk
flavor: suffix=-opendesk,onlatest=true
prepare: mv variants/openDesk/* .
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # needed for docker-package to be able to calculate the version
- name: Install Cosign
uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3
- name: Prepare
if: matrix.prepare
run: ${{ matrix.prepare }}
- name: Set up QEMU
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@aa33708b10e362ff993539393ff100fa93ed6a27 # v3
with:
install: true
- name: Login to Docker Hub
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Docker meta
id: meta
uses: docker/metadata-action@8e5442c4ef9f78752691e2d8f8d19755c6f78e81 # v5
with:
images: |
vectorim/element-web
tags: |
type=ref,event=branch
type=ref,event=tag
flavor: |
latest=${{ contains(github.ref_name, '-rc.') && 'false' || 'auto' }}
${{ matrix.flavor }}
- name: Build and push
id: build-and-push
uses: docker/build-push-action@5176d81f87c23d6fc96624dfdbcd9f3830bbe445 # v6
with:
context: .
push: true
platforms: linux/amd64,linux/arm64
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Sign the images with GitHub OIDC Token
env:
DIGEST: ${{ steps.build-and-push.outputs.digest }}
TAGS: ${{ steps.meta.outputs.tags }}
run: |
images=""
for tag in ${TAGS}; do
images+="${tag}@${DIGEST} "
done
cosign sign --yes ${images}
- name: Update repo description
if: matrix.variant == 'vanilla'
uses: peter-evans/dockerhub-description@e98e4d1628a5f3be2be7c231e50981aee98723ae # v4
continue-on-error: true
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: vectorim/element-web

View file

@ -1,116 +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: element-hq/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@v4
with:
cache: "yarn"
cache-dependency-path: element-web/yarn.lock
node-version: "lts/*"
- 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@v2
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@v3
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@v4

View file

@ -1,29 +0,0 @@
# Triggers after the "Downstream artifacts" build has finished, to run the
# matrix-react-sdk playwright tests (with access to repo secrets)
name: matrix-react-sdk End to End Tests
on:
merge_group:
types: [checks_requested]
pull_request: {}
push:
branches: [develop, master]
concurrency:
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch || github.run_id }}
cancel-in-progress: ${{ github.event.workflow_run.event == 'pull_request' }}
jobs:
playwright:
name: Playwright
uses: matrix-org/matrix-react-sdk/.github/workflows/end-to-end-tests.yaml@develop
permissions:
actions: read
issues: read
pull-requests: read
with:
element-web-sha: ${{ github.sha }}
react-sdk-repository: matrix-org/matrix-react-sdk
# We only want to run the playwright tests on merge queue to prevent regressions
# from creeping in. They take a long time to run and consume multiple concurrent runners.
skip: ${{ github.event_name != 'merge_group' }}

View file

@ -1,156 +0,0 @@
# For duplicate issues, ensure the close type is right (not planned), update it if not
# For all closed (completed) issues, cascade the closure onto any referenced rageshakes
# For all closed (not planned) issues, comment on rageshakes to move them into the canonical issue if one exists
on:
issues:
types: [closed]
jobs:
tidy:
name: Tidy closed issues
runs-on: ubuntu-latest
steps:
- uses: actions/github-script@v7
id: main
with:
# PAT needed as the GITHUB_TOKEN won't be able to see cross-references from other orgs (matrix-org)
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
script: |
const variables = {
owner: context.repo.owner,
name: context.repo.repo,
number: context.issue.number,
};
const query = `query($owner:String!, $name:String!, $number:Int!) {
repository(owner: $owner, name: $name) {
issue(number: $number) {
stateReason,
timelineItems(first: 100, itemTypes: [MARKED_AS_DUPLICATE_EVENT, UNMARKED_AS_DUPLICATE_EVENT, CROSS_REFERENCED_EVENT]) {
edges {
node {
__typename
... on MarkedAsDuplicateEvent {
canonical {
... on Issue {
repository {
nameWithOwner
}
number
}
... on PullRequest {
repository {
nameWithOwner
}
number
}
}
}
... on UnmarkedAsDuplicateEvent {
canonical {
... on Issue {
repository {
nameWithOwner
}
number
}
... on PullRequest {
repository {
nameWithOwner
}
number
}
}
}
... on CrossReferencedEvent {
source {
... on Issue {
repository {
nameWithOwner
}
number
}
... on PullRequest {
repository {
nameWithOwner
}
number
}
}
}
}
}
}
}
}
}`;
const result = await github.graphql(query, variables);
const { stateReason, timelineItems: { edges } } = result.repository.issue;
const RAGESHAKE_OWNER = "matrix-org";
const RAGESHAKE_REPO = "element-web-rageshakes";
const rageshakes = new Set();
const duplicateOf = new Set();
console.log("Edges: ", JSON.stringify(edges));
for (const { node } of edges) {
switch(node.__typename) {
case "MarkedAsDuplicateEvent":
duplicateOf.add(node.canonical.repository.nameWithOwner + "#" + node.canonical.number);
break;
case "UnmarkedAsDuplicateEvent":
duplicateOf.remove(node.canonical.repository.nameWithOwner + "#" + node.canonical.number);
break;
case "CrossReferencedEvent":
if (node.source.repository.nameWithOwner === (RAGESHAKE_OWNER + "/" + RAGESHAKE_REPO)) {
rageshakes.add(node.source.number);
}
break;
}
}
console.log("Duplicate of: ", duplicateOf);
console.log("Found rageshakes: ", rageshakes);
if (duplicateOf.size) {
const body = Array.from(duplicateOf).join("\n");
// Comment on all rageshakes to create relationship to the issue this was closed as duplicate of
for (const rageshake of rageshakes) {
github.rest.issues.createComment({
owner: RAGESHAKE_OWNER,
repo: RAGESHAKE_REPO,
issue_number: rageshake,
body,
});
}
// Duplicate was closed with wrong reason, fix it
if (stateReason === "COMPLETED") {
core.setOutput("closeAsNotPlanned", "true");
}
} else {
// This issue was closed, close all related rageshakes
for (const rageshake of rageshakes) {
github.rest.issues.update({
owner: RAGESHAKE_OWNER,
repo: RAGESHAKE_REPO,
issue_number: rageshake,
state: "closed",
});
}
}
- uses: actions/github-script@v7
name: Close duplicate as Not Planned
if: steps.main.outputs.closeAsNotPlanned
with:
# We do this step separately, and with the default token so as to not re-trigger this workflow when re-closing
script: |
await github.graphql(`mutation($id:ID!) {
closeIssue(input: { issueId:$id, stateReason:NOT_PLANNED }) {
clientMutationId
}
}`, {
id: context.payload.issue.node_id,
});

View file

@ -1,10 +0,0 @@
name: Localazy Download
on:
workflow_dispatch: {}
schedule:
- cron: "0 6 * * 1,3,5" # Every Monday, Wednesday and Friday at 6am UTC
jobs:
download:
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_download.yaml@main
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,11 +0,0 @@
name: Localazy Upload
on:
push:
branches: [develop]
paths:
- "src/i18n/strings/en_EN.json"
jobs:
upload:
uses: matrix-org/matrix-web-i18n/.github/workflows/localazy_upload.yaml@main
secrets:
LOCALAZY_WRITE_KEY: ${{ secrets.LOCALAZY_WRITE_KEY }}

View file

@ -1,90 +0,0 @@
name: Pending reviews automation
on:
# We run it on a schedule instead of on pull_request_* events to not create confusing messaging in the PR
schedule:
- cron: "*/10 * * * *"
concurrency: ${{ github.workflow }}
jobs:
bot:
name: Pending reviews bot
runs-on: ubuntu-latest
environment: Matrix
env:
URL: "https://github.com/pulls?q=is%3Apr+is%3Aopen+repo%3Amatrix-org%2Fmatrix-js-sdk+repo%3Amatrix-org%2Fmatrix-react-sdk+repo%3Aelement-hq%2Felement-web+repo%3Aelement-hq%2Felement-desktop+review-requested%3A%40me+sort%3Aupdated-desc+"
RELEASE_BLOCKERS_URL: "https://github.com/pulls?q=is%3Aopen+repo%3Amatrix-org%2Fmatrix-js-sdk+repo%3Amatrix-org%2Fmatrix-react-sdk+repo%3Aelement-hq%2Felement-web+repo%3Aelement-hq%2Felement-desktop+sort%3Aupdated-desc+label%3AX-Release-Blocker+"
steps:
- uses: actions/github-script@v7
env:
HS_URL: ${{ secrets.BETABOT_HS_URL }}
ROOM_ID: ${{ secrets.ROOM_ID }}
TOKEN: ${{ secrets.BETABOT_ACCESS_TOKEN }}
with:
# PAT needed as the GITHUB_TOKEN won't be able to see cross-references from other orgs (matrix-org)
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
script: |
const { HS_URL, ROOM_ID, TOKEN, URL, RELEASE_BLOCKERS_URL } = process.env;
async function updateCounter(counter, link, severity, title, value, clearOnZero) {
const apiUrl = `${HS_URL}/_matrix/client/v3/rooms/${ROOM_ID}/state/re.jki.counter/${counter}`;
const headers = {
"Content-Type": "application/json",
"Authorization": `Bearer ${TOKEN}`,
};
const res = await fetch(apiUrl, {
method: "GET",
headers,
});
const data = await res.json();
if (data.value === issueCount) {
console.log("Pending review count already correct");
return;
}
let body = {};
if (issueCount || !clearOnZero) {
body = JSON.stringify({
link,
severity,
title,
value,
});
}
await fetch(apiUrl, {
method: "PUT",
body,
headers,
});
}
const repos = [
"element-hq/element-desktop",
"element-hq/element-web",
"matrix-org/matrix-react-sdk",
"matrix-org/matrix-js-sdk",
];
const teams = [
"matrix-org/element-web-team",
"matrix-org/element-web-reviewers",
"element-hq/element-web-team",
"element-hq/element-web-reviewers",
];
let issueCount = 0;
for (const team of teams) {
const org = team.split("/", 2)[0];
const reposInOrg = repos.filter(repo => repo.startsWith(org + "/"));
const { data } = await github.rest.search.issuesAndPullRequests({
q: `is:pr is:open review:required ${reposInOrg.map(r => `repo:${r}`).join(" ")} team-review-requested:${team}`,
});
issueCount += data.total_count;
}
await updateCounter("gh_reviews", URL, "warning", "Pending reviews", issueCount);
const { data } = await github.rest.search.issuesAndPullRequests({
q: `is:open ${repos.map(repo => `repo:${repo}`).join(" ")} label:X-Release-Blocker`,
});
const blockerCount = data.total_count;
await updateCounter("release_blockers", RELEASE_BLOCKERS_URL, "alert", "Release Blockers", blockerCount, true);

View file

@ -0,0 +1,12 @@
name: Preview Changelog
on:
pull_request_target:
types: [ opened, edited, labeled ]
jobs:
changelog:
runs-on: ubuntu-latest
steps:
- name: Preview Changelog
uses: matrix-org/allchange@main
with:
ghToken: ${{ secrets.GITHUB_TOKEN }}

View file

@ -1,11 +0,0 @@
name: Pull Request
on:
pull_request_target:
types: [opened, edited, labeled, unlabeled, synchronize]
merge_group:
types: [checks_requested]
jobs:
action:
uses: matrix-org/matrix-js-sdk/.github/workflows/pull_request.yaml@develop
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,11 +0,0 @@
name: Release Drafter
on:
push:
branches: [staging]
workflow_dispatch: {}
concurrency: ${{ github.workflow }}
jobs:
draft:
uses: matrix-org/matrix-js-sdk/.github/workflows/release-drafter-workflow.yml@develop
with:
include-changes: matrix-react-sdk

View file

@ -1,15 +0,0 @@
# Gitflow merge-back master->develop
name: Merge master -> develop
on:
push:
branches: [master]
concurrency: ${{ github.repository }}-${{ github.workflow }}
jobs:
merge:
uses: matrix-org/matrix-js-sdk/.github/workflows/release-gitflow.yml@develop
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
with:
dependencies: |
matrix-react-sdk
matrix-js-sdk

View file

@ -1,62 +0,0 @@
name: Release Process
on:
workflow_dispatch:
inputs:
mode:
description: What type of release
required: true
default: rc
type: choice
options:
- rc
- final
concurrency: ${{ github.workflow }}
jobs:
release:
uses: matrix-org/matrix-js-sdk/.github/workflows/release-make.yml@develop
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}
GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
with:
final: ${{ inputs.mode == 'final' }}
gpg-fingerprint: ${{ vars.GPG_FINGERPRINT }}
asset-path: dist/*.tar.gz
expected-asset-count: 3
notify-downstream:
name: Trigger release drafter downstream
needs: release
runs-on: ubuntu-latest
steps:
- name: Notify element-desktop repo that element-web release has completed to re-trigger release-drafter
uses: benc-uk/workflow-dispatch@25b02cc069be46d637e8fe2f1e8484008e9e9609 # v1
with:
workflow: release-drafter.yml
repo: element-hq/element-desktop
ref: staging
# Required when using the `repo` option. Either a PAT or a token generated from the GitHub app or CLI
token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
check:
name: Post release checks
needs: release
runs-on: ubuntu-latest
steps:
- name: Wait for dockerhub
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
with:
ref: master
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
check-name: "Docker Buildx (vanilla)"
allowed-conclusions: success
- name: Wait for debian package
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
with:
ref: master
repo-token: ${{ secrets.GITHUB_TOKEN }}
wait-interval: 10
check-name: Build package
allowed-conclusions: success

View file

@ -1,124 +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
env:
# The order is specified bottom-up to avoid any races for allchange
REPOS: matrix-js-sdk matrix-react-sdk element-web element-desktop
steps:
- name: Checkout Element Desktop
uses: actions/checkout@v4
if: inputs.element-desktop
with:
repository: element-hq/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: element-hq/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: Merge develop
run: |
git config --global user.email "releases@riot.im"
git config --global user.name "RiotRobot"
for REPO in $REPOS; do [ -d "$REPO" ] && git -C "$REPO" merge origin/develop; done
- name: Push staging
run: for REPO in $REPOS; do [ -d "$REPO" ] && git -C "$REPO" push origin staging; done
- name: Wait for matrix-js-sdk draft
if: inputs.matrix-js-sdk
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
with:
ref: staging
repo: matrix-org/matrix-js-sdk
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
wait-interval: 10
check-name: draft
allowed-conclusions: success
- name: Wait for matrix-react-sdk draft
if: inputs.matrix-react-sdk
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
with:
ref: staging
repo: matrix-org/matrix-react-sdk
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
wait-interval: 10
check-name: draft
allowed-conclusions: success
- name: Wait for element-web draft
if: inputs.element-web
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
with:
ref: staging
repo: element-hq/element-web
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
wait-interval: 10
check-name: draft
allowed-conclusions: success
- name: Wait for element-desktop draft
if: inputs.element-desktop
uses: t3chguy/wait-on-check-action@18541021811b56544d90e0f073401c2b99e249d6 # fork
with:
ref: staging
repo: element-hq/element-desktop
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
wait-interval: 10
check-name: draft
allowed-conclusions: success

View file

@ -0,0 +1,26 @@
name: Upload Sentry Sourcemaps
on:
push:
branches:
- develop
repository_dispatch:
types: [ element-web-notify ]
jobs:
upload-sentry-sourcemaps:
runs-on: ubuntu-latest
environment: develop
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '14'
cache: 'yarn'
- run: ./scripts/fetch-develop.deps.sh --depth 1
- run: yarn install
- run: ./scripts/ci_package.sh
env:
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
SENTRY_URL: ${{ secrets.SENTRY_URL }}
SENTRY_ORG: sentry
SENTRY_PROJECT: riot-web

View file

@ -1,16 +0,0 @@
name: SonarQube
on:
workflow_run:
workflows: ["Tests"]
types:
- completed
concurrency:
group: ${{ github.workflow }}-${{ github.event.workflow_run.head_branch }}
cancel-in-progress: true
jobs:
sonarqube:
name: 🩻 SonarQube
uses: matrix-org/matrix-js-sdk/.github/workflows/sonarcloud.yml@develop
secrets:
SONAR_TOKEN: ${{ secrets.SONAR_TOKEN }}
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,107 +0,0 @@
name: Static Analysis
on:
pull_request: {}
push:
branches: [develop, master]
merge_group:
types: [checks_requested]
repository_dispatch:
types: [element-web-notify]
env:
# These must be set for fetchdep.sh to get the right branch
REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
jobs:
ts_lint:
name: "Typescript Syntax Check"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
- name: Install Dependencies
run: "./scripts/layered.sh"
- name: Typecheck
run: "yarn run lint:types"
i18n_lint:
name: "i18n Check"
uses: matrix-org/matrix-web-i18n/.github/workflows/i18n_check.yml@main
with:
hardcoded-words: "Element"
js_lint:
name: "ESLint"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Run Linter
run: "yarn run lint:js"
style_lint:
name: "Style Lint"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
# Needs branch matching as it inherits .stylelintrc.js from matrix-react-sdk
- name: Install Dependencies
run: "./scripts/layered.sh"
- name: Run Linter
run: "yarn run lint:style"
workflow_lint:
name: "Workflow Lint"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Run Linter
run: "yarn lint:workflows"
analyse_dead_code:
name: "Analyse Dead Code"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
- name: Install Deps
run: "scripts/layered.sh"
- name: Dead Code Analysis
run: "yarn run analyse:unused-exports"

View file

@ -1,21 +0,0 @@
name: Sync labels
on:
workflow_dispatch: {}
schedule:
- cron: "0 1 * * *" # 1am every day
push:
branches:
- develop
paths:
- .github/labels.yml
jobs:
sync-labels:
uses: element-hq/element-meta/.github/workflows/sync-labels.yml@develop
with:
LABELS: |
element-hq/element-meta
.github/labels.yml
DELETE: true
WET: true
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,60 +0,0 @@
name: Tests
on:
pull_request: {}
push:
branches: [develop, master]
merge_group:
types: [checks_requested]
repository_dispatch:
types: [element-web-notify]
env:
# These must be set for fetchdep.sh to get the right branch
REPOSITORY: ${{ github.repository }}
PR_NUMBER: ${{ github.event.pull_request.number }}
jobs:
jest:
name: Jest
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Yarn cache
uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
- name: Install Dependencies
run: "./scripts/layered.sh"
- name: Get number of CPU cores
id: cpu-cores
uses: SimenB/github-actions-cpu-cores@97ba232459a8e02ff6121db9362b09661c875ab8 # v2
- name: Run tests with coverage
run: "yarn coverage --ci --max-workers ${{ steps.cpu-cores.outputs.count }}"
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: coverage
path: |
coverage
!coverage/lcov-report
skip_sonar:
name: Skip SonarCloud in merge queue
if: github.event_name == 'merge_group'
runs-on: ubuntu-latest
needs: jest
steps:
- name: Skip SonarCloud
uses: Sibz/github-status-action@faaa4d96fecf273bd762985e0e7f9f933c774918 # v1
with:
authToken: ${{ secrets.GITHUB_TOKEN }}
state: success
description: SonarCloud skipped
context: SonarCloud Code Analysis
sha: ${{ github.sha }}
target_url: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}

View file

@ -1,18 +0,0 @@
name: Move issued assigned to specific team members to their boards
on:
issues:
types: [assigned]
jobs:
web-app-team:
runs-on: ubuntu-latest
if: |
contains(github.event.issue.assignees.*.login, 't3chguy') ||
contains(github.event.issue.assignees.*.login, 'andybalaam') ||
contains(github.event.issue.assignees.*.login, 'MidhunSureshR')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/element-hq/projects/67
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,14 +1,15 @@
name: Move new issues into Issue triage board
on:
issues:
types: [opened]
issues:
types: [opened]
jobs:
automate-project-columns:
runs-on: ubuntu-latest
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/element-hq/projects/120
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
automate-project-columns:
runs-on: ubuntu-latest
steps:
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
with:
project: Issue triage
column: Incoming
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,200 +0,0 @@
name: Move labelled issues to correct projects
on:
issues:
types: [labeled]
workflow_call:
secrets:
ELEMENT_BOT_TOKEN:
required: true
jobs:
apply_Z-Labs_label:
name: Add Z-Labs label for features behind labs flags
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Maths') ||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
contains(github.event.issue.labels.*.name, 'A-Jump-To-Date ') ||
contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
contains(github.event.issue.labels.*.name, 'A-Tags') ||
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')
steps:
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['Z-Labs']
})
apply_Help-Wanted_label:
name: Add "Help Wanted" label to all "good first issue" and Hacktoberfest
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'good first issue') ||
contains(github.event.issue.labels.*.name, 'Hacktoberfest')
steps:
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['Help Wanted']
})
move_needs_info_issues:
name: X-Needs-Info issues to Need info column on triage board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Info')
steps:
- id: add_to_project
uses: actions/add-to-project@v1.0.2
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: set_fields
uses: titoportas/update-project-fields@421a54430b3cdc9eefd8f14f9ce0142ab7678751 # 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: Status
field-values: "Needs info"
env:
PROJECT_URL: https://github.com/orgs/element-hq/projects/120
move_flakey_test_issues:
name: Z-Flaky-Test issues to Sized for maintainer column on triage board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'Z-Flaky-Test')
steps:
- id: add_to_project
uses: actions/add-to-project@v1.0.2
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: set_fields
uses: titoportas/update-project-fields@421a54430b3cdc9eefd8f14f9ce0142ab7678751 # 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: Status
field-values: "Sized for maintainer"
env:
PROJECT_URL: https://github.com/orgs/element-hq/projects/120
add_priority_design_issues_to_project:
name: P1 X-Needs-Design to Design project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Design') &&
(contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
contains(github.event.issue.labels.*.name, 'S-Major') &&
contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'A11y'))
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/element-hq/projects/18
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
add_product_issues:
name: X-Needs-Product to product project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/element-hq/projects/28
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
Search_issues_to_board:
name: Search issues to project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-New-Search-Experience')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/element-hq/projects/48
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
voip:
name: Add labelled issues to VoIP project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'Team: VoIP')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/element-hq/projects/41
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
verticals_feature:
name: Add labelled issues to Verticals Feature project
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'Team: Verticals Feature')
steps:
- uses: actions/add-to-project@main
with:
project-url: https://github.com/orgs/element-hq/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/element-hq/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@v1.0.2
with:
project-url: ${{ env.PROJECT_URL }}
github-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: set_fields
uses: titoportas/update-project-fields@421a54430b3cdc9eefd8f14f9ce0142ab7678751 # 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/element-hq/projects/76

View file

@ -0,0 +1,133 @@
name: Move labelled issues to correct boards and columns
on:
issues:
types: [labeled]
jobs:
move_needs_info_issues:
name: Move X-Needs-Info issues to Need info on triage board
runs-on: ubuntu-latest
steps:
- uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338
with:
action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
project-url: "https://github.com/vector-im/element-web/projects/27"
column-name: "Need info"
label-name: "X-Needs-Info"
add_priority_design_issues_to_project:
name: Move priority X-Needs-Design issues to Design project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Design') &&
contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
contains(github.event.issue.labels.*.name, 'S-Major') &&
contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'A11y') &&
contains(github.event.issue.labels.*.name, 'O-Frequent')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:String!,$contentid:String!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
projectNextItem {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PN_kwDOAM0swc0sUA"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_spaces_issues:
name: Move Spaces issues to Delight project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Spaces') ||
contains(github.event.issue.labels.*.name, 'A-Space-Settings') ||
contains(github.event.issue.labels.*.name, 'A-Subspaces')
steps:
- uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338
with:
action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
project-url: "https://github.com/orgs/vector-im/projects/6"
column-name: "📥 Inbox"
label-name: "A-Spaces"
- uses: octokit/graphql-action@v2.x
id: add_to_delight2
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:String!,$contentid:String!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
projectNextItem {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PN_kwDOAM0swc1HvQ"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_voice-message_issues:
name: Move A-Voice Messages to Voice message board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Voice Messages')
steps:
- uses: konradpabjan/move-labeled-or-milestoned-issue@219d384e03fa4b6460cd24f9f37d19eb033a4338
with:
action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
project-url: "https://github.com/vector-im/element-web/projects/28"
column-name: "📥 Inbox"
label-name: "A-Voice Messages"
- uses: octokit/graphql-action@v2.x
id: add_to_voice
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:String!,$contentid:String!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
projectNextItem {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PN_kwDOAM0swc2KCw"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_threads_issues:
name: Move A-Threads to Thread board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Threads')
steps:
- uses: octokit/graphql-action@v2.x
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:String!,$contentid:String!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
projectNextItem {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PN_kwDOAM0swc0rRA"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -1,139 +1,61 @@
name: Move pull requests asking for review to the relevant project
on:
pull_request_target:
types: [review_requested]
pull_request:
types: [review_requested]
jobs:
add_design_pr_to_project:
name: Move PRs asking for design review to the design board
runs-on: ubuntu-latest
steps:
- uses: octokit/graphql-action@v2.x
id: find_team_members
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
query find_team_members($team: String!) {
organization(login: "element-hq") {
team(slug: $team) {
members {
nodes {
login
}
}
}
}
}
team: ${{ env.TEAM }}
env:
TEAM: "design"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: any_matching_reviewers
run: |
# Fetch requested reviewers, and people who are on the team
echo '${{ tojson(fromjson(steps.find_team_members.outputs.data).organization.team.members.nodes[*].login) }}' | tee /tmp/team_members.json
echo '${{ tojson(github.event.pull_request.requested_reviewers[*].login) }}' | tee /tmp/reviewers.json
jq --raw-output .[] < /tmp/team_members.json | sort | tee /tmp/team_members.txt
jq --raw-output .[] < /tmp/reviewers.json | sort | tee /tmp/reviewers.txt
# Fetch requested team reviewers, and the name of the team
echo '${{ tojson(github.event.pull_request.requested_teams[*].slug) }}' | tee /tmp/team_reviewers.json
jq --raw-output .[] < /tmp/team_reviewers.json | sort | tee /tmp/team_reviewers.txt
echo '${{ env.TEAM }}' | tee /tmp/team.txt
# If either a reviewer matches a team member, or a team matches our team, say "true"
if [ $(join /tmp/team_members.txt /tmp/reviewers.txt | wc -l) != 0 ]; then
echo "match=true" >> $GITHUB_OUTPUT
elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then
echo "match=true" >> $GITHUB_OUTPUT
else
echo "match=false" >> $GITHUB_OUTPUT
fi
env:
TEAM: "design"
- uses: octokit/graphql-action@v2.x
id: add_to_project
if: steps.any_matching_reviewers.outputs.match == 'true'
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!, $contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.pull_request.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc0sUA"
TEAM: "design"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
add_product_pr_to_project:
name: Move PRs asking for design review to the design board
runs-on: ubuntu-latest
steps:
- uses: octokit/graphql-action@v2.x
id: find_team_members
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
query find_team_members($team: String!) {
organization(login: "element-hq") {
team(slug: $team) {
members {
nodes {
login
}
}
}
}
}
team: ${{ env.TEAM }}
env:
TEAM: "product"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: any_matching_reviewers
run: |
# Fetch requested reviewers, and people who are on the team
echo '${{ tojson(fromjson(steps.find_team_members.outputs.data).organization.team.members.nodes[*].login) }}' | tee /tmp/team_members.json
echo '${{ tojson(github.event.pull_request.requested_reviewers[*].login) }}' | tee /tmp/reviewers.json
jq --raw-output .[] < /tmp/team_members.json | sort | tee /tmp/team_members.txt
jq --raw-output .[] < /tmp/reviewers.json | sort | tee /tmp/reviewers.txt
# Fetch requested team reviewers, and the name of the team
echo '${{ tojson(github.event.pull_request.requested_teams[*].slug) }}' | tee /tmp/team_reviewers.json
jq --raw-output .[] < /tmp/team_reviewers.json | sort | tee /tmp/team_reviewers.txt
echo '${{ env.TEAM }}' | tee /tmp/team.txt
# If either a reviewer matches a team member, or a team matches our team, say "true"
if [ $(join /tmp/team_members.txt /tmp/reviewers.txt | wc -l) != 0 ]; then
echo "match=true" >> $GITHUB_OUTPUT
elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then
echo "match=true" >> $GITHUB_OUTPUT
else
echo "match=false" >> $GITHUB_OUTPUT
fi
env:
TEAM: "product"
- uses: octokit/graphql-action@v2.x
id: add_to_project
if: steps.any_matching_reviewers.outputs.match == 'true'
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!, $contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.pull_request.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4AAg6N"
TEAM: "product"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
add_design_pr_to_project:
name: Move PRs asking for design review to the design board
runs-on: ubuntu-latest
steps:
- uses: octokit/graphql-action@v2.x
id: find_team_members
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
query find_team_members($team: String!) {
organization(login: "vector-im") {
team(slug: $team) {
members {
nodes {
login
}
}
}
}
}
team: ${{ env.TEAM }}
env:
TEAM: "design"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
- id: any_reviewers_in_the_team
run: |
echo '${{ tojson(fromjson(steps.find_team_members.outputs.data).organization.team.members.nodes[*].login) }}' | tee /tmp/team_members.json
echo '${{ tojson(github.event.pull_request.requested_reviewers[*].login) }}' | tee /tmp/reviewers.json
jq --raw-output .[] < /tmp/team_members.json | sort | tee /tmp/team_members.txt
jq --raw-output .[] < /tmp/reviewers.json | sort | tee /tmp/reviewers.txt
if [ $(join /tmp/team_members.txt /tmp/reviewers.txt | wc -l) = 0 ]; then
echo "::set-output name=match::false"
else
echo "::set-output name=match::true"
fi
- uses: octokit/graphql-action@v2.x
id: add_to_project
if: >
(steps.any_reviewers_in_the_team.outputs.match == 'true') ||
(github.event.pull_request.requested_teams.slug == env.TEAM)
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:String!, $contentid:String!) {
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
projectNextItem {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.pull_request.node_id }}
env:
PROJECT_ID: "PN_kwDOAM0swc0sUA"
TEAM: "design"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -0,0 +1,35 @@
name: Move unlabelled from needs info columns to triaged
on:
issues:
types: [unlabeled]
jobs:
Move_Unabeled_Issue_On_Project_Board:
name: Move no longer X-Needs-Info issues to Triaged
runs-on: ubuntu-latest
if: >
${{
!contains(github.event.issue.labels.*.name, 'X-Needs-Info') }}
env:
BOARD_NAME: "Issue triage"
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
ISSUE: ${{ github.event.issue.number }}
steps:
- name: Check if issue is already in "${{ env.BOARD_NAME }}"
run: |
if curl -i -H 'Content-Type: application/json' -H "Authorization: bearer ${{ secrets.GITHUB_TOKEN }}" -X POST -d '{"query": "query($issue: Int!, $owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { issue(number: $issue) { projectCards { nodes { project { name } } } } } } ", "variables" : "{ \"issue\": '${ISSUE}', \"owner\": \"'${OWNER}'\", \"repo\": \"'${REPO}'\" }" }' https://api.github.com/graphql | grep "\b$BOARD_NAME\b"; then
echo "Issue is already in Project '$BOARD_NAME', proceeding";
echo "ALREADY_IN_BOARD=true" >> $GITHUB_ENV
else
echo "Issue is not in project '$BOARD_NAME', cancelling this workflow"
echo "ALREADY_IN_BOARD=false" >> $GITHUB_ENV
fi
- name: Move issue
uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
if: ${{ env.ALREADY_IN_BOARD == 'true' }}
with:
project: Issue triage
column: Triaged
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

@ -0,0 +1,55 @@
name: Move labelled issues into the Priority bugs column for the Web App Team
on:
issues:
types: [labeled, unlabeled]
jobs:
p1_issues_to_team_workboard:
runs-on: ubuntu-latest
if: >
(!contains(github.event.issue.labels.*.name, 'A-E2EE') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') &&
!contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification') &&
!contains(github.event.issue.labels.*.name, 'A-Spaces') &&
!contains(github.event.issue.labels.*.name, 'A-Spaces-Settings') &&
!contains(github.event.issue.labels.*.name, 'A-Subspaces')) &&
(contains(github.event.issue.labels.*.name, 'T-Defect') &&
contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
contains(github.event.issue.labels.*.name, 'S-Major') &&
contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'A11y') &&
contains(github.event.issue.labels.*.name, 'O-Frequent'))
steps:
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
with:
project: Web App Team
column: P1
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
P1_issues_to_crypto_team_workboard:
runs-on: ubuntu-latest
if: >
(contains(github.event.issue.labels.*.name, 'A-E2EE') ||
contains(github.event.issue.labels.*.name, 'A-E2EE-Cross-Signing') ||
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
contains(github.event.issue.labels.*.name, 'A-E2EE-Key-Backup') ||
contains(github.event.issue.labels.*.name, 'A-E2EE-SAS-Verification')) &&
(contains(github.event.issue.labels.*.name, 'T-Defect') &&
contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
contains(github.event.issue.labels.*.name, 'S-Major') &&
contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'A11y') &&
contains(github.event.issue.labels.*.name, 'O-Frequent'))
steps:
- uses: alex-page/github-project-automation-plus@bb266ff4dde9242060e2d5418e120a133586d488
with:
project: Crypto Team
column: Ready
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}

View file

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

View file

@ -1,71 +0,0 @@
name: Move unlabelled from needs info columns to triaged
on:
issues:
types: [unlabeled]
jobs:
Move_Unabeled_Issue_On_Project_Board:
name: Move no longer X-Needs-Info issues to Triaged
runs-on: ubuntu-latest
if: >
${{
!contains(github.event.issue.labels.*.name, 'X-Needs-Info') }}
env:
BOARD_NAME: "Issue triage"
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}
ISSUE: ${{ github.event.issue.number }}
steps:
- name: Check if issue is already in "${{ env.BOARD_NAME }}"
run: |
json=$(curl -s -H 'Content-Type: application/json' -H "Authorization: bearer ${{ secrets.GITHUB_TOKEN }}" -X POST -d '{"query": "query($issue: Int!, $owner: String!, $repo: String!) { repository(owner: $owner, name: $repo) { issue(number: $issue) { projectCards { nodes { project { name } isArchived } } } } } ", "variables" : "{ \"issue\": '${ISSUE}', \"owner\": \"'${OWNER}'\", \"repo\": \"'${REPO}'\" }" }' https://api.github.com/graphql)
if echo $json | jq '.data.repository.issue.projectCards.nodes | length'; then
if [[ $(echo $json | jq '.data.repository.issue.projectCards.nodes[0].project.name') =~ "${BOARD_NAME}" ]]; then
if [[ $(echo $json | jq '.data.repository.issue.projectCards.nodes[0].isArchived') == 'true' ]]; then
echo "Issue is already in Project '$BOARD_NAME', but is archived - skipping workflow";
echo "SKIP_ACTION=true" >> $GITHUB_ENV
else
echo "Issue is already in Project '$BOARD_NAME', proceeding";
echo "ALREADY_IN_BOARD=true" >> $GITHUB_ENV
fi
else
echo "Issue is not in project '$BOARD_NAME', cancelling this workflow"
echo "ALREADY_IN_BOARD=false" >> $GITHUB_ENV
fi
fi
- name: Move issue
uses: alex-page/github-project-automation-plus@303f24a24c67ce7adf565a07e96720faf126fe36
if: ${{ env.ALREADY_IN_BOARD == 'true' && env.SKIP_ACTION != 'true' }}
with:
project: Issue triage
column: Triaged
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}
remove_Z-Labs_label:
name: Remove Z-Labs label when features behind labs flags are removed
runs-on: ubuntu-latest
if: >
!(contains(github.event.issue.labels.*.name, 'A-Maths') ||
contains(github.event.issue.labels.*.name, 'A-Message-Pinning') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
contains(github.event.issue.labels.*.name, 'A-Jump-To-Date') ||
contains(github.event.issue.labels.*.name, 'A-Themes-Custom') ||
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
contains(github.event.issue.labels.*.name, 'A-Tags') ||
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, 'Z-Labs')
steps:
- uses: actions/github-script@v7
with:
script: |
github.rest.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: ['Z-Labs']
})

View file

@ -1,32 +0,0 @@
# Re-fetches the Jitsi SDK and opens a PR to update it if it's different from what's in the repository
name: Update Jitsi
on:
workflow_dispatch: {}
schedule:
- cron: "0 3 * * 0" # 3am every Sunday
jobs:
update:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
cache: "yarn"
node-version: "lts/*"
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Fetch Jitsi
run: "yarn update:jitsi"
- name: Create Pull Request
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6
with:
token: ${{ secrets.ELEMENT_BOT_TOKEN }}
branch: actions/jitsi-update
delete-branch: true
title: Jitsi Update
labels: |
T-Task

View file

@ -1,102 +0,0 @@
name: Update release topics
on:
workflow_dispatch:
inputs:
expected_status:
description: What type of release is the next expected release
required: true
default: RC
type: choice
options:
- RC
- Release
expected_date:
description: Expected release date e.g. July 11th
required: true
type: string
concurrency: ${{ github.workflow }}
jobs:
bot:
name: Release topic update
runs-on: ubuntu-latest
environment: Matrix
steps:
- uses: actions/github-script@v7
env:
HS_URL: ${{ secrets.BETABOT_HS_URL }}
LOBBY_ROOM_ID: ${{ secrets.ROOM_ID }}
PUBLIC_ROOM_ID: "!YTvKGNlinIzlkMTVRl:matrix.org"
ANNOUNCEMENT_ROOM_ID: "!bijaLdadorKgNGtHdA:matrix.org"
TOKEN: ${{ secrets.BETABOT_ACCESS_TOKEN }}
RELEASE_STATUS: "Release status: ${{ inputs.expected_status }} expected ${{ inputs.expected_date }}"
with:
script: |
const { HS_URL, TOKEN, RELEASE_STATUS, LOBBY_ROOM_ID, PUBLIC_ROOM_ID, ANNOUNCEMENT_ROOM_ID } = process.env;
const repo = context.repo;
const { data } = await github.rest.repos.getLatestRelease({
owner: repo.owner,
repo: repo.repo,
});
console.log("Found latest version: " + data.tag_name);
const releaseTopic = `Stable: ${data.tag_name} | ${RELEASE_STATUS}`;
console.log("Release topic: " + releaseTopic);
const regex = /Stable: v(.+) \| Release status: (\w+) expected (\w+ \d+\w\w)/gm;
async function updateReleaseInTopic(roomId) {
const apiUrl = `${HS_URL}/_matrix/client/v3/rooms/${roomId}/state/m.room.topic/`;
const headers = {
"Content-Type": "application/json",
"Authorization": `Bearer ${TOKEN}`,
};
await fetch(`${HS_URL}/_matrix/client/v3/rooms/${roomId}/join`, {
method: "POST",
headers,
body: "{}",
});
let res = await fetch(apiUrl, {
method: "GET",
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");
return;
}
if (data["org.matrix.msc3765.topic"]) {
data["org.matrix.msc3765.topic"].forEach(d => {
d.body = d.body.replace(regex, releaseTopic);
});
}
res = await fetch(apiUrl, {
method: "PUT",
body: JSON.stringify({
...data,
topic,
}),
headers,
});
if (res.ok) {
console.log(roomId, "topic updated:", topic);
} else {
console.log(roomId, await res.text());
}
}
await updateReleaseInTopic(LOBBY_ROOM_ID);
await updateReleaseInTopic(PUBLIC_ROOM_ID);
await updateReleaseInTopic(ANNOUNCEMENT_ROOM_ID);

7
.gitignore vendored
View file

@ -16,16 +16,9 @@ electron/pub
/config.json
/config.json.*
/config.local*.json
# Legacy skinning file that some people might still have
/src/component-index.js
/.tmp
/webpack-stats.json
.vscode
.vscode/
.env
/coverage
# Auto-generated file
/src/modules.ts
/build_config.yaml
/book
/index.html

30
.gitlab-ci.yml Normal file
View file

@ -0,0 +1,30 @@
stages:
- build
variables:
USE_CUSTOM_SDKS: "true"
JS_SDK_BRANCH: "release-v9.8.0"
JS_SDK_REPO: "https://github.com/matrix-org/matrix-js-sdk.git"
REACT_SDK_REPO: "https://gitlab-ci-token:$GL_BAYERN_REACT_SDK_TOKEN@gitlab.matrix.org/new-vector/dataport/bayern-react-sdk"
REACT_SDK_BRANCH: "master"
docker-build:
tags: ['shell']
stage: build
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
- "[ -d './js-sdk' ] && rm -rf ./js-sdk"
- "[[ $JS_SDK_BRANCH != 'master' ]] && git clone --depth 1 --branch $JS_SDK_BRANCH $JS_SDK_REPO js-sdk && cd js-sdk && export JS_SDK_SHA=$(git rev-parse --short=12 HEAD) && cd ../ && rm -rf js-sdk"
- "[[ $JS_SDK_BRANCH == 'master' ]] && export JS_SDK_SHA=master"
- "[ -d './react-sdk' ] && rm -rf ./react-sdk"
- "[[ $REACT_SDK_BRANCH != 'master' ]] && git clone --depth 1 --branch $REACT_SDK_BRANCH $REACT_SDK_REPO react-sdk && cd react-sdk && export REACT_SDK_SHA=$(git rev-parse --short=12 HEAD) && cd ../ && rm -rf react-sdk"
- "[[ $REACT_SDK_BRANCH == 'master' ]] && export REACT_SDK_SHA=master"
- "[[ $CI_COMMIT_BRANCH != 'master' ]] && export ELEMENT_WEB_SHA=$(git rev-parse --short=12 HEAD)"
- "[[ $CI_COMMIT_BRANCH == 'master' ]] && export ELEMENT_WEB_SHA=master"
- "[[ -v CI_COMMIT_TAG ]] && export SPECIAL_DOCKER_TAG=$CI_REGISTRY_IMAGE:$CI_COMMIT_REF_NAME"
- "([[ $CI_COMMIT_BRANCH == 'master' ]] && [[ $REACT_SDK_BRANCH == 'master' ]] && [[ $JS_SDK_BRANCH == 'master' ]]) && export SPECIAL_DOCKER_TAG=$CI_REGISTRY_IMAGE:latest"
- '[[ -z $SPECIAL_DOCKER_TAG ]] && export DOCKER_TAG="$CI_REGISTRY_IMAGE:$ELEMENT_WEB_SHA-react-$REACT_SDK_SHA-js-$JS_SDK_SHA" || export DOCKER_TAG="$SPECIAL_DOCKER_TAG"'
script:
- echo "Docker tag will be $DOCKER_TAG"
- docker build --pull -t "$DOCKER_TAG" --build-arg "USE_CUSTOM_SDKS=$USE_CUSTOM_SDKS" --build-arg "JS_SDK_BRANCH=$JS_SDK_BRANCH" --build-arg "JS_SDK_REPO=$JS_SDK_REPO" --build-arg "REACT_SDK_REPO=$REACT_SDK_REPO" --build-arg "REACT_SDK_BRANCH=$REACT_SDK_BRANCH" .
- docker push "$DOCKER_TAG"

View file

@ -1,4 +0,0 @@
#!/usr/bin/env sh
. "$(dirname "$0")/_/husky.sh"
npx lint-staged --concurrent false

View file

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

View file

@ -1,37 +1,35 @@
{
"minify": false,
"enableClasses": false,
"feature-detects": [
"test/css/animations",
"test/css/displaytable",
"test/css/filters",
"test/css/flexbox",
"test/css/objectfit",
"minify": true,
"enableClasses": false,
"feature-detects": [
"test/css/animations",
"test/css/displaytable",
"test/css/filters",
"test/css/flexbox",
"test/css/objectfit",
"test/es5/date",
"test/es5/function",
"test/es5/object",
"test/es5/undefined",
"test/es5/date",
"test/es5/function",
"test/es5/object",
"test/es5/undefined",
"test/es6/array",
"test/es6/collections",
"test/es6/promises",
"test/es6/string",
"test/es6/array",
"test/es6/collections",
"test/es6/promises",
"test/es6/string",
"test/svg",
"test/svg/asimg",
"test/svg/filters",
"test/svg",
"test/svg/asimg",
"test/svg/filters",
"test/url/parser",
"test/url/urlsearchparams",
"test/url/parser",
"test/url/urlsearchparams",
"test/cors",
"test/crypto",
"test/iframe/sandbox",
"test/json",
"test/network/fetch",
"test/storage/localstorage",
"test/window/resizeobserver",
"test/audio/webaudio"
]
"test/cors",
"test/crypto",
"test/iframe/sandbox",
"test/json",
"test/network/fetch",
"test/storage/localstorage"
]
}

View file

@ -1,34 +0,0 @@
/build
/dist
/lib
/node_modules
/packages/
/webapp
/*.log
yarn.lock
electron/dist
electron/pub
**/.idea
/.tmp
/webpack-stats.json
.vscode
.vscode/
.env
/coverage
# Auto-generated file
/src/modules.ts
/src/i18n/strings
/build_config.yaml
# Raises an error because it contains a template var breaking the script tag
src/vector/index.html
src/vector/modernizr.js
/docs/lib
/book
/debian/tmp
# This file is owned, parsed, and generated by allchange, which doesn't comply with prettier
/CHANGELOG.md
/docs/changelogs
# Downloaded and already minified
res/jitsi_external_api.min.js

View file

@ -1 +0,0 @@
module.exports = require("eslint-plugin-matrix-org/.prettierrc.js");

0
.sentryclirc Normal file
View file

View file

@ -1,4 +1,26 @@
// Copied from react-sdk
// TODO: Only keep one copy of this for synchronization purposes
module.exports = {
...require("matrix-react-sdk/.stylelintrc.js"),
extends: ["stylelint-config-standard"],
"extends": "stylelint-config-standard",
"plugins": [
"stylelint-scss",
],
"rules": {
"indentation": 4,
"comment-empty-line-before": null,
"declaration-empty-line-before": null,
"length-zero-no-unit": null,
"rule-empty-line-before": null,
"color-hex-length": null,
"max-empty-lines": null,
"number-no-trailing-zeros": null,
"number-leading-zero": null,
"selector-list-comma-newline-after": null,
"at-rule-no-unknown": null,
"no-descending-specificity": null,
"scss/at-rule-no-unknown": [true, {
// https://github.com/vector-im/element-web/issues/10544
"ignoreAtRules": ["define-mixin"],
}],
}
};

File diff suppressed because it is too large Load diff

View file

@ -1,309 +1,4 @@
# Contributing code to Element Web
Contributing code to Element
============================
Everyone is welcome to contribute code to Element Web, provided that they are
willing to license their contributions under the same license as the project
itself. We follow a simple 'inbound=outbound' model for contributions: the act
of submitting an 'inbound' contribution means that the contributor agrees to
license the code under the same terms as the project's overall 'outbound'
license - in this case, Apache Software License v2 (see
[LICENSE](LICENSE)).
## How to contribute
The preferred and easiest way to contribute changes to the project is to fork
it on github, and then create a pull request to ask us to pull your changes
into our repo (https://help.github.com/articles/using-pull-requests/)
We use GitHub's pull request workflow to review the contribution, and either
ask you to make any refinements needed or merge it and make them ourselves.
Your PR should have a title that describes what change is being made. This
is used for the text in the Changelog entry by default (see below), so a good
title will tell a user succinctly what change is being made. "Fix bug where
cows had five legs" and, "Add support for miniature horses" are examples of good
titles. Don't include an issue number here: that belongs in the description.
Definitely don't use the GitHub default of "Update file.ts".
As for your PR description, it should include these things:
- References to any bugs fixed by the change (in GitHub's `Fixes` notation)
- Describe the why and what is changing in the PR description so it's easy for
onlookers and reviewers to onboard and context switch. This information is
also helpful when we come back to look at this in 6 months and ask "why did
we do it like that?" we have a chance of finding out.
- Why didn't it work before? Why does it work now? What use cases does it
unlock?
- If you find yourself adding information on how the code works or why you
chose to do it the way you did, make sure this information is instead
written as comments in the code itself.
- Sometimes a PR can change considerably as it is developed. In this case,
the description should be updated to reflect the most recent state of
the PR. (It can be helpful to retain the old content under a suitable
heading, for additional context.)
- Include both **before** and **after** screenshots to easily compare and discuss
what's changing.
- Include a step-by-step testing strategy so that a reviewer can check out the
code locally and easily get to the point of testing your change.
- Add comments to the diff for the reviewer that might help them to understand
why the change is necessary or how they might better understand and review it.
### Changelogs
There's no need to manually add Changelog entries: we use information in the
pull request to populate the information that goes into the changelogs our
users see, both for Element Web itself and other projects on which it is based.
This is picked up from both labels on the pull request and the `Notes:`
annotation in the description. By default, the PR title will be used for the
changelog entry, but you can specify more options, as follows.
To add a longer, more detailed description of the change for the changelog:
_Fix llama herding bug_
```
Notes: Fix a bug (https://github.com/matrix-org/notaproject/issues/123) where the 'Herd' button would not herd more than 8 Llamas if the moon was in the waxing gibbous phase
```
For some PRs, it's not useful to have an entry in the user-facing changelog (this is
the default for PRs labelled with `T-Task`):
_Remove outdated comment from `Ungulates.ts`_
```
Notes: none
```
Sometimes, you're fixing a bug in a downstream project, in which case you want
an entry in that project's changelog. You can do that too:
_Fix another herding bug_
```
Notes: Fix a bug where the `herd()` function would only work on Tuesdays
element-web notes: Fix a bug where the 'Herd' button only worked on Tuesdays
```
This example is for Element Web. You can specify:
- matrix-react-sdk
- element-web
- element-desktop
If your PR introduces a breaking change, use the `Notes` section in the same
way, additionally adding the `X-Breaking-Change` label (see below). There's no need
to specify in the notes that it's a breaking change - this will be added
automatically based on the label - but remember to tell the developer how to
migrate:
_Remove legacy class_
```
Notes: Remove legacy `Camelopard` class. `Giraffe` should be used instead.
```
Other metadata can be added using labels.
- `X-Breaking-Change`: A breaking change - adding this label will mean the change causes a _major_ version bump.
- `T-Enhancement`: A new feature - adding this label will mean the change causes a _minor_ version bump.
- `T-Defect`: A bug fix (in either code or docs).
- `T-Task`: No user-facing changes, eg. code comments, CI fixes, refactors or tests. Won't have a changelog entry unless you specify one.
If you don't have permission to add labels, your PR reviewer(s) can work with you
to add them: ask in the PR description or comments.
We use continuous integration, and all pull requests get automatically tested:
if your change breaks the build, then the PR will show that there are failed
checks, so please check back after a few minutes.
## Tests
Your PR should include tests.
For new user facing features in `matrix-js-sdk`, `matrix-react-sdk` or `element-web`, you
must include:
1. Comprehensive unit tests written in Jest. These are located in `/test`.
2. "happy path" end-to-end tests.
These are located in `/playwright/e2e` in `matrix-react-sdk`, and
are run using `element-web`. Ideally, you would also include tests for edge
and error cases.
Unit tests are expected even when the feature is in labs. It's good practice
to write tests alongside the code as it ensures the code is testable from
the start, and gives you a fast feedback loop while you're developing the
functionality. End-to-end tests should be added prior to the feature
leaving labs, but don't have to be present from the start (although it might
be beneficial to have some running early, so you can test things faster).
For bugs in those repos, your change must include at least one unit test or
end-to-end test; which is best depends on what sort of test most concisely
exercises the area.
Changes to must be accompanied by unit tests written in Jest.
These are located in `/spec/` in `matrix-js-sdk` or `/test/` in `element-web`
and `matrix-react-sdk`.
When writing unit tests, please aim for a high level of test coverage
for new code - 80% or greater. If you cannot achieve that, please document
why it's not possible in your PR.
Some sections of code are not sensible to add coverage for, such as those
which explicitly inhibit noisy logging for tests. Which can be hidden using
an istanbul magic comment as [documented here][1]. See example:
```javascript
/* istanbul ignore if */
if (process.env.NODE_ENV !== "test") {
logger.error("Log line that is noisy enough in tests to want to skip");
}
```
Tests validate that your change works as intended and also document
concisely what is being changed. Ideally, your new tests fail
prior to your change, and succeed once it has been applied. You may
find this simpler to achieve if you write the tests first.
If you're spiking some code that's experimental and not being used to support
production features, exceptions can be made to requirements for tests.
Note that tests will still be required in order to ship the feature, and it's
strongly encouraged to think about tests early in the process, as adding
tests later will become progressively more difficult.
If you're not sure how to approach writing tests for your change, ask for help
in [#element-dev](https://matrix.to/#/#element-dev:matrix.org).
## Code style
Element Web aims to target TypeScript/ES6. All new files should be written in
TypeScript and existing files should use ES6 principles where possible.
Members should not be exported as a default export in general - it causes problems
with the architecture of the SDK (index file becomes less clear) and could
introduce naming problems (as default exports get aliased upon import). In
general, avoid using `export default`.
The remaining code style is documented in [code_style.md](./code_style.md).
Contributors are encouraged to it and follow the principles set out there.
Please ensure your changes match the cosmetic style of the existing project,
and **_never_** mix cosmetic and functional changes in the same commit, as it
makes it horribly hard to review otherwise.
## Attribution
Everyone who contributes anything to Matrix is welcome to be listed in the
AUTHORS.rst file for the project in question. Please feel free to include a
change to AUTHORS.rst in your pull request to list yourself and a short
description of the area(s) you've worked on. Also, we sometimes have swag to
give away to contributors - if you feel that Matrix-branded apparel is missing
from your life, please mail us your shipping address to matrix at matrix.org
and we'll try to fix it :)
## Sign off
In order to have a concrete record that your contribution is intentional
and you agree to license it under the same terms as the project's license, we've
adopted the same lightweight approach that the Linux Kernel
(https://www.kernel.org/doc/html/latest/process/submitting-patches.html), Docker
(https://github.com/docker/docker/blob/master/CONTRIBUTING.md), and many other
projects use: the DCO (Developer Certificate of Origin:
http://developercertificate.org/). This is a simple declaration that you wrote
the contribution or otherwise have the right to contribute it to Matrix:
```
Developer Certificate of Origin
Version 1.1
Copyright (C) 2004, 2006 The Linux Foundation and its contributors.
660 York Street, Suite 102,
San Francisco, CA 94110 USA
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
Developer's Certificate of Origin 1.1
By making a contribution to this project, I certify that:
(a) The contribution was created in whole or in part by me and I
have the right to submit it under the open source license
indicated in the file; or
(b) The contribution is based upon previous work that, to the best
of my knowledge, is covered under an appropriate open source
license and I have the right under that license to submit that
work with modifications, whether created in whole or in part
by me, under the same open source license (unless I am
permitted to submit under a different license), as indicated
in the file; or
(c) The contribution was provided directly to me by some other
person who certified (a), (b) or (c) and I have not modified
it.
(d) I understand and agree that this project and the contribution
are public and that a record of the contribution (including all
personal information I submit with it, including my sign-off) is
maintained indefinitely and may be redistributed consistent with
this project or the open source license(s) involved.
```
If you agree to this for your contribution, then all that's needed is to
include the line in your commit or pull request comment:
```
Signed-off-by: Your Name <your@email.example.org>
```
We accept contributions under a legally identifiable name, such as your name on
government documentation or common-law names (names claimed by legitimate usage
or repute). Unfortunately, we cannot accept anonymous contributions at this
time.
Git allows you to add this signoff automatically when using the `-s` flag to
`git commit`, which uses the name and email set in your `user.name` and
`user.email` git configs.
If you forgot to sign off your commits before making your pull request and are
on Git 2.17+ you can mass signoff using rebase:
```
git rebase --signoff origin/develop
```
## Private sign off
If you would like to provide your legal name privately to the Matrix.org
Foundation (instead of in a public commit or comment), you can do so by emailing
your legal name and a link to the pull request to dco@matrix.org. It helps to
include "sign off" or similar in the subject line. You will then be instructed
further.
Once private sign off is complete, doing so for future contributions will not
be required.
# Review expectations
See https://github.com/element-hq/element-meta/wiki/Review-process
# Merge Strategy
The preferred method for merging pull requests is squash merging to keep the
commit history trim, but it is up to the discretion of the team member merging
the change. We do not support rebase merges due to `allchange` being unable to
handle them. When merging make sure to leave the default commit title, or
at least leave the PR number at the end in brackets like by default.
When stacking pull requests, you may wish to do the following:
1. Branch from develop to your branch (branch1), push commits onto it and open a pull request
2. Branch from your base branch (branch1) to your work branch (branch2), push commits and open a pull request configuring the base to be branch1, saying in the description that it is based on your other PR.
3. Merge the first PR using a merge commit otherwise your stacked PR will need a rebase. Github will automatically adjust the base branch of your other PR to be develop.
[1]: https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md
# Decoding Stack Traces
Element Web has crashed and given you an obfuscated stack trace? Don't panic:
use the [Decoder Ring](https://app.element.io/decoder-ring/) (or /decoder-ring/
on any Element Web deploy). It is somewhat of a manual process, but it should
tell you what lines the stack trace corresponds to from the source maps.
Element follows the same pattern as the [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md).

View file

@ -1,5 +1,5 @@
# Builder
FROM --platform=$BUILDPLATFORM node:20-bullseye as builder
FROM node:14-buster as builder
# Support custom branches of the react-sdk and js-sdk. This also helps us build
# images of element-web develop.
@ -15,7 +15,7 @@ WORKDIR /src
COPY . /src
RUN dos2unix /src/scripts/docker-link-repos.sh && bash /src/scripts/docker-link-repos.sh
RUN yarn --network-timeout=200000 install
RUN yarn --network-timeout=100000 install
RUN dos2unix /src/scripts/docker-package.sh && bash /src/scripts/docker-package.sh
@ -23,10 +23,13 @@ RUN dos2unix /src/scripts/docker-package.sh && bash /src/scripts/docker-package.
RUN cp /src/config.sample.json /src/webapp/config.json
# App
FROM nginx:alpine-slim
FROM nginx:alpine
COPY --from=builder /src/webapp /app
# Insert wasm type into Nginx mime.types file so they load correctly.
RUN sed -i '3i\ \ \ \ application/wasm wasm\;' /etc/nginx/mime.types
# Override default nginx config
COPY /nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf

310
README.md
View file

@ -1,93 +1,104 @@
[![Chat](https://img.shields.io/matrix/element-web:matrix.org?logo=matrix)](https://matrix.to/#/#element-web:matrix.org)
![Tests](https://github.com/element-hq/element-web/actions/workflows/tests.yaml/badge.svg)
![Static Analysis](https://github.com/element-hq/element-web/actions/workflows/static_analysis.yaml/badge.svg)
[![Localazy](https://img.shields.io/endpoint?url=https%3A%2F%2Fconnect.localazy.com%2Fstatus%2Felement-web%2Fdata%3Fcontent%3Dall%26title%3Dlocalazy%26logo%3Dtrue)](https://localazy.com/p/element-web)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=element-web)
[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=coverage)](https://sonarcloud.io/summary/new_code?id=element-web)
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=element-web)
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=element-web&metric=bugs)](https://sonarcloud.io/summary/new_code?id=element-web)
# Element
Element
=======
Element (formerly known as Vector and Riot) is a Matrix web client built using the [Matrix
React SDK](https://github.com/matrix-org/matrix-react-sdk).
# Supported Environments
Supported Environments
======================
Element has several tiers of support for different environments:
- Supported
- Definition:
- Issues **actively triaged**, regressions **block** the release
- Last 2 major versions of Chrome, Firefox, and Edge on desktop OSes
- Last 2 versions of Safari
- Latest release of official Element Desktop app on desktop OSes
- Desktop OSes means macOS, Windows, and Linux versions for desktop devices
that are actively supported by the OS vendor and receive security updates
- Best effort
- Definition:
- Issues **accepted**, regressions **do not block** the release
- The wider Element Products(including Element Call and the Enterprise Server Suite) do still not officially support these browsers.
- The element web project and its contributors should keep the client functioning and gracefully degrade where other sibling features (E.g. Element Call) may not function.
- Last major release of Firefox ESR and Chrome/Edge Extended Stable
- Community Supported
- Definition:
- Issues **accepted**, regressions **do not block** the release
- Community contributions are welcome to support these issues
- Mobile web for current stable version of Chrome, Firefox, and Safari on Android, iOS, and iPadOS
- Not supported
- Definition: Issues only affecting unsupported environments are **closed**
- Everything else
The period of support for these tiers should last until the releases specified above, plus 1 app release cycle(2 weeks). In the case of Firefox ESR this is extended further to allow it land in Debian Stable.
* Supported
* Definition: Issues **actively triaged**, regressions **block** the release
* Last 2 major versions of Chrome, Firefox, Safari, and Edge on desktop OSes
* Latest release of official Element Desktop app on desktop OSes
* Desktop OSes means macOS, Windows, and Linux versions for desktop devices
that are actively supported by the OS vendor and receive security updates
* Experimental
* Definition: Issues **accepted**, regressions **do not block** the release
* Element as an installed PWA via current stable version of Chrome, Firefox, and Safari
* Mobile web for current stable version of Chrome, Firefox, and Safari on Android, iOS, and iPadOS
* Not supported
* Definition: Issues only affecting unsupported environments are **closed**
* Everything else
For accessing Element on an Android or iOS device, we currently recommend the
native apps [element-android](https://github.com/element-hq/element-android)
and [element-ios](https://github.com/element-hq/element-ios).
native apps [element-android](https://github.com/vector-im/element-android)
and [element-ios](https://github.com/vector-im/element-ios).
# Getting Started
Getting Started
===============
The easiest way to test Element is to just use the hosted copy at <https://app.element.io>.
The `develop` branch is continuously deployed to <https://develop.element.io>
for those who like living dangerously.
To host your own instance of Element see [Installing Element Web](docs/install.md).
To host your own copy of Element, the quickest bet is to use a pre-built
released version of Element:
To install Element as a desktop application, see [Running as a desktop app](#running-as-a-desktop-app) below.
1. Download the latest version from <https://github.com/vector-im/element-web/releases>
1. Untar the tarball on your web server
1. Move (or symlink) the `element-x.x.x` directory to an appropriate name
1. Configure the correct caching headers in your webserver (see below)
1. If desired, copy `config.sample.json` to `config.json` and edit it
as desired. See the [configuration docs](docs/config.md) for details.
1. Enter the URL into your browser and log into Element!
# Important Security Notes
Releases are signed using gpg and the OpenPGP standard, and can be checked against the public key located
at <https://packages.riot.im/element-release-key.asc>.
## Separate domains
Note that for the security of your chats will need to serve Element
over HTTPS. Major browsers also do not allow you to use VoIP/video
chats over HTTP, as WebRTC is only usable over HTTPS.
There are some exceptions like when using localhost, which is
considered a [secure context](https://developer.mozilla.org/docs/Web/Security/Secure_Contexts)
and thus allowed.
To install Element as a desktop application, see [Running as a desktop
app](#running-as-a-desktop-app) below.
Important Security Notes
========================
Separate domains
----------------
We do not recommend running Element from the same domain name as your Matrix
homeserver. The reason is the risk of XSS (cross-site-scripting)
homeserver. The reason is the risk of XSS (cross-site-scripting)
vulnerabilities that could occur if someone caused Element to load and render
malicious user generated content from a Matrix API which then had trusted
access to Element (or other apps) due to sharing the same domain.
We have put some coarse mitigations into place to try to protect against this
situation, but it's still not good practice to do it in the first place. See
<https://github.com/element-hq/element-web/issues/1977> for more details.
situation, but it's still not good practice to do it in the first place. See
<https://github.com/vector-im/element-web/issues/1977> for more details.
## Configuration best practices
Configuration best practices
----------------------------
Unless you have special requirements, you will want to add the following to
your web server configuration when hosting Element Web:
- The `X-Frame-Options: SAMEORIGIN` header, to prevent Element Web from being
framed and protect from [clickjacking][owasp-clickjacking].
- The `frame-ancestors 'self'` directive to your `Content-Security-Policy`
header, as the modern replacement for `X-Frame-Options` (though both should be
included since not all browsers support it yet, see
[this][owasp-clickjacking-csp]).
- The `X-Content-Type-Options: nosniff` header, to [disable MIME
sniffing][mime-sniffing].
- The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in
legacy browsers.
* The `X-Frame-Options: SAMEORIGIN` header, to prevent Element Web from being
framed and protect from [clickjacking][owasp-clickjacking].
* The `frame-ancestors 'none'` directive to your `Content-Security-Policy`
header, as the modern replacement for `X-Frame-Options` (though both should be
included since not all browsers support it yet, see
[this][owasp-clickjacking-csp]).
* The `X-Content-Type-Options: nosniff` header, to [disable MIME
sniffing][mime-sniffing].
* The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in
legacy browsers.
[mime-sniffing]: https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing
[owasp-clickjacking-csp]: https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html#content-security-policy-frame-ancestors-examples
[owasp-clickjacking]: https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html
[mime-sniffing]:
<https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing>
[owasp-clickjacking-csp]:
<https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html#content-security-policy-frame-ancestors-examples>
[owasp-clickjacking]:
<https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html>
If you are using nginx, this would look something like the following:
@ -95,23 +106,15 @@ If you are using nginx, this would look something like the following:
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "frame-ancestors 'self'";
```
For Apache, the configuration looks like:
```
Header set X-Frame-Options SAMEORIGIN
Header set X-Content-Type-Options nosniff
Header set X-XSS-Protection "1; mode=block"
Header set Content-Security-Policy "frame-ancestors 'self'"
add_header Content-Security-Policy "frame-ancestors 'none'";
```
Note: In case you are already setting a `Content-Security-Policy` header
elsewhere, you should modify it to include the `frame-ancestors` directive
instead of adding that last line.
# Building From Source
Building From Source
====================
Element is a modular webapp built with modern ES6 and uses a Node.js build system.
Ensure you have the latest LTS version of Node.js installed.
@ -119,12 +122,12 @@ Ensure you have the latest LTS version of Node.js installed.
Using `yarn` instead of `npm` is recommended. Please see the Yarn [install
guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it already.
1. Install or update `node.js` so that your `node` is at least the current recommended LTS.
1. Install or update `node.js` so that your `node` is at least v14.x.
1. Install `yarn` if not present already.
1. Clone the repo: `git clone https://github.com/element-hq/element-web.git`.
1. Clone the repo: `git clone https://github.com/vector-im/element-web.git`.
1. Switch to the element-web directory: `cd element-web`.
1. Install the prerequisites: `yarn install`.
- If you're using the `develop` branch, then it is recommended to set up a
* If you're using the `develop` branch, then it is recommended to set up a
proper development environment (see [Setting up a dev
environment](#setting-up-a-dev-environment) below). Alternatively, you
can use <https://develop.element.io> - the continuous integration release of
@ -141,29 +144,89 @@ will not appear in Settings without using the dist script. You can then mount th
`webapp` directory on your web server to actually serve up the app, which is
entirely static content.
# Running as a Desktop app
Running as a Desktop app
========================
Element can also be run as a desktop app, wrapped in Electron. You can download a
pre-built version from <https://element.io/get-started> or, if you prefer,
build it yourself.
To build it yourself, follow the instructions at <https://github.com/element-hq/element-desktop>.
To build it yourself, follow the instructions at <https://github.com/vector-im/element-desktop>.
Many thanks to @aviraldg for the initial work on the Electron integration.
The [configuration docs](docs/config.md#desktop-app-configuration) show how to override the desktop app's default settings if desired.
Other options for running as a desktop app:
# config.json
* @asdf:matrix.org points out that you can use nativefier and it just works(tm)
```bash
yarn global add nativefier
nativefier https://app.element.io/
```
The [configuration docs](docs/config.md#desktop-app-configuration) show how to
override the desktop app's default settings if desired.
Running from Docker
===================
The Docker image can be used to serve element-web as a web server. The easiest way to use
it is to use the prebuilt image:
```bash
docker run -p 80:80 vectorim/element-web
```
To supply your own custom `config.json`, map a volume to `/app/config.json`. For example,
if your custom config was located at `/etc/element-web/config.json` then your Docker command
would be:
```bash
docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web
```
To build the image yourself:
```bash
git clone https://github.com/vector-im/element-web.git element-web
cd element-web
git checkout master
docker build .
```
If you're building a custom branch, or want to use the develop branch, check out the appropriate
element-web branch and then run:
```bash
docker build -t \
--build-arg USE_CUSTOM_SDKS=true \
--build-arg REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git" \
--build-arg REACT_SDK_BRANCH="develop" \
--build-arg JS_SDK_REPO="https://github.com/matrix-org/matrix-js-sdk.git" \
--build-arg JS_SDK_BRANCH="develop" \
.
```
Running in Kubernetes
=====================
The provided element-web docker image can also be run from within a Kubernetes cluster.
See the [Kubernetes example](docs/kubernetes.md) for more details.
config.json
===========
Element supports a variety of settings to configure default servers, behaviour, themes, etc.
See the [configuration docs](docs/config.md) for more details.
# Labs Features
Labs Features
=============
Some features of Element may be enabled by flags in the `Labs` section of the settings.
Some of these features are described in [labs.md](https://github.com/element-hq/element-web/blob/develop/docs/labs.md).
Some of these features are described in [labs.md](https://github.com/vector-im/element-web/blob/develop/docs/labs.md).
# Caching requirements
Caching requirements
====================
Element requires the following URLs not to be cached, when/if you are serving Element from your own webserver:
@ -180,17 +243,17 @@ webserver to return `Cache-Control: no-cache` for `/`. This ensures the browser
the next page load after it's been deployed. Note that this is already configured for you in the nginx config of our
Dockerfile.
# Development
Development
===========
Before attempting to develop on Element you **must** read the [developer guide
for `matrix-react-sdk`](https://github.com/matrix-org/matrix-react-sdk#developer-guide), which
also defines the design, architecture and style for Element too.
Read the [Choosing an issue](docs/choosing-an-issue.md) page for some guidance
about where to start. Before starting work on a feature, it's best to ensure
your plan aligns well with our vision for Element. Please chat with the team in
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) before
you start so we can ensure it's something we'd be willing to merge.
Before starting work on a feature, it's best to ensure your plan aligns well
with our vision for Element. Please chat with the team in
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) before you
start so we can ensure it's something we'd be willing to merge.
You should also familiarise yourself with the ["Here be Dragons" guide
](https://docs.google.com/document/d/12jYzvkidrp1h7liEuLIe6BMdU0NUjndUYI971O06ooM)
@ -201,8 +264,11 @@ top of the underlying `matrix-react-sdk`. `matrix-react-sdk` provides both the
higher and lower level React components useful for building Matrix communication
apps using React.
After creating a new component you must run `yarn reskindex` to regenerate
the `component-index.js` for the app (used in future for skinning).
Please note that Element is intended to run correctly without access to the public
internet. So please don't depend on resources (JS libs, CSS, images, fonts)
internet. So please don't depend on resources (JS libs, CSS, images, fonts)
hosted by external CDNs or servers but instead please package all dependencies
into Element itself.
@ -210,7 +276,8 @@ CSS hot-reload is available as an opt-in development feature. You can enable it
by defining a `CSS_HOT_RELOAD` environment variable, in a `.env` file in the root
of the repository. See `.env.example` for documentation and an example.
# Setting up a dev environment
Setting up a dev environment
============================
Much of the functionality in Element is actually in the `matrix-react-sdk` and
`matrix-js-sdk` modules. It is possible to set these up in a way that makes it
@ -219,7 +286,7 @@ having to manually rebuild each time.
First clone and build `matrix-js-sdk`:
```bash
``` bash
git clone https://github.com/matrix-org/matrix-js-sdk.git
pushd matrix-js-sdk
yarn link
@ -238,22 +305,15 @@ yarn install
popd
```
Clone the repo and switch to the `element-web` directory:
```bash
git clone https://github.com/element-hq/element-web.git
cd element-web
```
Configure the app by copying `config.sample.json` to `config.json` and
modifying it. See the [configuration docs](docs/config.md) for details.
Finally, build and start Element itself:
```bash
git clone https://github.com/vector-im/element-web.git
cd element-web
yarn link matrix-js-sdk
yarn link matrix-react-sdk
yarn install
yarn reskindex
yarn start
```
@ -266,9 +326,12 @@ Wait a few seconds for the initial build to finish; you should see something lik
[element-js] 「wdm」: Compiled successfully.
```
Remember, the command will not terminate since it runs the web server
and rebuilds source files when they change. This development server also
disables caching, so do NOT use it in production.
Remember, the command will not terminate since it runs the web server
and rebuilds source files when they change. This development server also
disables caching, so do NOT use it in production.
Configure the app by copying `config.sample.json` to `config.json` and
modifying it. See the [configuration docs](docs/config.md) for details.
Open <http://127.0.0.1:8080/> in your browser to see your newly built Element.
@ -277,8 +340,8 @@ for changes. If the inotify limits are too low your build will fail silently or
`Error: EMFILE: too many open files`. To avoid these issues, we recommend a watch limit
of at least `128M` and instance limit around `512`.
You may be interested in issues [#15750](https://github.com/element-hq/element-web/issues/15750) and
[#15774](https://github.com/element-hq/element-web/issues/15774) for further details.
You may be interested in issues [#15750](https://github.com/vector-im/element-web/issues/15750) and
[#15774](https://github.com/vector-im/element-web/issues/15774) for further details.
To set a new inotify watch and instance limit, execute:
@ -296,36 +359,53 @@ echo fs.inotify.max_user_instances=512 | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
```
---
___
When you make changes to `matrix-react-sdk` or `matrix-js-sdk` they should be
automatically picked up by webpack and built.
If you add or remove any components from the Element skin, you will need to rebuild
the skin's index by running, `yarn reskindex`.
If any of these steps error with, `file table overflow`, you are probably on a mac
which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again.
You'll need to do this in each new terminal you open before building Element.
## Running the tests
Running the tests
-----------------
There are a number of application-level tests in the `tests` directory; these
are designed to run with Jest and JSDOM. To run them
are designed to run in a browser instance under the control of
[karma](https://karma-runner.github.io). To run them:
```
yarn test
```
* Make sure you have Chrome installed (a recent version, like 59)
* Make sure you have `matrix-js-sdk` and `matrix-react-sdk` installed and
built, as above
* `yarn test`
The above will run the tests under Chrome in a `headless` mode.
You can also tell karma to run the tests in a loop (every time the source
changes), in an instance of Chrome on your desktop, with `yarn
test-multi`. This also gives you the option of running the tests in 'debug'
mode, which is useful for stepping through the tests in the developer tools.
### End-to-End tests
See [matrix-react-sdk](https://github.com/matrix-org/matrix-react-sdk/#end-to-end-tests) for how to run the end-to-end tests.
See [matrix-react-sdk](https://github.com/matrix-org/matrix-react-sdk/#end-to-end-tests) how to run the end-to-end tests.
# Translations
Translations
============
To add a new translation, head to the [translating doc](docs/translating.md).
For a developer guide, see the [translating dev doc](docs/translating-dev.md).
# Triaging issues
[<img src="https://translate.element.io/widgets/element-web/-/multi-auto.svg" alt="translationsstatus" width="340">](https://translate.element.io/engage/element-web/?utm_source=widget)
Issues are triaged by community members and the Web App Team, following the [triage process](https://github.com/element-hq/element-meta/wiki/Triage-process).
Triaging issues
===============
We use [issue labels](https://github.com/element-hq/element-meta/wiki/Issue-labelling) to sort all incoming issues.
Issues are triaged by community members and the Web App Team, following the [triage process](https://github.com/vector-im/element-meta/wiki/Triage-process).
We use [issue labels](https://github.com/vector-im/element-meta/wiki/Issue-labelling) to sort all incoming issues.

View file

@ -1,34 +1,25 @@
module.exports = {
sourceMaps: true,
presets: [
[
"@babel/preset-env",
{
targets: [
"last 2 Chrome versions",
"last 2 Firefox versions",
"last 2 Safari versions",
"last 2 Edge versions",
],
include: ["@babel/plugin-transform-class-properties"],
},
],
["@babel/preset-typescript", { allowDeclareFields: true }],
"sourceMaps": true,
"presets": [
["@babel/preset-env", {
"targets": [
"last 2 Chrome versions",
"last 2 Firefox versions",
"last 2 Safari versions",
"last 2 Edge versions",
],
}],
"@babel/preset-typescript",
"@babel/preset-react",
],
plugins: [
"plugins": [
["@babel/plugin-proposal-decorators", {legacy: true}],
"@babel/plugin-proposal-export-default-from",
"@babel/plugin-transform-numeric-separator",
"@babel/plugin-transform-object-rest-spread",
"@babel/plugin-transform-optional-chaining",
"@babel/plugin-transform-nullish-coalescing-operator",
// transform logical assignment (??=, ||=, &&=). preset-env doesn't
// normally bother with these (presumably because all the target
// browsers support it natively), but they make our webpack version (or
// something downstream of babel, at least) fall over.
"@babel/plugin-transform-logical-assignment-operators",
"@babel/plugin-proposal-numeric-separator",
"@babel/plugin-proposal-class-properties",
"@babel/plugin-proposal-object-rest-spread",
"@babel/plugin-proposal-optional-chaining",
"@babel/plugin-proposal-nullish-coalescing-operator",
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-transform-runtime",
],

View file

@ -1,33 +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
additional-css = ["docs/lib/custom.css"]
# The source code URL of the repository
git-repository-url = "https://github.com/element-hq/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

@ -1,25 +0,0 @@
# A sample build_config.yaml to supply to Element Web's build pipeline,
# enabling custom functionality at compile time. Copy this file to
# `build_config.yaml` in the same directory to use, as you would with
# `config.json`.
#
# Note: The vast majority of users DO NOT need this. If you are looking
# to build your own Element Web as seen on app.element.io or similar then
# this is not required.
#
# This config file does become required if you are looking to add runtime
# functionality to Element Web, such as customisation endpoints and modules.
#
# Over time we might expand this config to better support some use cases.
# Watch the release notes for features which might impact this config.
# The modules to install. See ./docs/modules.md for more information on
# what modules are.
#
# The values of this are provided to `yarn add` for inclusion.
modules:
# An example of pulling a module from NPM
- "@vector-im/element-web-ilag-module@^0.0.1"
# An example of pulling a module from local filesystem during development
- "file:/home/user/development/element-web-ilag-module"

View file

@ -1,413 +0,0 @@
# Element Web/Desktop code style guide
This code style applies to projects which the element-web team directly maintains or is reasonably
adjacent to. As of writing, these are:
- element-desktop
- element-web
- matrix-react-sdk
- matrix-js-sdk
Other projects might extend this code style for increased strictness. For example, matrix-events-sdk
has stricter code organization to reduce the maintenance burden. These projects will declare their code
style within their own repos.
Note that some requirements will be layer-specific. Where the requirements don't make sense for the
project, they are used to the best of their ability, used in spirit, or ignored if not applicable,
in that order.
## Guiding principles
1. We want the lint rules to feel natural for most team members. No one should have to think too much
about the linter.
2. We want to stay relatively close to [industry standards](https://google.github.io/styleguide/tsguide.html)
to make onboarding easier.
3. We describe what good code looks like rather than point out bad examples. We do this to avoid
excessively punishing people for writing code which fails the linter.
4. When something isn't covered by the style guide, we come up with a reasonable rule rather than
claim that it "passes the linter". We update the style guide and linter accordingly.
5. While we aim to improve readability, understanding, and other aspects of the code, we deliberately
do not let solely our personal preferences drive decisions.
6. We aim to have an understandable guide.
## Coding practices
1. Lint rules enforce decisions made by this guide. The lint rules and this guide are kept in
perfect sync.
2. Commit messages are descriptive for the changes. When the project supports squash merging,
only the squashed commit needs to have a descriptive message.
3. When there is disagreement with a code style approved by the linter, a PR is opened against
the lint rules rather than making exceptions on the responsible code PR.
4. Rules which are intentionally broken (via eslint-ignore, @ts-ignore, etc) have a comment
included in the immediate vicinity for why. Determination of whether this is valid applies at
code review time.
5. When editing a file, nearby code is updated to meet the modern standards. "Nearby" is subjective,
but should be whatever is reasonable at review time. Such an example might be to update the
class's code style, but not the file's.
1. These changes should be minor enough to include in the same commit without affecting a code
reviewer's job.
## All code
Unless otherwise specified, the following applies to all code:
1. Files must be formatted with Prettier.
2. 120 character limit per line. Match existing code in the file if it is using a lower guide.
3. A tab/indentation is 4 spaces.
4. Newlines are Unix.
5. A file has a single empty line at the end.
6. Lines are trimmed of all excess whitespace, including blank lines.
7. Long lines are broken up for readability.
## TypeScript / JavaScript
1. Write TypeScript. Turn JavaScript into TypeScript when working in the area.
2. Use [TSDoc](https://tsdoc.org/) to document your code. See [Comments](#comments) below.
3. Use named exports.
4. Use semicolons for block/line termination.
1. Except when defining interfaces, classes, and non-arrow functions specifically.
5. When a statement's body is a single line, it must be written without curly braces, so long as the body is placed on
the same line as the statement.
```typescript
if (x) doThing();
```
6. Blocks for `if`, `for`, `switch` and so on must have a space surrounding the condition, but not
within the condition.
```typescript
if (x) {
doThing();
}
```
7. lowerCamelCase is used for function and variable naming.
8. UpperCamelCase is used for general naming.
9. Interface names should not be marked with an uppercase `I`.
10. One variable declaration per line.
11. If a variable is not receiving a value on declaration, its type must be defined.
```typescript
let errorMessage: Optional<string>;
```
12. Objects can use shorthand declarations, including mixing of types.
```typescript
{
room,
prop: this.prop,
}
// ... or ...
{ room, prop: this.prop }
```
13. Object keys should always be non-strings when possible.
```typescript
{
property: "value",
"m.unavoidable": true,
[EventType.RoomMessage]: true,
}
```
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).
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.
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.
1. Note that an explicit type is optional if not expected to be used outside of the function call,
unlike in this example:
```typescript
interface MyObject {
hasString: boolean;
}
type Options = MyObject | string;
function doThing(arg: Options) {
// ...
}
```
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:
```typescript
interface Test {
myCallback: (arg: string) => Promise<void>;
}
```
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
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
of truly optional parameters.
1. A notable exception is when the likelihood of a bug is minimal, such as when a function
takes an argument that is more often not required than required. An example where the
`?` operator is inappropriate is when taking a room ID: typically the caller should
supply the room ID if it knows it, otherwise deliberately acknowledge that it doesn't
have one with `null`.
```typescript
function doThingWithRoom(
thing: string,
room: Optional<string>, // require the caller to specify
) {
// ...
}
```
30. 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:
1. Licence header
2. Imports
3. Constants
4. Enums
5. Interfaces
6. Functions
7. Classes
1. Public/protected/private static properties
2. Public/protected/private properties
3. Constructors
4. Public/protected/private getters & setters
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
of "string: string".
35. 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
```typescript
async function () {
const result = await anotherAsyncFunction();
// ...
}
```
37. Avoid functions whose fundamental behaviour varies with different parameter types.
Multiple return types are fine, but if the function's behaviour is going to change significantly,
have two separate functions. For example, `SDKConfig.get()` with a string param which returns the
type according to the param given is ok, but `SDKConfig.get()` with no args returning the whole
config object would not be: this should just be a separate function.
## React
Inheriting all the rules of TypeScript, the following additionally apply:
1. Types for lifecycle functions are not required (render, componentDidMount, and so on).
2. Class components must always have a `Props` interface declared immediately above them. It can be
empty if the component accepts no props.
3. Class components should have an `State` interface declared immediately above them, but after `Props`.
4. Props and State should not be exported. Use `React.ComponentProps<typeof ComponentNameHere>`
instead.
5. One component per file, except when a component is a utility component specifically for the "primary"
component. The utility component should not be exported.
6. Exported constants, enums, interfaces, functions, etc must be separate from files containing components
or stores.
7. Stores should use a singleton pattern with a static instance property:
```typescript
class FooStore {
public static readonly instance = new FooStore();
// or if the instance can't be created eagerly:
private static _instance: FooStore;
public static get instance(): FooStore {
if (!FooStore._instance) {
FooStore._instance = new FooStore();
}
return FooStore._instance;
}
}
```
8. Stores must support using an alternative MatrixClient and dispatcher instance.
9. Utilities which require JSX must be split out from utilities which do not. This is to prevent import
cycles during runtime where components accidentally include more of the app than they intended.
10. Interdependence between stores should be kept to a minimum. Break functions and constants out to utilities
if at all possible.
11. A component should only use CSS class names in line with the component name.
1. When knowingly using a class name from another component, document it with a [comment](#comments).
12. Curly braces within JSX should be padded with a space, however properties on those components should not.
See above code example.
13. Functions used as properties should either be defined on the class or stored in a variable. They should not
be inline unless mocking/short-circuiting the value.
14. Prefer hooks (functional components) over class components. Be consistent with the existing area if unsure
which should be used.
1. Unless the component is considered a "structure", in which case use classes.
15. Write more views than structures. Structures are chunks of functionality like MatrixChat while views are
isolated components.
16. Components should serve a single, or near-single, purpose.
17. Prefer to derive information from component properties rather than establish state.
18. Do not use `React.Component::forceUpdate`.
## Stylesheets (\*.pcss = PostCSS + Plugins)
Note: We use PostCSS + some plugins to process our styles. It looks like SCSS, but actually it is not.
1. Class names must be prefixed with "mx\_".
2. Class names must denote the component which defines them, followed by any context.
The context is not further specified here in terms of meaning or syntax.
Use whatever is appropriate for your implementation use case.
Some examples:
1. `mx_MyFoo`
2. `mx_MyFoo_avatar`
3. `mx_MyFoo_avatarUser`
4. `mx_MyFoo_avatar--user`
3. Use the `$font` variables instead of manual values.
4. Keep indentation/nesting to a minimum. Maximum suggested nesting is 5 layers.
5. Use the whole class name instead of shortcuts:
```scss
.mx_MyFoo {
& .mx_MyFoo_avatar {
// instead of &_avatar
// ...
}
}
```
6. Break multiple selectors over multiple lines this way:
```scss
.mx_MyFoo,
.mx_MyBar,
.mx_MyFooBar {
// ...
}
```
7. Non-shared variables should use $lowerCamelCase. Shared variables use $dashed-naming.
8. Overrides to Z indexes, adjustments of dimensions/padding with pixels, and so on should all be
[documented](#comments) for what the values mean:
```scss
.mx_MyFoo {
width: calc(100% - 12px); // 12px for read receipts
top: -2px; // visually centred vertically
z-index: 10; // above user avatar, but below dialogs
}
```
9. Avoid the use of `!important`. If `!important` is necessary, add a [comment](#comments) explaining why.
## Tests
1. Tests must be written in TypeScript.
2. Jest mocks are declared below imports, but above everything else.
3. Use the following convention template:
```typescript
// Describe the class, component, or file name.
describe("FooComponent", () => {
// all test inspecific variables go here
beforeEach(() => {
// exclude if not used.
});
afterEach(() => {
// exclude if not used.
});
// Use "it should..." terminology
it("should call the correct API", async () => {
// test-specific variables go here
// function calls/state changes go here
// expectations go here
});
});
// If the file being tested is a utility class:
describe("foo-utils", () => {
describe("firstUtilFunction", () => {
it("should...", async () => {
// ...
});
});
describe("secondUtilFunction", () => {
it("should...", async () => {
// ...
});
});
});
```
## Comments
1. As a general principle: be liberal with comments. This applies to all files: stylesheets as well as
JavaScript/TypeScript.
Good comments not only help future readers understand and maintain the code; they can also encourage good design
by clearly setting out how different parts of the codebase interact where that would otherwise be implicit and
subject to interpretation.
2. Aim to document all types, methods, class properties, functions, etc, with [TSDoc](https://tsdoc.org/) doc comments.
This is _especially_ important for public interfaces in `matrix-js-sdk`, but is good practice in general.
Even very simple interfaces can often benefit from a doc-comment, both as a matter of consistency, and because simple
interfaces have a habit of becoming more complex over time.
3. React components should be documented in the same way as other classes or functions. The documentation should give
a brief description of how the component should be used, and, especially for more complex components, each of its
properties should be clearly documented.
4. Inside a function, there is no need to comment every line, but consider:
- before a particular multiline section of code within the function, give an overview of what it does,
to make it easier for a reader to follow the flow through the function as a whole.
- if it is anything less than obvious, explain _why_ we are doing a particular operation, with particular emphasis
on how this function interacts with other parts of the codebase.
5. When making changes to existing code, authors are expected to read existing comments and make any necessary changes
to ensure they remain accurate.
6. Reviewers are encouraged to consider whether more comments would be useful, and to ask the author to add them.
It is natural for an author to feel that the code they have just written is "obvious" and that comments would be
redundant, whereas in reality it would take some time for reader unfamiliar with the code to understand it. A
reviewer is well-placed to make a more objective judgement.

View file

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

View file

@ -22,28 +22,31 @@
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"default_country_code": "GB",
"show_labs_settings": false,
"features": {},
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"defaultCountryCode": "GB",
"showLabsSettings": false,
"features": { },
"default_federate": true,
"default_theme": "light",
"room_directory": {
"servers": ["matrix.org"]
"roomDirectory": {
"servers": [
"matrix.org"
]
},
"piwik": {
"url": "https://piwik.riot.im/",
"whitelistedHSUrls": ["https://matrix.org"],
"whitelistedISUrls": ["https://vector.im", "https://matrix.org"],
"siteId": 1
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"setting_defaults": {
"settingDefaults": {
"breadcrumbs": true
},
"jitsi": {
"preferred_domain": "meet.element.io"
},
"element_call": {
"url": "https://call.element.io",
"participant_limit": 8,
"brand": "Element Call"
},
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
"preferredDomain": "jitsi.riot.im"
}
}

View file

@ -1,13 +1,17 @@
{
"name": "Element",
"name": "Element",
"description": "A glossy Matrix collaboration client for the web.",
"repository": {
"url": "https://github.com/element-hq/element-web",
"license": "Apache License 2.0"
"url": "https://github.com/vector-im/element-web",
"license": "Apache License 2.0"
},
"bugs": {
"list": "https://github.com/element-hq/element-web/issues",
"report": "https://github.com/element-hq/element-web/issues/new/choose"
"list": "https://github.com/vector-im/element-web/issues",
"report": "https://github.com/vector-im/element-web/issues/new/choose"
},
"keywords": ["chat", "riot", "matrix"]
"keywords": [
"chat",
"riot",
"matrix"
]
}

2
debian/.gitignore vendored
View file

@ -1,2 +0,0 @@
/files
/tmp

1
debian/conffiles vendored
View file

@ -1 +0,0 @@
/etc/element-web/config.json

13
debian/control vendored
View file

@ -1,13 +0,0 @@
Source: element-web
Maintainer: support@element.io
Section: web
Priority: optional
Homepage: https://element.io/
Package: element-web
Architecture: all
Recommends: httpd, element-io-archive-keyring
Description:
A feature-rich client for Matrix.org
This package contains the web-based client that can be served through a web
server.

View file

@ -1,41 +0,0 @@
# Summary
- [Introduction](../README.md)
# Usage
- [Betas](betas.md)
- [Labs](labs.md)
# Setup
- [Install](install.md)
- [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)
- [Release Process](release.md)

View file

@ -1,108 +1,81 @@
# App load order
**Dev note**: As of March 2022, the skin is no longer part of the app load order at all. The document's graphs have
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
- Blue arrow: async task is allowed to settle but allowed to fail
- Red arrow: async task success is asserted
+ Parallelogram: async/await task
+ Box: sync task
+ Diamond: conditional branch
+ Egg: user interaction
+ Blue arrow: async task is allowed to settle but allowed to fail
+ Red arrow: async task success is asserted
Notes:
- A task begins when all its dependencies (arrows going into it) are fulfilled.
- The success of setting up rageshake is never asserted, element-web has a fallback path for running without IDB (and thus rageshake).
- Everything is awaited to be settled before the Modernizr check, to allow it to make use of things like i18n if they are successful.
+ A task begins when all its dependencies (arrows going into it) are fulfilled.
+ The success of setting up rageshake is never asserted, element-web has a fallback path for running without IDB (and thus rageshake).
+ 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

@ -1,14 +0,0 @@
# Beta features
Beta features are features that are not ready for production yet but the team
wants more people to try the features and give feedback on them.
Before a feature gets into its beta phase, it is often a labs feature (see
[Labs](https://github.com/element-hq/element-web/blob/develop/docs/labs.md)).
**Be warned! Beta features may not be completely finalised or stable!**
## Video rooms (`feature_video_rooms`)
Enables support for creating and joining video rooms, which are persistent video
chats that users can jump in and out of.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,81 +0,0 @@
# Choosing an issue to work on
So you want to contribute to Element Web? That is awesome!
If you're not sure where to start, make sure you read
[CONTRIBUTING.md](../CONTRIBUTING.md), and the
[Development](../README.md#development) and
[Setting up a dev environment](../README.md#setting-up-a-dev-environment)
sections of the README.
Maybe you've got something specific you'd like to work on? If so, make sure you
create an issue and
[discuss it with the developers](https://matrix.to/#/#element-dev:matrix.org)
before you put a lot of time into it.
If you're looking for inspiration on where to start, keep reading!
## Finding a good first issue
All the issues for Element Web live in the
[element-web](https://github.com/element-hq/element-web) repository, including
issues that actually need fixing in `matrix-react-sdk` or one of the related
repos.
The first place to look is for
[issues tagged with "good first issue"](https://github.com/element-hq/element-web/issues?q=is%3Aopen+is%3Aissue+label%3A%22good+first+issue%22).
Look through that list and find something that catches your interest. If there
is nothing, there, try gently asking in
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) for
someone to add something.
When you're looking through the list, here are some things that might make an
issue a **GOOD** choice:
- It is a problem or feature you care about.
- It concerns a type of code you know a little about.
- You think you can understand what's needed.
- It already has approval from Element Web's designers (look for comments from
members of the
[Product](https://github.com/orgs/element-hq/teams/product/members) or
[Design](https://github.com/orgs/element-hq/teams/design/members) teams).
Here are some things that might make it a **BAD** choice:
- You don't understand it (maybe add a comment asking a clarifying question).
- It sounds difficult, or is part of a larger change you don't know about.
- **It is tagged with `X-Needs-Design` or `X-Needs-Product`.**
**Element Web's Design and Product teams tend to be very busy**, so if you make
changes that require approval from one of those teams, you will probably have
to wait a very long time. The kind of change affected by this is changing the
way the product works, or how it looks in a specific area.
## Finding a good second issue
Once you've fixed a few small things, you can consider taking on something a
little larger. This should mostly be driven by what you find interesting, but
you may also find the
[Help Wanted](https://github.com/element-hq/element-web/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc+label%3A%22Help+Wanted%22)
label useful.
Note that the same comment applies as in the previous section: if you want to
work in areas that require Design or Product approval, you should look to join
existing work that is already designed, as getting approval for your random
change will take a very long time.
So you should **always avoid issues tagged with `X-Needs-Design` or
`X-Needs-Product`**.
## Asking questions
Feel free to ask questions about the issues or how to choose them in the
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) Matrix
room.
## Thank you
Thank you again for contributing to Element Web. We welcome your contributions
and are grateful for your work. We find working on it great fun, and we hope
you do too!

View file

@ -1,510 +1,170 @@
# Configuration
### 🦖 Deprecation notice
Configuration keys were previously a mix of camelCase and snake_case.
We standardised to snake_case but added compatibility for camelCase to all settings.
This backwards compatibility will be getting removed in a future release so please ensure you are using snake_case.
---
You can configure the app by copying `config.sample.json` to `config.json` or `config.$domain.json` and customising it.
Element will attempt to load first `config.$domain.json` and if it fails `config.json`. This mechanism allows different
configuration options depending on if you're hitting e.g. `app1.example.com` or `app2.example.com`. Configs are not mixed
in any way, it either entirely uses the domain config, or entirely uses `config.json`.
The possible configuration options are described here. If you run into issues, please visit
[#element-web:matrix.org](https://matrix.to/#/#element-web:matrix.org) on Matrix.
For a good example of a production-tuned config, see https://app.element.io/config.json
For an example of a development/beta-tuned config, see https://develop.element.io/config.json
After changing the config, the app will need to be reloaded. For web browsers this is a simple page refresh, however
for the desktop app the application will need to be exited fully (including via the task tray) and re-started.
## Homeserver configuration
In order for Element to even start you will need to tell it what homeserver to connect to _by default_. Users will be
able to use a different homeserver if they like, though this can be disabled with `"disable_custom_urls": true` in your
config.
One of the following options **must** be supplied:
1. `default_server_config`: The preferred method of setting the homeserver connection information. Simply copy/paste
your [`/.well-known/matrix/client`](https://spec.matrix.org/latest/client-server-api/#getwell-knownmatrixclient)
into this field. For example:
```json
{
"default_server_config": {
"m.homeserver": {
"base_url": "https://matrix-client.matrix.org"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
}
}
```
2. `default_server_name`: A different method of connecting to the homeserver by looking up the connection information
using `.well-known`. When using this option, simply use your server's domain name (the part at the end of user IDs):
`"default_server_name": "matrix.org"`
3. <del>`default_hs_url` and (optionally) `default_is_url`</del>: A very deprecated method of defining the connection
information. These are the same values seen as `base_url` in the `default_server_config` example, with `default_is_url`
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.
## Labs flags
Labs flags are optional, typically beta or in-development, features that can be turned on or off. The full range of
labs flags and their development status are documented [here](./labs.md). If interested, the feature flag process is
documented [here](./feature-flags.md).
To force a labs flag on or off, use the following:
```json
{
"features": {
"feature_you_want_to_turn_on": true,
"feature_you_want_to_keep_off": false
}
}
```
If you'd like the user to be able to self-select which labs flags they can turn on, add `"show_labs_settings": true` to
your config. This will turn on the tab in user settings.
**Note**: Feature support varies release-by-release. Check the [labs flag documentation](./labs.md) frequently if enabling
the functionality.
## Default settings
Some settings additionally support being specified at the config level to affect the user experience of your Element Web
instance. As of writing those settings are not fully documented, however a few are:
1. `default_federate`: When `true` (default), rooms will be marked as "federatable" during creation. Typically this setting
shouldn't be used as the federation capabilities of a room **cannot** be changed after the room is created.
2. `default_country_code`: An optional ISO 3166 alpha2 country code (eg: `GB`, the default) to use when showing phone number
inputs.
3. `room_directory`: Optionally defines how the room directory component behaves. Currently only a single property, `servers`
is supported to add additional servers to the dropdown. For example:
```json
{
"room_directory": {
"servers": ["matrix.org", "example.org"]
}
}
```
4. `setting_defaults`: Optional configuration for settings which are not described by this document and support the `config`
level. This list is incomplete. For example:
```json
{
"setting_defaults": {
"MessageComposerInput.showStickersButton": false,
"MessageComposerInput.showPollsButton": false
}
}
```
These values will take priority over the hardcoded defaults for the settings. For a list of available settings, see
[Settings.tsx](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.tsx).
## Customisation & branding
<!-- Author's note: https://english.stackexchange.com/questions/570116/alternative-ways-of-saying-white-labeled -->
Element supports some customisation of the user experience through various branding and theme options. While it doesn't support
complete re-branding/private labeling, a more personalised experience can be achieved for your users.
1. `default_theme`: Typically either `light` (the default) or `dark`, this is the optional name of the colour theme to use.
If using custom themes, this can be a theme name from that as well.
2. `default_device_display_name`: Optional public name for devices created by login and registration, instead of the default
templated string. Note that this option does not support templating, currently.
3. `brand`: Optional name for the app. Defaults to `Element`. This is used throughout the application in various strings/locations.
4. `permalink_prefix`: An optional URL pointing to an Element Web deployment. For example, `https://app.element.io`. This will
change all permalinks (via the "Share" menus) to point at the Element Web deployment rather than `matrix.to`.
5. `desktop_builds`: Optional. Where the desktop builds for the application are, if available. This is explained in more detail
down below.
6. `mobile_builds`: Optional. Like `desktop_builds`, except for the mobile apps. Also described in more detail down below.
7. `mobile_guide_toast`: When `true` (default), users accessing the Element Web instance from a mobile device will be prompted to
download the app instead.
8. `update_base_url`: For the desktop app only, the URL where to acquire update packages. If specified, must be a path to a directory
containing `macos` and `win32` directories, with the update packages within. Defaults to `https://packages.element.io/desktop/update/`
in production.
9. `map_style_url`: Map tile server style URL for location sharing. e.g. `https://api.maptiler.com/maps/streets/style.json?key=YOUR_KEY_GOES_HERE`
This setting is ignored if your homeserver provides `/.well-known/matrix/client` in its well-known location, and the JSON file
at that location has a key `m.tile_server` (or the unstable version `org.matrix.msc3488.tile_server`). In this case, the
configuration found in the well-known location is used instead.
10. `welcome_user_id`: **DEPRECATED** 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.
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
`true` to hide these options.
15. `disable_login_language_selector`: When `false` (default), **enables** the language selector on the login pages. Set to `true`
to hide this dropdown.
16. `disable_guests`: When `false` (default), **enable** guest-related functionality (peeking/previewing rooms, etc) for unregistered
users. Set to `true` to disable this functionality.
17. `user_notice`: Optional notice to show to the user, e.g. for sunsetting a deployment and pushing users to move in their own time.
Takes a configuration object as below:
1. `title`: Required. Title to show at the top of the notice.
2. `description`: Required. The description to use for the notice.
3. `show_once`: Optional. If true then the notice will only be shown once per device.
18. `help_url`: The URL to point users to for help with the app, defaults to `https://element.io/help`.
19. `help_encrption_url`: The URL to point users to for help with encryption, defaults to `https://element.io/help#encryption`.
### `desktop_builds` and `mobile_builds`
These two options describe the various availability for the application. When the app needs to promote an alternative download,
such as trying to get the user to use an Android app or the desktop app for encrypted search, the config options will be looked
at to see if the link should be to somewhere else.
Starting with `desktop_builds`, the following subproperties are available:
1. `available`: Required. When `true`, the desktop app can be downloaded from somewhere.
2. `logo`: Required. A URL to a logo (SVG), intended to be shown at 24x24 pixels.
3. `url`: Required. The download URL for the app. This is used as a hyperlink.
4. `url_macos`: Optional. Direct link to download macOS desktop app.
5. `url_win32`: Optional. Direct link to download Windows 32-bit desktop app.
6. `url_win64`: Optional. Direct link to download Windows 64-bit desktop app.
7. `url_linux`: Optional. Direct link to download Linux desktop app.
When `desktop_builds` is not specified at all, the app will assume desktop downloads are available from https://element.io
For `mobile_builds`, the following subproperties are available:
1. `ios`: The URL for where to download the iOS app, such as an App Store link. When explicitly `null`, the app will assume the
iOS app cannot be downloaded. When not provided, the default Element app will be assumed available.
2. `android`: The same as `ios`, except for Android instead.
3. `fdroid`: The same as `android`, except for FDroid instead.
Together, these two options might look like the following in your config:
```json
{
"desktop_builds": {
"available": true,
"logo": "https://example.org/assets/logo-small.svg",
"url": "https://example.org/not_element/download"
},
"mobile_builds": {
"ios": null,
"android": "https://example.org/not_element/android",
"fdroid": "https://example.org/not_element/fdroid"
}
}
```
### `branding` and `embedded_pages`
These two options point at various URLs for changing different internal pages (like the welcome page) and logos within the
application.
Starting with `branding`, the following subproperties are available:
1. `welcome_background_url`: When a string, the URL for the full-page image background of the login, registration, and welcome
pages. This property can additionally be an array to have the app choose an image at random from the selections.
2. `auth_header_logo_url`: A URL to the logo used on the login, registration, etc pages.
3. `auth_footer_links`: A list of links to add to the footer during login, registration, etc. Each entry must have a `text` and
`url` property.
`embedded_pages` can be configured as such:
1. `welcome_url`: A URL to an HTML page to show as a welcome page (landing on `#/welcome`). When not specified, the default
`welcome.html` that ships with Element will be used instead.
2. `home_url`: A URL to an HTML page to show within the app as the "home" page. When the app doesn't have a room/screen to
show the user, it will use the home page instead. The home page is additionally accessible from the user menu. By default,
no home page is set and therefore a hardcoded landing screen is used. More documentation and examples are [here](./custom-home.md).
3. `login_for_welcome`: When `true` (default `false`), the app will use the login form as a welcome page instead of the welcome
page itself. This disables use of `welcome_url` and all welcome page functionality.
Together, the options might look like this in your config:
```json
{
"branding": {
"welcome_background_url": "https://example.org/assets/background.jpg",
"auth_header_logo_url": "https://example.org/assets/logo.svg",
"auth_footer_links": [
{ "text": "FAQ", "url": "https://example.org/faq" },
{ "text": "Donate", "url": "https://example.org/donate" }
]
},
"embedded_pages": {
"welcome_url": "https://example.org/assets/welcome.html",
"home_url": "https://example.org/assets/home.html"
}
}
```
Note that `index.html` also has an og:image meta tag that is set to an image hosted on element.io. This is the image used if
links to your copy of Element appear in some websites like Facebook, and indeed Element itself. This has to be static in the HTML
and an absolute URL (and HTTP rather than HTTPS), so it's not possible for this to be an option in config.json. If you'd like to
change it, you can build Element, but run `RIOT_OG_IMAGE_URL="http://example.com/logo.png" yarn build`. Alternatively, you can edit
the `og:image` meta tag in `index.html` directly each time you download a new version of Element.
## SSO setup
When Element is deployed alongside a homeserver with SSO-only login, some options to ease the user experience might want to be set:
1. `logout_redirect_url`: Optional URL to redirect the user to after they have logged out. Some SSO systems support a page that the
user can be sent to in order to log them out of that system too, making logout symmetric between Element and the SSO system.
2. `sso_redirect_options`: Options to define how to handle unauthenticated users. If the object contains `"immediate": true`, then
all unauthenticated users will be automatically redirected to the SSO system to start their login. If instead you'd only like to
have users which land on the welcome page to be redirected, use `"on_welcome_page": true`. Additionally, there is an option to
redirect anyone landing on the login page, by using `"on_login_page": true`. As an example:
```json
{
"sso_redirect_options": {
"immediate": false,
"on_welcome_page": true,
"on_login_page": true
}
}
```
It is most common to use the `immediate` flag instead of `on_welcome_page`.
## Native OIDC
Native OIDC support is currently in labs and is subject to change.
Static OIDC Client IDs are preferred and can be specified under `oidc_static_clients` as a mapping from `issuer` to configuration object containing `client_id`.
Issuer must have a trailing forward slash. As an example:
```json
{
"oidc_static_clients": {
"https://auth.example.com/": {
"client_id": "example-client-id"
}
}
}
```
If a matching static client is not found, the app will attempt to dynamically register a client using metadata specified under `oidc_metadata`.
The app has sane defaults for the metadata properties below but on stricter policy identity providers they may not pass muster, e.g. `contacts` may be required.
The following subproperties are available:
1. `client_uri`: This is the base URI for the OIDC client registration, typically `logo_uri`, `tos_uri`, and `policy_uri` must be either on the same domain or a subdomain of this URI.
2. `logo_uri`: Optional URI for the client logo.
3. `tos_uri`: Optional URI for the client's terms of service.
4. `policy_uri`: Optional URI for the client's privacy policy.
5. `contacts`: Optional list of contact emails for the client.
As an example:
```json
{
"oidc_metadata": {
"client_uri": "https://example.com",
"logo_uri": "https://example.com/logo.png",
"tos_uri": "https://example.com/tos",
"policy_uri": "https://example.com/policy",
"contacts": ["support@example.com"]
}
}
```
## VoIP / Jitsi calls
Currently, Element uses Jitsi to offer conference calls in rooms, with an experimental Element Call implementation in the works.
A set of defaults are applied, pointing at our Jitsi and Element Call instances, to ensure conference calling works, however you
can point Element at your own if you prefer.
More information about the Jitsi setup can be found [here](./jitsi.md).
The VoIP and Jitsi options are:
1. `jitsi`: Optional configuration for how to start Jitsi conferences. Currently can only contain a single `preferred_domain`
value which points at the domain of the Jitsi instance. Defaults to `meet.element.io`. This is _not_ used if the Jitsi widget
was created by an integration manager, or if the homeserver provides Jitsi information in `/.well-known/matrix/client`. For
example:
```json
{
"jitsi": {
"preferred_domain": "meet.jit.si"
}
}
```
2. `jitsi_widget`: Optional configuration for the built-in Jitsi widget. Currently can only contain a single `skip_built_in_welcome_screen`
value, denoting whether the "Join Conference" button should be shown. When `true` (default `false`), Jitsi calls will skip to
the call instead of having a screen with a single button on it. This is most useful if the Jitsi instance being used already
has a landing page for users to test audio and video before joining the call, otherwise users will automatically join the call.
For example:
```json
{
"jitsi_widget": {
"skip_built_in_welcome_screen": true
}
}
```
3. `voip`: Optional configuration for various VoIP features. Currently can only contain a single `obey_asserted_identity` value to
send MSC3086-style asserted identity messages during VoIP calls in the room corresponding to the asserted identity. This _must_
only be set in trusted environments. The option defaults to `false`. For example:
```json
{
"voip": {
"obey_asserted_identity": false
}
}
```
4. `widget_build_url`: Optional URL to have Element make a request to when a user presses the voice/video call buttons in the app,
if a call would normally be started by the action. The URL will be called with a `roomId` query parameter to identify the room
being called in. The URL must respond with a JSON object similar to the following:
```json
{
"widget_id": "$arbitrary_string",
"widget": {
"creatorUserId": "@user:example.org",
"id": "$the_same_widget_id",
"type": "m.custom",
"waitForIframeLoad": true,
"name": "My Widget Name Here",
"avatar_url": "mxc://example.org/abc123",
"url": "https://example.org/widget.html",
"data": {
"title": "Subtitle goes here"
}
},
"layout": {
"container": "top",
"index": 0,
"width": 65,
"height": 50
}
}
```
The `widget` is the `content` of a normal widget state event. The `layout` is the layout specifier for the widget being created,
as defined by the `io.element.widgets.layout` state event. By default this applies to all rooms, but the behaviour can be skipped for
2-person rooms, causing Element to fall back to 1:1 VoIP, by setting the option `widget_build_url_ignore_dm` to `true`.
5. `audio_stream_url`: Optional URL to pass to Jitsi to enable live streaming. This option is considered experimental and may be removed
at any time without notice.
6. `element_call`: Optional configuration for native group calls using Element Call, with the following subkeys:
- `url`: The URL of the Element Call instance to use for native group calls. This option is considered experimental
and may be removed at any time without notice. Defaults to `https://call.element.io`.
- `use_exclusively`: A boolean specifying whether Element Call should be used exclusively as the only VoIP stack in
the app, removing the ability to start legacy 1:1 calls or Jitsi calls. Defaults to `false`.
- `participant_limit`: The maximum number of users who can join a call; if
this number is exceeded, the user will not be able to join a given call.
- `brand`: Optional name for the app. Defaults to `Element Call`. This is
used throughout the application in various strings/locations.
- `guest_spa_url`: Optional URL for an Element Call single-page app (SPA),
for guest links. If this is set, Element Web will expose a "join" link
for public video rooms, which can then be shared to non-matrix users.
The target Element Call SPA is typically set up to use a homeserver that
allows users to register without email ("passwordless guest users") and to
federate.
## Bug reporting
If you run your own rageshake server to collect bug reports, the following options may be of interest:
1. `bug_report_endpoint_url`: URL for where to submit rageshake logs to. Rageshakes include feedback submissions and bug reports. When
not present in the config, the app will disable all rageshake functionality. Set to `https://element.io/bugreports/submit` to submit
rageshakes to us, or use your own rageshake server.
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:
1. `dsn`: The Sentry [DSN](https://docs.sentry.io/product/sentry-basics/dsn-explainer/).
2. `environment`: Optional [environment](https://docs.sentry.io/product/sentry-basics/environments/) to pass to Sentry.
For example:
```json
{
"sentry": {
"dsn": "dsn-goes-here",
"environment": "production"
}
}
```
## Integration managers
Integration managers are embedded applications within Element to help the user configure bots, bridges, and widgets. An integration manager
is a separate piece of software not typically available with your homeserver. To disable integrations, set the options defined here to `null`.
1. `integrations_ui_url`: The UI URL for the integration manager.
2. `integrations_rest_url`: The REST interface URL for the integration manager.
3. `integrations_widgets_urls`: A list of URLs the integration manager uses to host widgets.
If you would like to use Scalar, the integration manager maintained by Element, the following options would apply:
```json
{
"integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
]
}
```
## Administrative options
If you would like to include a custom message when someone is reporting an event, set the following Markdown-capable field:
```json
{
"report_event": {
"admin_message_md": "Please be sure to review our [terms of service](https://example.org/terms) before reporting a message."
}
}
```
To add additional "terms and conditions" links throughout the app, use the following template:
```json
{
"terms_and_conditions_links": [{ "text": "Code of conduct", "url": "https://example.org/code-of-conduct" }]
}
```
## Analytics
To configure [Posthog](https://posthog.com/), add the following under `posthog` in your config:
1. `api_host`: The hostname of the posthog server.
2. `project_api_key`: The API key from posthog.
When these configuration options are not present,
analytics are deemed impossible and the user won't be asked to opt in to the system.
There are additional root-level options which can be specified:
1. `analytics_owner`: the company name used in dialogs talking about analytics - this defaults to `brand`,
and is useful when the provider of analytics is different from the provider of the Element instance.
2. `privacy_policy_url`: URL to the privacy policy including the analytics collection policy.
## Miscellaneous
Element supports other options which don't quite fit into other sections of this document.
To configure whether presence UI is shown for a given homeserver, set `enable_presence_by_hs_url`. It is recommended to
set this value to the following at a minimum:
```json
{
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
}
}
```
## Identity servers
Configuration
=============
You can configure the app by copying `config.sample.json` to
`config.json` and customising it:
For a good example, see https://develop.element.io/config.json.
1. `default_server_config` sets the default homeserver and identity server URL for
Element to use. The object is the same as returned by [https://<server_name>/.well-known/matrix/client](https://matrix.org/docs/spec/client_server/latest.html#get-well-known-matrix-client),
with added support for a `server_name` under the `m.homeserver` section to display
a custom homeserver name. Alternatively, the config can contain a `default_server_name`
instead which is where Element will go to get that same object, although this option is
deprecated - see the `.well-known` link above for more information on using this option.
Note that the `default_server_name` is used to get a complete server configuration
whereas the `server_name` in the `default_server_config` is for display purposes only.
* *Note*: The URLs can also be individually specified as `default_hs_url` and
`default_is_url`, however these are deprecated. They are maintained for backwards
compatibility with older configurations. `default_is_url` is respected only
if `default_hs_url` is used.
* Element will fail to load if a mix of `default_server_config`, `default_server_name`, or
`default_hs_url` is specified. When multiple sources are specified, it is unclear
which should take priority and therefore the application cannot continue.
* As of Element 1.4.0, identity servers are optional. See [Identity servers](#identity-servers) below.
1. `sso_redirect_options`: Optionally defines how Element will behave with a server which supports
Single Sign On (SSO). By default, Element will do nothing special and simply show a button where
needed for the user to click to navigate to the SSO system. This behaviour can be tuned with the
config options below (as properties of the `sso_redirect_options` object). None of the options apply
if Element thinks the user is already logged in, and similarly Element will assume the default server
supports SSO if these redirect options are used.
* `immediate`: When `true` (default `false`), Element will automatically redirect all unauthenticated
users to the SSO system to log in regardless of how they reached the app. This overrides the use of
other redirect options.
* `on_welcome_page`: When `true` (default `false`), Element will automatically redirect all unauthenticated
users to the SSO to log in if the user lands on the welcome page or no specific page. For example,
https://app.element.io/#/welcome and https://app.element.io would redirect if set up to use this option.
This can be useful to maintain guest experience until an account is needed.
1. `features`: Lookup of optional features that may be force-enabled (`true`) or force-disabled (`false`).
When features are not listed here, their defaults will be used, and users can turn them on/off if `showLabsSettings`
allows them to. The available optional experimental features vary from release to release and are
[documented](labs.md). The feature flag process is [documented](feature-flags.md) as well.
1. `showLabsSettings`: Shows the "labs" tab of user settings. Useful to allow users to turn on experimental features
they might not otherwise have access to.
1. `brand`: String to pass to your homeserver when configuring email notifications, to let the
homeserver know what email template to use when talking to you.
1. `branding`: Configures various branding and logo details, such as:
1. `welcomeBackgroundUrl`: An image to use as a wallpaper outside the app
during authentication flows. If an array is passed, an image is chosen randomly for each visit.
1. `authHeaderLogoUrl`: An logo image that is shown in the header during
authentication flows
1. `authFooterLinks`: a list of links to show in the authentication page footer:
`[{"text": "Link text", "url": "https://link.target"}, {"text": "Other link", ...}]`
1. `reportEvent`: Configures the dialog for reporting content to the homeserver
admin.
1. `adminMessageMD`: An extra message to show on the reporting dialog to
mention homeserver-specific policies. Accepts Markdown.
1. `integrations_ui_url`: URL to the web interface for the integrations server. The integrations
server is not Element and normally not your homeserver either. The integration server settings
may be left blank to disable integrations.
1. `integrations_rest_url`: URL to the REST interface for the integrations server.
1. `integrations_widgets_urls`: list of URLs to the REST interface for the widget integrations server.
1. `bug_report_endpoint_url`: endpoint to send bug reports to (must be running a
https://github.com/matrix-org/rageshake server). Bug reports are sent when a user clicks
"Send Logs" within the application. Bug reports can be disabled/hidden by leaving the
`bug_report_endpoint_url` out of your config file.
1. `roomDirectory`: config for the public room directory. This section is optional.
1. `roomDirectory.servers`: List of other homeservers' directories to include in the drop
down list. Optional.
1. `default_theme`: name of theme to use by default (e.g. 'light')
1. `update_base_url` (electron app only): HTTPS URL to a web server to download
updates from. This should be the path to the directory containing `macos`
and `win32` (for update packages, not installer packages).
1. `piwik`: Analytics can be disabled by setting `piwik: false` or by leaving the piwik config
option out of your config file. If you want to enable analytics, set `piwik` to be an object
containing the following properties:
1. `url`: The URL of the Piwik instance to use for collecting analytics
1. `whitelistedHSUrls`: a list of HS URLs to not redact from the analytics
1. `whitelistedISUrls`: a list of IS URLs to not redact from the analytics
1. `siteId`: The Piwik Site ID to use when sending analytics to the Piwik server configured above
1. `welcomeUserId`: the user ID of a bot to invite whenever users register that can give them a tour
1. `embeddedPages`: Configures the pages displayed in portions of Element that
embed static files, such as:
1. `welcomeUrl`: Initial content shown on the outside of the app when not
logged in. Defaults to `welcome.html` supplied with Element.
1. `homeUrl`: Content shown on the inside of the app when a specific room is
not selected. By default, no home page is configured. If one is set, a
button to access it will be shown in the top left menu.
1. `loginForWelcome`: Overrides `welcomeUrl` to make the welcome page be the
same page as the login page when `true`. This effectively disables the
welcome page.
1. `defaultCountryCode`: The ISO 3166 alpha2 country code to use when showing
country selectors, like the phone number input on the registration page.
Defaults to `GB` if the given code is unknown or not provided.
1. `settingDefaults`: Defaults for settings that support the `config` level,
as an object mapping setting name to value (note that the "theme" setting
is special cased to the `default_theme` in the config file).
1. `disable_custom_urls`: disallow the user to change the
default homeserver when signing up or logging in.
1. `permalinkPrefix`: Used to change the URL that Element generates permalinks with.
By default, this is "https://matrix.to" to generate matrix.to (spec) permalinks.
Set this to your Element instance URL if you run an unfederated server (eg:
"https://element.example.org").
1. `jitsi`: Used to change the default conference options. Learn more about the
Jitsi options at [jitsi.md](./jitsi.md).
1. `preferredDomain`: The domain name of the preferred Jitsi instance. Defaults
to `jitsi.riot.im`. This is used whenever a user clicks on the voice/video
call buttons - integration managers may use a different domain.
1. `enable_presence_by_hs_url`: The property key should be the URL of the homeserver
and its value defines whether to enable/disable the presence status display
from that homeserver. If no options are configured, presence is shown for all
homeservers.
1. `disable_guests`: Disables guest access tokens and auto-guest registrations.
Defaults to false (guests are allowed).
1. `disable_login_language_selector`: Disables the login language selector. Defaults
to false (language selector is shown).
1. `disable_3pid_login`: Disables 3rd party identity options on login and registration form
Defaults to false (3rd party identity options are shown).
1. `default_federate`: Default option for room federation when creating a room
Defaults to true (room federation enabled).
1. `desktopBuilds`: Used to alter promotional links to the desktop app. By default
the builds are considered available and accessible from https://element.io. This
config option is typically used in the context of encouraging encrypted message
search capabilities (Seshat). All the options listed below are required if this
option is specified.
1. `available`: When false, the desktop app will not be promoted to the user.
1. `logo`: An HTTP URL to the avatar for the desktop build. Should be 24x24, ideally
an SVG.
1. `url`: An HTTP URL for where to send the user to download the desktop build.
1. `mobileBuilds`: Used to alter promotional links to the mobile app. By default the
builds are considered available and accessible from https://element.io. This config
option is typically used in a context of encouraging the user to try the mobile app
instead of a mobile/incompatible browser.
1. `ios`: The URL to the iOS build. If `null`, it will be assumed to be not available.
If not set, the default element.io builds will be used.
1. `android`: The URL to the Android build. If `null`, it will be assumed to be not available.
If not set, the default element.io builds will be used.
1. `fdroid`: The URL to the FDroid build. If `null`, it will be assumed to be not available.
If not set, the default element.io builds will be used.
1. `mobileGuideToast`: Whether to show a toast a startup which nudges users on
iOS and Android towards the native mobile apps. The toast redirects to the
mobile guide if they accept. Defaults to false.
1. `audioStreamUrl`: If supplied, show an option on Jitsi widgets to stream
audio using Jitsi's live streaming feature. This option is experimental and
may be removed at any time without notice.
1. `voip`: Behaviour related to calls
1. `obeyAssertedIdentity`: If set, MSC3086 asserted identity messages sent
on VoIP calls will cause the call to appear in the room corresponding to the
asserted identity. This *must* only be set in trusted environments.
1. `posthog`: [Posthog](https://posthog.com/) integration config. If not set, Posthog analytics are disabled.
1. `projectApiKey`: The Posthog project API key
2. `apiHost`: The Posthog API host
1. `sentry`: [Sentry](https://sentry.io/) configuration for rageshake data being sent to sentry.
1. `dsn`: the Sentry [DSN](https://docs.sentry.io/product/sentry-basics/dsn-explainer/)
2. `environment`: (optional) The [Environment](https://docs.sentry.io/product/sentry-basics/environments/) to pass to sentry
Note that `index.html` also has an og:image meta tag that is set to an image
hosted on riot.im. This is the image used if links to your copy of Element
appear in some websites like Facebook, and indeed Element itself. This has to be
static in the HTML and an absolute URL (and HTTP rather than HTTPS), so it's
not possible for this to be an option in config.json. If you'd like to change
it, you can build Element, but run
`RIOT_OG_IMAGE_URL="http://example.com/logo.png" yarn build`.
Alternatively, you can edit the `og:image` meta tag in `index.html` directly
each time you download a new version of Element.
Identity servers
================
The identity server is used for inviting other users to a room via third party
identifiers like emails and phone numbers. It is not used to store your password
@ -517,8 +177,8 @@ Element will check multiple sources when looking for an identity server to use i
the following order of preference:
1. The identity server set in the user's account data
- For a new user, no value is present in their account data. It is only set
if the user visits Settings and manually changes their identity server.
* For a new user, no value is present in their account data. It is only set
if the user visits Settings and manually changes their identity server.
2. The identity server provided by the `.well-known` lookup that occurred at
login
3. The identity server provided by the Riot config file
@ -531,58 +191,48 @@ Currently, the only two public identity servers are https://vector.im and
https://matrix.org, however in the future identity servers will be
decentralised.
## Desktop app configuration
Desktop app configuration
=========================
See https://github.com/element-hq/element-desktop#user-specified-configjson
See https://github.com/vector-im/element-desktop#user-specified-configjson
## UI Features
UI Features
===========
Parts of the UI can be disabled using UI features. These are settings which appear
under `setting_defaults` and can only be `true` (default) or `false`. When `false`,
under `settingDefaults` and can only be `true` (default) or `false`. When `false`,
parts of the UI relating to that feature will be disabled regardless of the user's
preferences.
Currently, the following UI feature flags are supported:
- `UIFeature.urlPreviews` - Whether URL previews are enabled across the entire application.
- `UIFeature.feedback` - Whether prompts to supply feedback are shown.
- `UIFeature.voip` - Whether or not VoIP is shown readily to the user. When disabled,
Jitsi widgets will still work though they cannot easily be added.
- `UIFeature.widgets` - Whether or not widgets will be shown.
- `UIFeature.advancedSettings` - Whether or not sections titled "advanced" in room and
user settings are shown to the user.
- `UIFeature.shareQrCode` - Whether or not the QR code on the share room/event dialog
is shown.
- `UIFeature.shareSocial` - Whether or not the social icons on the share room/event dialog
are shown.
- `UIFeature.identityServer` - Whether or not functionality requiring an identity server
is shown. When disabled, the user will not be able to interact with the identity
server (sharing email addresses, 3PID invites, etc).
- `UIFeature.thirdPartyId` - Whether or not UI relating to third party identifiers (3PIDs)
is shown. Typically this is considered "contact information" on the homeserver, and is
not directly related to the identity server.
- `UIFeature.registration` - Whether or not the registration page is accessible. Typically
useful if accounts are managed externally.
- `UIFeature.passwordReset` - Whether or not the password reset page is accessible. Typically
useful if accounts are managed externally.
- `UIFeature.deactivate` - Whether or not the deactivate account button is accessible. Typically
useful if accounts are managed externally.
- `UIFeature.advancedEncryption` - Whether or not advanced encryption options are shown to the
user.
- `UIFeature.roomHistorySettings` - Whether or not the room history settings are shown to the user.
This should only be used if the room history visibility options are managed by the server.
- `UIFeature.TimelineEnableRelativeDates` - Display relative date separators (eg: 'Today', 'Yesterday') in the
timeline for recent messages. When false day dates will be used.
- `UIFeature.BulkUnverifiedSessionsReminder` - Display popup reminders to verify or remove unverified sessions. Defaults
to true.
- `UIFeature.locationSharing` - Whether or not location sharing menus will be shown.
## Undocumented / developer options
The following are undocumented or intended for developer use only.
1. `fallback_hs_url`
2. `sync_timeline_limit`
3. `dangerously_allow_unsafe_and_insecure_passwords`
4. `latex_maths_delims`: An optional setting to override the default delimiters used for maths parsing. See https://github.com/matrix-org/matrix-react-sdk/pull/5939 for details. Only used when `feature_latex_maths` is enabled.
5. `voice_broadcast.chunk_length`: Target chunk length in seconds for the Voice Broadcast feature currently under development.
* `UIFeature.urlPreviews` - Whether URL previews are enabled across the entire application.
* `UIFeature.feedback` - Whether prompts to supply feedback are shown.
* `UIFeature.voip` - Whether or not VoIP is shown readily to the user. When disabled,
Jitsi widgets will still work though they cannot easily be added.
* `UIFeature.widgets` - Whether or not widgets will be shown.
* `UIFeature.flair` - Whether or not community flair is shown in rooms.
* `UIFeature.communities` - Whether or not to show any UI related to communities. Implicitly
disables `UIFeature.flair` when disabled.
* `UIFeature.advancedSettings` - Whether or not sections titled "advanced" in room and
user settings are shown to the user.
* `UIFeature.shareQrCode` - Whether or not the QR code on the share room/event dialog
is shown.
* `UIFeature.shareSocial` - Whether or not the social icons on the share room/event dialog
are shown.
* `UIFeature.identityServer` - Whether or not functionality requiring an identity server
is shown. When disabled, the user will not be able to interact with the identity
server (sharing email addresses, 3PID invites, etc).
* `UIFeature.thirdPartyId` - Whether or not UI relating to third party identifiers (3PIDs)
is shown. Typically this is considered "contact information" on the homeserver, and is
not directly related to the identity server.
* `UIFeature.registration` - Whether or not the registration page is accessible. Typically
useful if accounts are managed externally.
* `UIFeature.passwordReset` - Whether or not the password reset page is accessible. Typically
useful if accounts are managed externally.
* `UIFeature.deactivate` - Whether or not the deactivate account button is accessible. Typically
useful if accounts are managed externally.
* `UIFeature.advancedEncryption` - Whether or not advanced encryption options are shown to the
user.
* `UIFeature.roomHistorySettings` - Whether or not the room history settings are shown to the user.
This should only be used if the room history visibility options are managed by the server.

View file

@ -1,63 +0,0 @@
# Custom Home Page
The home page is shown whenever the user is logged in, but no room is selected.
A custom `home.html` replacing the default home page can be configured either in `.well-known/matrix/client` or `config.json`.
Such a custom home page can be used to communicate helpful information and important rules to the users.
## Configuration
To provide a custom home page for all element-web/desktop users of a homeserver, include the following in `.well-known/matrix/client`:
```
{
"io.element.embedded_pages": {
"home_url": "https://example.org/home.html"
}
}
```
The home page can be overridden in `config.json` to provide all users of an element-web installation with the same experience:
```
{
"embeddedPages": {
"homeUrl": "https://example.org/home.html"
}
}
```
## `home.html` Example
The following is a simple example for a custom `home.html`:
```
<style type="text/css">
.tos {
width: auto;
color: black;
background : #ffcccb;
font-weight: bold;
}
</style>
<h1>The example.org Matrix Server</h1>
<div class="tos">
<p>Behave appropriately.</p>
</div>
<h2>Start Chatting</h2>
<ul>
<li><a href="#/dm">Send a Direct Message</a></li>
<li><a href="#/directory">Explore Public Rooms</a></li>
<li><a href="#/new">Create a Group Chat</a></li>
</ul>
```
When choosing colors, be aware that the home page may be displayed in either light or dark mode.
It may be needed to set CORS headers for the `home.html` to enable element-desktop to fetch it, with e.g., the following nginx config:
```
add_header Access-Control-Allow-Origin *;
```

View file

@ -1,13 +1,5 @@
# Customisations
### 🦖 DEPRECATED
Customisations have been deprecated in favour of the [Module API](https://github.com/element-hq/element-web/blob/develop/docs/modules.md).
If you have use cases from customisations which are not yet available via the Module API please open an issue.
Customisations will be removed from the codebase in a future release.
---
Element Web and the React SDK support "customisation points" that can be used to
easily add custom logic specific to a particular deployment of Element Web.
@ -24,56 +16,19 @@ the React SDK, you can still override it from the Element Web layer:
`element-web/src/customisations/YourNameSecurity.ts`
2. Edit customisations points and make sure export the ones you actually want to
activate
3. Create/add an entry to `customisations.json` next to the webpack config:
3. Tweak the Element build process to use the customised module instead of the
default by adding this to the `additionalPlugins` array in `webpack.config.js`:
```json
{
"src/customisations/Security.ts": "src/customisations/YourNameSecurity.ts"
}
```js
new webpack.NormalModuleReplacementPlugin(
/src[\/\\]customisations[\/\\]Security\.ts/,
path.resolve(__dirname, 'src/customisations/YourNameSecurity.ts'),
),
```
If we add more customisation modules in the future, we'll likely improve these
steps to remove the need for build changes like the above.
By isolating customisations to their own module, this approach should remove the
chance of merge conflicts when updating your fork, and thus simplify ongoing
maintenance.
**Note**: The project deliberately does not exclude `customisations.json` from Git.
This is to ensure that in shared projects it's possible to have a common config. By
default, Element Web does _not_ ship with this file to prevent conflicts.
### Custom components
Maintainers can use the above system to override components if they wish. Maintenance and API surface compatibility are
left as a responsibility for the project - the layering in Element Web (including the react-sdk) do not make guarantees
that properties/state machines won't change.
### Component visibility customisation
UI for some actions can be hidden via the ComponentVisibility customisation:
- inviting users to rooms and spaces,
- creating rooms,
- creating spaces,
To customise visibility create a customisation module from [ComponentVisibility](https://github.com/matrix-org/matrix-react-sdk/blob/master/src/customisations/ComponentVisibility.ts) following the instructions above.
`shouldShowComponent` determines whether the active MatrixClient user should be able to use
the given UI component. When `shouldShowComponent` returns falsy all UI components for that feature will be hidden.
If shown, the user might still not be able to use the
component depending on their contextual permissions. For example, invite options
might be shown to the user, but they won't have permission to invite users to
the current room: the button will appear disabled.
For example, to only allow users who meet a certain condition to create spaces:
```typescript
function shouldShowComponent(component: UIComponent): boolean {
if (component === UIComponent.CreateSpaces) {
// customConditionCheck() is a function of your own creation
const userMeetsCondition = customConditionCheck(MatrixClientPeg.get().getUserId());
return userMeetsCondition;
}
return true;
}
```
In this example, all UI related to creating a space will be hidden unless the users meets the custom condition.

View file

@ -10,34 +10,12 @@ Set the following on your homeserver's
```json
{
"io.element.e2ee": {
"default": false
}
"io.element.e2ee": {
"default": false
}
}
```
## Disabling encryption
Set the following on your homeserver's
`/.well-known/matrix/client` config:
```json
{
"io.element.e2ee": {
"force_disable": true
}
}
```
When `force_disable` is true:
- all rooms will be created with encryption disabled, and it will not be possible to enable
encryption from room settings.
- 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.
# Secure backup
By default, Element strongly encourages (but does not require) users to set up
@ -51,9 +29,9 @@ following on your homeserver's `/.well-known/matrix/client` config:
```json
{
"io.element.e2ee": {
"secure_backup_required": true
}
"io.element.e2ee": {
"secure_backup_required": true
}
}
```
@ -66,9 +44,9 @@ only offer one of these, you can signal this via the
```json
{
"io.element.e2ee": {
"secure_backup_setup_methods": ["passphrase"]
}
"io.element.e2ee": {
"secure_backup_setup_methods": ["passphrase"]
}
}
```

View file

@ -5,10 +5,10 @@ flexibility and control over when and where those features are enabled.
For example, flags make the following things possible:
- Extended testing of a feature via labs on develop
- Enabling features when ready instead of the first moment the code is released
- Testing a feature with a specific set of users (by enabling only on a specific
Element instance)
* Extended testing of a feature via labs on develop
* Enabling features when ready instead of the first moment the code is released
* Testing a feature with a specific set of users (by enabling only on a specific
Element instance)
The size of the feature controlled by a feature flag may vary widely: it could
be a large project like reactions or a smaller change to an existing algorithm.
@ -35,9 +35,8 @@ clients commit to doing the associated clean up work once a feature stabilises.
When starting work on a feature, we should create a matching feature flag:
1. Add a new
[setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.tsx)
[setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.ts)
of the form:
```js
"feature_cats": {
isFeature: true,
@ -46,14 +45,11 @@ When starting work on a feature, we should create a matching feature flag:
default: false,
},
```
2. Check whether the feature is enabled as appropriate:
```js
SettingsStore.getValue("feature_cats");
SettingsStore.getValue("feature_cats")
```
3. Document the feature in the [labs documentation](https://github.com/element-hq/element-web/blob/develop/docs/labs.md)
3. Document the feature in the [labs documentation](https://github.com/vector-im/element-web/blob/develop/docs/labs.md)
With these steps completed, the feature is disabled by default, but can be
enabled on develop and nightly by interested users for testing.
@ -64,9 +60,9 @@ The following lists a few common options.
## Enabling by default on develop and nightly
Set the feature to `true` in the
[develop](https://github.com/element-hq/element-web/blob/develop/element.io/develop/config.json)
[develop](https://github.com/vector-im/element-web/blob/develop/element.io/develop/config.json)
and
[nightly](https://github.com/element-hq/element-desktop/blob/develop/element.io/nightly/config.json)
[nightly](https://github.com/vector-im/element-desktop/blob/develop/element.io/nightly/config.json)
configs:
```json
@ -78,36 +74,34 @@ configs:
## Enabling by default on staging, app, and release
Set the feature to `true` in the
[staging / app](https://github.com/element-hq/element-web/blob/develop/element.io/app/config.json)
[staging / app](https://github.com/vector-im/element-web/blob/develop/element.io/app/config.json)
and
[release](https://github.com/element-hq/element-desktop/blob/develop/element.io/release/config.json)
[release](https://github.com/vector-im/element-desktop/blob/develop/element.io/release/config.json)
configs.
**Note:** The above will only enable the feature for https://app.element.io and official Element
Desktop builds. It will not be enabled for self-hosted installed, custom desktop builds, etc. To
cover these cases, change the setting's `default` in `Settings.tsx` to `true`.
cover these cases, change the setting's `default` in `Settings.ts` to `true`.
## Feature deployed successfully
Once we're confident that a feature is working well, we should remove or convert the flag.
If the feature is meant to be turned off/on by the user:
1. Remove `isFeature` from the [setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.ts)
2. Change the `default` to `true` (if desired).
3. Remove the feature from the [labs documentation](https://github.com/element-hq/element-web/blob/develop/docs/labs.md)
3. Remove the feature from the [labs documentation](https://github.com/vector-im/element-web/blob/develop/docs/labs.md)
4. Celebrate! 🥳
If the feature is meant to be forced on (non-configurable):
1. Remove the [setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.ts)
2. Remove all `getValue` lines that test for the feature.
3. Remove the feature from the [labs documentation](https://github.com/element-hq/element-web/blob/develop/docs/labs.md)
3. Remove the feature from the [labs documentation](https://github.com/vector-im/element-web/blob/develop/docs/labs.md)
4. If applicable, remove the feature state from
[develop](https://github.com/element-hq/element-web/blob/develop/element.io/develop/config.json),
[nightly](https://github.com/element-hq/element-desktop/blob/develop/element.io/nightly/config.json),
[staging / app](https://github.com/element-hq/element-web/blob/develop/element.io/app/config.json),
[develop](https://github.com/vector-im/element-web/blob/develop/element.io/develop/config.json),
[nightly](https://github.com/vector-im/element-desktop/blob/develop/element.io/nightly/config.json),
[staging / app](https://github.com/vector-im/element-web/blob/develop/element.io/app/config.json),
and
[release](https://github.com/element-hq/element-desktop/blob/develop/element.io/release/config.json)
[release](https://github.com/vector-im/element-desktop/blob/develop/element.io/release/config.json)
configs
5. Celebrate! 🥳

View file

@ -1,80 +0,0 @@
# Installing Element Web
**Familiarise yourself with the [Important Security Notes](../README.md#important-security-notes) before starting, they apply to all installation methods.**
_Note: that for the security of your chats will need to serve Element over HTTPS.
Major browsers also do not allow you to use VoIP/video chats over HTTP, as WebRTC is only usable over HTTPS.
There are some exceptions like when using localhost, which is considered a [secure context](https://developer.mozilla.org/docs/Web/Security/Secure_Contexts) and thus allowed._
## Release tarball
1. Download the latest version from <https://github.com/element-hq/element-web/releases>
1. Untar the tarball on your web server
1. Move (or symlink) the `element-x.x.x` directory to an appropriate name
1. Configure the correct caching headers in your webserver (see below)
1. Configure the app by copying `config.sample.json` to `config.json` and
modifying it. See the [configuration docs](config.md) for details.
1. Enter the URL into your browser and log into Element!
Releases are signed using gpg and the OpenPGP standard,
and can be checked against the public key located at <https://packages.element.io/element-release-key.asc>.
## Debian package
Element Web is now also available as a Debian package for Debian and Ubuntu based systems.
```shell
sudo apt install -y wget apt-transport-https
sudo wget -O /usr/share/keyrings/element-io-archive-keyring.gpg https://packages.element.io/debian/element-io-archive-keyring.gpg
echo "deb [signed-by=/usr/share/keyrings/element-io-archive-keyring.gpg] https://packages.element.io/debian/ default main" | sudo tee /etc/apt/sources.list.d/element-io.list
sudo apt update
sudo apt install element-web
```
Configure the app by modifying `/etc/element-web/config.json`. See the [configuration docs](config.md) for details.
Then point your chosen web server (e.g. Caddy, Nginx, Apache, etc) at the `/usr/share/element-web` webroot.
## Docker
The Docker image can be used to serve element-web as a web server. The easiest way to use
it is to use the prebuilt image:
```bash
docker run -p 80:80 vectorim/element-web
```
To supply your own custom `config.json`, map a volume to `/app/config.json`. For example,
if your custom config was located at `/etc/element-web/config.json` then your Docker command
would be:
```bash
docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web
```
To build the image yourself:
```bash
git clone https://github.com/element-hq/element-web.git element-web
cd element-web
git checkout master
docker build .
```
If you're building a custom branch, or want to use the develop branch, check out the appropriate
element-web branch and then run:
```bash
docker build -t \
--build-arg USE_CUSTOM_SDKS=true \
--build-arg REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git" \
--build-arg REACT_SDK_BRANCH="develop" \
--build-arg JS_SDK_REPO="https://github.com/matrix-org/matrix-js-sdk.git" \
--build-arg JS_SDK_BRANCH="develop" \
.
```
## Kubernetes
The provided element-web docker image can also be run from within a Kubernetes cluster.
See the [Kubernetes example](kubernetes.md) for more details.

View file

@ -1,7 +1,7 @@
# Jitsi wrapper developer docs
_If you're looking for information on how to set up Jitsi in your Element, see
[jitsi.md](./jitsi.md) instead._
*If you're looking for information on how to set up Jitsi in your Element, see
[jitsi.md](./jitsi.md) instead.*
These docs are for developers wondering how the different conference buttons work
within Element. If you're not a developer, you're probably looking for [jitsi.md](./jitsi.md).
@ -46,24 +46,24 @@ end up creating a widget with a URL like `https://integrations.example.org?widge
The integration manager's wrapper will typically have another iframe to isolate the
widget from the client by yet another layer. The wrapper often provides other functionality
which might not be available on the embedded site, such as a fullscreen button or the
communication layer with the client (all widgets _should_ be talking to the client
communication layer with the client (all widgets *should* be talking to the client
over `postMessage`, even if they aren't going to be using the widget APIs).
Widgets added with the `/addwidget` command will _not_ be wrapped as they are not going
through an integration manager. The widgets themselves _should_ also work outside of
Widgets added with the `/addwidget` command will *not* be wrapped as they are not going
through an integration manager. The widgets themselves *should* also work outside of
Element. Widgets currently have a "pop out" button which opens them in a new tab and
therefore have no connection back to Riot.
## Jitsi widgets from integration managers
Integration managers will create an entire widget event and send it over `postMessage`
for the client to add to the room. This means that the integration manager gets to
for the client to add to the room. This means that the integration manager gets to
decide the conference domain, conference name, and other aspects of the widget. As
a result, users can end up with a Jitsi widget that does not use the same conference
server they specified in their config.json - this is expected.
Some integration managers allow the user to change the conference name while others
will generate one for the user.
will generate one for the user.
## Jitsi widgets generated by Element itself
@ -79,7 +79,7 @@ The Jitsi widget created by Element uses a local `jitsi.html` wrapper (or one ho
required `postMessage` calls are fulfilled.
**Note**: Per [jitsi.md](./jitsi.md) the `preferredDomain` can also come from the server's
client .well-known data.
client .well-known data.
## The Jitsi wrapper in Element
@ -92,9 +92,9 @@ and less risky to load. The local wrapper URL is populated with the conference i
from the original widget (which could be a v1 or v2 widget) so the user joins the right
call.
Critically, when the widget URL is reconstructed it does _not_ take into account the
Critically, when the widget URL is reconstructed it does *not* take into account the
config.json's `preferredDomain` for Jitsi. If it did this, users would end up on different
conference servers and therefore different calls entirely.
conference servers and therefore different calls entirely.
**Note**: Per [jitsi.md](./jitsi.md) the `preferredDomain` can also come from the server's
client .well-known data.

View file

@ -4,10 +4,10 @@ Element uses [Jitsi](https://jitsi.org/) for conference calls, which provides op
self-hosting your own server and supports most major platforms.
1:1 calls, or calls between you and one other person, do not use Jitsi. Instead, those
calls work directly between clients or via TURN servers configured on the respective
calls work directly between clients or via TURN servers configured on the respective
homeservers.
There's a number of ways to start a Jitsi call: the easiest way is to click on the
There's a number of ways to start a Jitsi call: the easiest way is to click on the
voice or video buttons near the message composer in a room with more than 2 people. This
will add a Jitsi widget which allows anyone in the room to join.
@ -16,43 +16,37 @@ provide their own approaches for adding Jitsi widgets.
## Configuring Element to use your self-hosted Jitsi server
You can host your own Jitsi server to use with Element. It's usually advisable to use a recent
version of Jitsi. In particular, versions older than around 6826 will cause problems with
Element 1.9.10 or newer.
Element will use the Jitsi server that is embedded in the widget, even if it is not the
one you configured. This is because conference calls must be held on a single Jitsi
server and cannot be split over multiple servers.
However, you can configure Element to _start_ a conference with your Jitsi server by adding
However, you can configure Element to *start* a conference with your Jitsi server by adding
to your [config](./config.md) the following:
```json
{
"jitsi": {
"preferred_domain": "your.jitsi.example.org"
}
"jitsi": {
"preferredDomain": "your.jitsi.example.org"
}
}
```
Element's default is `meet.element.io` (a free service offered by Element). `meet.jit.si`
is an instance hosted by Jitsi themselves and is also free to use.
The default is `jitsi.riot.im` (a free service offered by Element), and the demo site for
Jitsi uses `meet.jit.si` (also free).
Once you've applied the config change, refresh Element and press the call button. This
should start a new conference on your Jitsi server.
should start a new conference on your Jitsi server.
**Note**: The widget URL will point to a `jitsi.html` page hosted by Element. The Jitsi
domain will appear later in the URL as a configuration parameter.
**Hint**: If you want everyone on your homeserver to use the same Jitsi server by
default, and you are using element-web 1.6 or newer, set the following on your homeserver's
default, and you are using element-web 1.6 or newer, set the following on your homeserver's
`/.well-known/matrix/client` config:
```json
{
"im.vector.riot.jitsi": {
"preferredDomain": "your.jitsi.example.org"
}
"im.vector.riot.jitsi": {
"preferredDomain": "your.jitsi.example.org"
}
}
```
@ -61,11 +55,11 @@ default, and you are using element-web 1.6 or newer, set the following on your h
Element Android (1.0.5+) supports custom Jitsi domains, similar to Element Web above.
1:1 calls, or calls between you and one other person, do not use Jitsi. Instead, those
calls work directly between clients or via TURN servers configured on the respective
calls work directly between clients or via TURN servers configured on the respective
homeservers.
For rooms with more than 2 joined members, when creating a Jitsi conference via call/video buttons of the toolbar (not via integration manager), Element Android will create a widget using the [wrapper](https://github.com/element-hq/element-web/blob/develop/docs/jitsi-dev.md) hosted on `app.element.io`.
The domain used is the one specified by the `/.well-known/matrix/client` endpoint, and if not present it uses the fallback defined in `config.json` (meet.element.io)
For rooms with more than 2 joined members, when creating a Jitsi conference via call/video buttons of the toolbar (not via integration manager), Element Android will create a widget using the [wrapper](https://github.com/vector-im/element-web/blob/develop/docs/jitsi-dev.md) hosted on `app.element.io`.
The domain used is the one specified by the `/.well-known/matrix/client` endpoint, and if not present it uses the fallback defined in `config.xml` (jitsi.riot.im)
For active Jitsi widgets in the room, a native Jitsi widget UI is created and points to the instance specified in the `domain` key of the widget content data.

View file

@ -1,4 +1,5 @@
# Running in Kubernetes
Running in Kubernetes
=====================
In case you would like to deploy element-web in a kubernetes cluster you can use
the provided Kubernetes example below as a starting point. Note that this example assumes the
@ -60,24 +61,30 @@ Then you can deploy it to your cluster with something like `kubectl apply -f my-
],
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"defaultCountryCode": "GB",
"show_labs_settings": false,
"showLabsSettings": false,
"features": { },
"default_federate": true,
"default_theme": "light",
"room_directory": {
"roomDirectory": {
"servers": [
"matrix.org"
]
},
"piwik": {
"url": "https://piwik.riot.im/",
"whitelistedHSUrls": ["https://matrix.org"],
"whitelistedISUrls": ["https://vector.im", "https://matrix.org"],
"siteId": 1
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
},
"setting_defaults": {
"settingDefaults": {
"breadcrumbs": true
},
"jitsi": {
"preferred_domain": "meet.element.io"
"preferredDomain": "jitsi.riot.im"
}
}
@ -162,7 +169,7 @@ Then you can deploy it to your cluster with something like `kubectl apply -f my-
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header Content-Security-Policy "frame-ancestors 'self'";
add_header Content-Security-Policy "frame-ancestors 'none'";
spec:
rules:
- host: element.example.nl
@ -177,3 +184,4 @@ Then you can deploy it to your cluster with something like `kubectl apply -f my-
number: 80
---

View file

@ -4,9 +4,6 @@ If Labs is enabled in the [Element config](config.md), you can enable some of th
to `Settings->Labs`. This list is non-exhaustive and subject to change, chat in
[#element-web:matrix.org](https://matrix.to/#/#element-web:matrix.org) for more information.
If a labs features gets more stable, it _may_ be promoted to a beta feature
(see [Betas](https://github.com/element-hq/element-web/blob/develop/docs/betas.md)).
**Be warned! Labs features are not finalised, they may be fragile, they may change, they may be
dropped. Ask in the room if you are unclear about any details here.**
@ -24,18 +21,44 @@ Enables rendering of LaTeX maths in messages using [KaTeX](https://katex.org/).
Allows you to pin messages in the room. To pin a message, use the 3 dots to the right of the message
and select "Pin".
## Jump to date (`feature_jump_to_date`)
## Custom status (`feature_custom_status`)
Note: This labs feature is only visible when your homeserver has MSC3030 enabled
(in Synapse, add `experimental_features` -> `msc3030_enabled` to your
`homeserver.yaml`) which means `GET /_matrix/client/versions` responds with
`org.matrix.msc3030` under the `unstable_features` key.
An experimental approach for supporting custom status messages across DMs. To set a status, click on
your avatar next to the message composer.
Adds a dropdown menu to the date separator headers in the timeline which allows
you to jump to last week, last month, the beginning of the room, or choose a
date from the calendar.
## Custom tags (`feature_custom_tags`)
Also adds the `/jumptodate 2022-01-31` slash command.
An experimental approach for dealing with custom tags. Custom tags will appear in the bottom portion
of the community filter panel.
Setting custom tags is not supported by Element.
## Render simple counters in room header (`feature_state_counters`)
Allows rendering of labelled counters above the message list.
Once enabled, send a custom state event to a room to set values:
1. In a room, type `/devtools` to bring up the devtools interface
2. Click "Send Custom Event"
3. Toggle from "Event" to "State Event"
4. Set the event type to: `re.jki.counter` and give it a unique key
5. Specify the content in the following format:
```
{
"link": "",
"severity": "normal",
"title": "my counter",
"value": 0
}
```
That's it. Now should see your new counter under the header.
## Multiple integration managers (`feature_many_integration_managers`)
Exposes a way to access all the integration managers known to Element. This is an implementation of [MSC1957](https://github.com/matrix-org/matrix-doc/pull/1957).
## New ways to ignore people (`feature_mjolnir`)
@ -63,6 +86,11 @@ present in the room. The Bridge info tab pulls information from the `m.bridge` s
bridges are not expected to be compatible, and users should not rely on this
tab as the single source of truth just yet.
## Presence indicator in room list (`feature_presence_in_room_list`)
This adds a presence indicator in the room list next to DM rooms where the other
person is online.
## Custom themes (`feature_custom_themes`)
Custom themes are possible through Element's [theme support](./theming.md), though
@ -72,52 +100,57 @@ theme definition.
For some sample themes, check out [aaronraimist/element-themes](https://github.com/aaronraimist/element-themes).
## Message preview tweaks
To enable message previews for reactions in all rooms, enable `feature_roomlist_preview_reactions_all`.
To enable message previews for reactions in DMs, enable `feature_roomlist_preview_reactions_dms`, ignored when it is enabled for all rooms.
## Communities v2 prototyping (`feature_communities_v2_prototypes`) [In Development]
**This is a highly experimental implementation for parts of the communities v2 experience.** It does not
represent what communities v2 will look/feel like and can/will change without notice. Due to the early
stages this feature is in and the requirement for a compatible homeserver, we will not be accepting issues
or feedback for this functionality at this time.
## Dehydrated devices (`feature_dehydration`)
Allows users to receive encrypted messages by creating a device that is stored
encrypted on the server, as described in [MSC2697](https://github.com/matrix-org/matrix-doc/pull/2697).
## Live location sharing (`feature_location_share_live`) [In Development]
## Do not disturb (`feature_dnd`)
Enables sharing your current location to the timeline, with live updates.
Enables UI for turning on "do not disturb" mode for the current device. When DND mode is engaged, popups
and notification noises are suppressed. Not perfect, but can help reduce noise.
## Video rooms (`feature_video_rooms`)
## Hidden read receipts (`feature_hidden_read_receipts`)
Enables support for creating and joining video rooms, which are persistent video chats that users can jump in and out of.
Enables sending hidden read receipts as per [MSC2285](https://github.com/matrix-org/matrix-doc/pull/2285)
## Element Call video rooms (`feature_element_call_video_rooms`) [In Development]
## New layout switcher (with message bubbles) (`feature_new_layout_switcher`)
Enables support for video rooms that use Element Call rather than Jitsi, and causes the 'New video room' option to create Element Call video rooms rather than Jitsi ones.
Adds a "Message layout" section under `Settings -> Appearance`, where the user can select their preferred message layout (e.g. IRC or Modern). Additionally, adds a new "Message bubbles" layout.
This flag will not have any effect unless `feature_video_rooms` is also enabled.
## Pseudonymous Analytics opt-in (`feature_pseudonymous_analytics_opt_in`)
## New group call experience (`feature_group_calls`) [In Development]
Opts in to collection of pseudonymous analytics data via Posthog. See https://github.com/matrix-org/matrix-react-sdk/pull/6495
This feature allows users to place and join native [MSC3401](https://github.com/matrix-org/matrix-spec-proposals/pull/3401) group calls in compatible rooms, using Element Call.
## Polls (`feature_polls`) [In Development]
If you're enabling this at the deployment level, you may also want to reference the docs for the `element_call` config section.
Polls are a way to gauge interest from your community about a certain topic with a simple voting mechanic
within the message timeline. Note that this feature is currently under active development and therefore is
entirely incomplete and may not work at all - it is not recommended for general use at this time.
## Disable per-sender encryption for Element Call (`feature_disable_call_per_sender_encryption`)
Bug reports, feature requests, etc are not currently accepted for this feature flag. A later stage of
development will provide opportunities for feedback.
The default for embedded Element Call in Element Web is per-participant encryption.
This labs flag disables encryption for embedded Element Call in encrypted rooms.
## Maximised widgets (`feature_maximised_widgets`) [In Development]
Under the hood this stops Element Web from adding the `perParticipantE2EE` flag for the Element Call widget url.
Maximised widgets provide a room layout in which a widget is (temporarily) the primary focus of the room. The whole chat area is then used for the widget. The chat is moved into the right panel.
This is useful while we experiment with encryption and to make calling compatible with platforms that don't use encryption yet.
Note that this feature is currently under active development and therefore is
entirely incomplete and may not work at all - it is not recommended for general use at this time.
## Rich text in room topics (`feature_html_topic`) [In Development]
## Metaspaces (`feature_spaces_metaspaces`) [In Development]
Enables rendering of MD / HTML in room topics.
## 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.
Metaspaces are automatically populated spaces you can enable in your Space panel.
By default, you'll have Home or All rooms, but you can opt in to a People, Favourites, and Other Rooms metaspace too.

View file

@ -1,14 +0,0 @@
/* Prevent collapsible headings from wrapping onto two lines eagerly */
summary > h1,
summary > h2,
summary > h3,
summary > h4,
summary > h5,
summary > h6 {
display: inline-block;
}
/* Prevent longer checkbox lists from wrapping eagerly */
input + p {
display: inline;
}

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,11 +1,11 @@
## Memory leaks
Element usually emits slow behaviour just before it is about to crash. Getting a
Element usually emits slow behaviour just before it is about to crash. Getting a
memory snapshot (below) just before that happens is ideal in figuring out what
is going wrong.
Common symptoms are clicking on a room and it feels like the tab froze and scrolling
becoming jumpy/staggered.
becoming jumpy/staggered.
If you receive a white screen (electron) or the chrome crash page, it is likely
run out of memory and it is too late for a memory profile. Please do report when
@ -22,8 +22,8 @@ and anything newer is still in the warmup stages of the app.
**Memory profiles can contain sensitive information.** If you are submitting a memory
profile to us for debugging purposes, please pick the appropriate Element developer and
send them over an encrypted private message. _Do not share your memory profile in
public channels or with people you do not trust._
send them over an encrypted private message. *Do not share your memory profile in
public channels or with people you do not trust.*
### Taking a memory profile (Firefox)

View file

@ -1,51 +0,0 @@
# Module system
The module system in Element Web is a way to add or modify functionality of Element Web itself, bundled at compile time
for the app. This means that modules are loaded as part of the `yarn build` process but have an effect on user experience
at runtime.
## Installing modules
If you already have a module you want to install, such as our [ILAG Module](https://github.com/element-hq/element-web-ilag-module),
then copy `build_config.sample.yaml` to `build_config.yaml` in the same directory. In your new `build_config.yaml` simply
add the reference to the module as described by the sample file, using the same syntax you would for `yarn add`:
```yaml
modules:
# Our module happens to be published on NPM, so we use that syntax to reference it.
- "@vector-im/element-web-ilag-module@latest"
```
Then build the app as you normally would: `yarn build` or `yarn dist` (if compatible on your platform). If you are building
the Docker image then ensure your `build_config.yaml` ends up in the build directory. Usually this works fine if you use
the current directory as the build context (the `.` in `docker build -t my-element-web .`).
## Writing modules
While writing modules is meant to be easy, not everything is possible yet. For modules which want to do something we haven't
exposed in the module API, the module API will need to be updated. This means a PR to both the
[`matrix-react-sdk`](https://github.com/matrix-org/matrix-react-sdk) and [`matrix-react-sdk-module-api`](https://github.com/matrix-org/matrix-react-sdk-module-api).
Once your change to the module API is accepted, the `@matrix-org/react-sdk-module-api` dependency gets updated at the
`matrix-react-sdk` and `element-web` layers (usually by us, the maintainers) to ensure your module can operate.
If you're not adding anything to the module API, or your change was accepted per above, then start off with a clone of
our [ILAG module](https://github.com/element-hq/element-web-ilag-module) which will give you a general idea for what the
structure of a module is and how it works.
The following requirements are key for any module:
1. The module must depend on `@matrix-org/react-sdk-module-api` (usually as a dev dependency).
2. The module's `main` entrypoint must have a `default` export for the `RuntimeModule` instance, supporting a constructor
which takes a single parameter: a `ModuleApi` instance. This instance is passed to `super()`.
3. The module must be deployed in a way where `yarn add` can access it, as that is how the build system will try to
install it. Note that while this is often NPM, it can also be a GitHub/GitLab repo or private NPM registry.
Be careful when using git dependencies in yarn classic, many lifecycle scripts will not be executed which may mean
that your module is not built and thus may fail to be imported.
... and that's pretty much it. As with any code, please be responsible and call things in line with the documentation.
Both `RuntimeModule` and `ModuleApi` have extensive documentation to describe what is proper usage and how to set things
up.
If you have any questions then please visit [#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) on
Matrix and we'll help as best we can.

View file

@ -1,3 +1,3 @@
# Native Node Modules
This documentation moved to the [`element-desktop`](https://github.com/element-hq/element-desktop/blob/develop/docs/native-node-modules.md) repository.
This documentation moved to the [`element-desktop`](https://github.com/vector-im/element-desktop/blob/develop/docs/native-node-modules.md) repository.

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

@ -1,270 +0,0 @@
> Tip: Paste this into the browser console to make the checkboxes on this page tickable. (Bear in mind that your ticks will be lost if you reload though.)
>
> ```
> document.querySelectorAll("input[type='checkbox']").forEach(i => {i.disabled = false;})
> ```
<details><summary><h1>Branches</h1></summary><blockquote>
#### develop
The develop branch holds the very latest and greatest code we have to offer, as such it may be less stable. It corresponds to the develop.element.io CD platform.
#### staging
The staging branch corresponds to the very latest release regardless of whether it is an RC or not. Deployed to staging.element.io manually.
#### master
The master branch is the most stable as it is the very latest non-RC release. Deployed to app.element.io manually.
</blockquote></details>
<details><summary><h1>Versions</h1></summary><blockquote>
The matrix-js-sdk follows semver, the matrix-react-sdk loosely follows semver, most releases for both will bump the minor version number.
Breaking changes will bump the major version number.
Element Web & Element Desktop do not follow semver and always have matching version numbers. The patch version number is normally incremented for every release.
</blockquote></details>
<details><summary><h1>Release Types</h1></summary><blockquote>
#### Release candidate
A normal release begins with a Release Candidate on the Tick phase of the release cycle,
and may contain as many further RCs as are needed before the Tock phase of cycle.
Each subsequent RC may add additional commits via any of the means of preparation.
A normal release is the most typical run-of-the-mill release,
with at least one RC (Release Candidate) followed by a FINAL release.
The typical cadence for these is every 2 weeks we'll do a new initial RC,
then the following week we'll do that release cycle's FINAL release with sometimes more RCs in between, as needed.
#### Final
A normal release culminates with a Final release on the Tock phase of the cycle.
This may be merely shipping the very latest RC with an adjusted version number,
but can also include (hopefully small) additional changes present on `staging` if they are deemed safe to skip an RC.
### Hotfix / Security
This is an accelerated type of release which sits somewhere between RC and Final.
They tend to contain few patches delta from the previous release but also skip any form of RC
and in the case of Security the patch lands on GitHub only moments prior.
For all intents and purposes they are the same as a Final release but with a different purpose.
</blockquote></details>
<details><summary><h1>Release Blockers</h1></summary><blockquote>
You should become release rabbit on the day after the last full release.
For that week, it's your job to keep an eye on the Releases room and see whether any issues marked `X-Release-Blocker` are opened,
or were already open. You should chase people to fix them, so that on RC day you can make the release.
If release-blocking issues are still open, you need to delay the release until they are fixed or reclassified.
There are two labels for tracking release blockers.
#### X-Release-Blocker
This label applied to an issue means we cannot ship a release affected by the specific issue.
This means we cannot cut branches for an RC but security & hotfix releases may still be fine.
#### X-Upcoming-Release-Blocker
This label applied to an issue means that the next (read: not current) release cycle will be affected by the specific issue.
This label will automagically convert to `X-Release-Blocker` at the conclusion of a full release.
</blockquote></details>
<details><summary><h1>Repositories</h1></summary><blockquote>
This release process revolves around our four main repositories:
- [Element Desktop](https://github.com/element-hq/element-desktop/)
- [Element Web](https://github.com/element-hq/element-web/)
- [Matrix React SDK](https://github.com/matrix-org/matrix-react-sdk/)
- [Matrix JS SDK](https://github.com/matrix-org/matrix-js-sdk/)
We own other repositories, but they have more ad-hoc releases and are not part of the bi-weekly cycle:
- https://github.com/matrix-org/matrix-web-i18n/
- https://github.com/matrix-org/matrix-react-sdk-module-api
</blockquote></details>
<details><summary><h1>Prerequisites</h1></summary><blockquote>
- You must be part of the 2 Releasers GitHub groups:
- <https://github.com/orgs/element-hq/teams/element-web-releasers>
- <https://github.com/orgs/matrix-org/teams/element-web-releasers>
- You will need access to the **VPN** ([docs](https://gitlab.matrix.org/new-vector/internal/-/wikis/SRE/Tailscale)) to be able to follow the instructions under Deploy below.
- You will need the ability to **SSH** in to the production machines to be able to follow the instructions under Deploy below. Ensure that your SSH key has a non-empty passphrase, and you registered your SSH key with Ops. Log a ticket at https://github.com/matrix-org/matrix-ansible-private and ask for:
- Two-factor authentication to be set up on your SSH key. (This is needed to get access to production).
- SSH access to `horme` (staging.element.io and app.element.io)
- Permission to sudo on horme as the user `element`
- You need "**jumphost**" configuration in your local `~/.ssh/config`. This should have been set up as part of your onboarding.
</blockquote></details>
<details><summary><h1>Overview</h1></summary><blockquote>
```mermaid
flowchart TD
P[[Prepare staging branches]]
P --> R1
subgraph Releasing
R1[[Releasing matrix-js-sdk]]
R2[[Releasing matrix-react-sdk]]
R3[[Releasing element-web]]
R4[[Releasing element-desktop]]
R1 --> R2 --> R3 --> R4
end
R4 --> D1
subgraph Deploying
D1[\Deploy staging.element.io/]
D2[\Check dockerhub/]
D3[\Deploy app.element.io/]
D4[\Check desktop package/]
D1 --> D2 --> D
D{FINAL?}
D -->|Yes| D3 --> D4
end
D -->|No| H1
D4 --> H1
subgraph Housekeeping
H1[\Update topics/]
H2[\Announce/]
H3[\Archive done column/]
H4[\Add diary entry/]
H5[\Renovate/]
H1 --> H2 --> H
H{FINAL?}
H -->|Yes| H3 --> H4 --> DONE
H -->|No| H5
end
DONE([You are done!])
H5 --> DONE
```
</blockquote></details>
---
# Preparation
The goal of this stage is to get the code you want to ship onto the `staging` branch.
There are multiple ways to accomplish this depending on the type of release you need to perform.
For the first RC in a given release cycle the easiest way to prepare branches is using the
[Cut branches automation](https://github.com/element-hq/element-web/actions/workflows/release_prepare.yml) -
this will take `develop` and merge it into the `staging` on the chosen repositories.
For subsequent RCs, if you need to include a change you may PR it directly to the `staging` branch or rely on the
backport automation via labelling a PR to `develop` with `backport staging` which will cause a new PR to be opened
which backports the requested change to the `staging` branch.
For security, you may wish to merge the security advisory private fork or apply the patches manually and then push them directly to `staging`.
It is worth noting that at the end of the Final/Hotfix/Security release `staging` is merged to `master` which is merged back into `develop` -
this means that any commit which goes to `staging` will eventually make its way back to the default branch.
- [ ] The staging branch is prepared
# Releasing
Shortly after concluding the preparation stage (or pushing any changes to `staging` in general);
a draft release will be automatically made on the 4 project repositories with suggested changelogs and version numbers.
_Note: we should add a step here to write summaries atop the changelogs manually, or via AI_
Publishing the SDKs to npm also commits a dependency upgrade to the relevant downstream projects,
if you skip a layer of this release (e.g. for a hotfix) then the dependency will remain on `#develop` which will be
switched back to the version of the dependency from the master branch to not leak develop code into a release.
### Matrix JS SDK
- [ ] Check the draft release which has been generated by [the automation](https://github.com/matrix-org/matrix-js-sdk/actions/workflows/release-drafter.yml)
- [ ] Make any changes to the release notes in the draft release as are necessary - **Do not click publish, only save draft**
- [ ] Kick off a release using [the automation](https://github.com/matrix-org/matrix-js-sdk/actions/workflows/release.yml) - making sure to select the right type of release. For anything other than an RC: choose final. You should not need to ever switch off either of the Publishing options.
### Matrix React SDK
- [ ] Check the draft release which has been generated by [the automation](https://github.com/matrix-org/matrix-react-sdk/actions/workflows/release-drafter.yml)
- [ ] Make any changes to the release notes in the draft release as are necessary - **Do not click publish, only save draft**
- [ ] Kick off a release using [the automation](https://github.com/matrix-org/matrix-react-sdk/actions/workflows/release.yml) - making sure to select the right type of release. For anything other than an RC: choose final. You should not need to ever switch off either of the Publishing options.
### Element Web
- [ ] Check the draft release which has been generated by [the automation](https://github.com/element-hq/element-web/actions/workflows/release-drafter.yml)
- [ ] Make any changes to the release notes in the draft release as are necessary - **Do not click publish, only save draft**
- [ ] Kick off a release using [the automation](https://github.com/element-hq/element-web/actions/workflows/release.yml) - making sure to select the right type of release. For anything other than an RC: choose final. You should not need to ever switch off either of the Publishing options.
### Element Desktop
- [ ] Check the draft release which has been generated by [the automation](https://github.com/element-hq/element-desktop/actions/workflows/release-drafter.yml)
- [ ] Make any changes to the release notes in the draft release as are necessary - **Do not click publish, only save draft**
- [ ] Kick off a release using [the automation](https://github.com/element-hq/element-desktop/actions/workflows/release.yml) - making sure to select the right type of release. For anything other than an RC: choose final. You should not need to ever switch off either of the Publishing options.
# Deploying
We ship the SDKs to npm, this happens as part of the release process.
We ship Element Web to dockerhub, `*.element.io`, and packages.element.io.
We ship Element Desktop to packages.element.io.
- [ ] Check that element-web has shipped to dockerhub
- [ ] Deploy staging.element.io. [See docs.](https://handbook.element.io/books/element-web-team/page/deploying-appstagingelementio)
- [ ] Test staging.element.io
For final releases additionally do these steps:
- [ ] Deploy app.element.io. [See docs.](https://handbook.element.io/books/element-web-team/page/deploying-appstagingelementio)
- [ ] Test app.element.io
- [ ] Ensure Element Web package has shipped to packages.element.io
- [ ] Ensure Element Desktop packages have shipped to packages.element.io
# Housekeeping
We have some manual housekeeping to do in order to prepare for the next release.
- [ ] Update topics using [the automation](https://github.com/element-hq/element-web/actions/workflows/update-topics.yaml). It will autodetect the current latest version. Don't forget the date you supply should be e.g. September 5th (including the "th") for the script to work.
- [ ] Announce the release in [#element-web-announcements:matrix.org](https://matrix.to/#/#element-web-announcements:matrix.org)
<details><summary>(show)</summary>
With wording like:
> Element Web v1.11.24 is here!
>
> This version adds ... and fixes bugs ...
>
> Check it out at app.element.io, in Element Desktop, or from Docker Hub. Changelog and more details at https://github.com/element-hq/element-web/releases/tag/v1.11.24
</details>
For the first RC of a given release cycle do these steps:
- [ ] Go to the [matrix-js-sdk Renovate dashboard](https://github.com/matrix-org/matrix-js-sdk/issues/2406) and click the checkbox to create/update its PRs.
- [ ] Go to the [matrix-react-sdk Renovate dashboard](https://github.com/matrix-org/matrix-react-sdk/issues/9667) and click the checkbox to create/update its PRs.
- [ ] Go to the [element-web Renovate dashboard](https://github.com/element-hq/element-web/issues/22941) and click the checkbox to create/update its PRs.
- [ ] Go to the [element-desktop Renovate dashboard](https://github.com/element-hq/element-desktop/issues/465) and click the checkbox to create/update its PRs.
- [ ] Later, check back and merge the PRs that succeeded to build. The ones that failed will get picked up by the [maintainer](https://docs.google.com/document/d/1V5VINWXATMpz9UBw4IKmVVB8aw3CxM0Jt7igtHnDfSk/edit#).
For final releases additionally do these steps:
- [ ] Archive done column on the [team board](https://github.com/orgs/element-hq/projects/67/views/34) _Note: this should be automated_
- [ ] Add entry to the [milestones diary](https://docs.google.com/document/d/1cpRFJdfNCo2Ps6jqzQmatzbYEToSrQpyBug0aP_iwZE/edit#heading=h.6y55fw4t283z). The document says only to add significant releases, but we add all of them just in case.

View file

@ -10,53 +10,53 @@ When reviewing code, here are some things we look for and also things we avoid:
### We review for
- Correctness
- Performance
- Accessibility
- Security
- Quality via automated and manual testing
- Comments and documentation where needed
- Sharing knowledge of different areas among the team
- Ensuring it's something we're comfortable maintaining for the long term
- Progress indicators and local echo where appropriate with network activity
* Correctness
* Performance
* Accessibility
* Security
* Quality via automated and manual testing
* Comments and documentation where needed
* Sharing knowledge of different areas among the team
* Ensuring it's something we're comfortable maintaining for the long term
* Progress indicators and local echo where appropriate with network activity
### We should avoid
- Style nits that are already handled by the linter
- Dramatically increasing scope
* Style nits that are already handled by the linter
* Dramatically increasing scope
### Good practices
- Use empathetic language
- See also [Mindful Communication in Code
Reviews](https://kickstarter.engineering/a-guide-to-mindful-communication-in-code-reviews-48aab5282e5e)
and [How to Do Code Reviews Like a Human](https://mtlynch.io/human-code-reviews-1/)
- Authors should prefer smaller commits for easier reviewing and bisection
- Reviewers should be explicit about required versus optional changes
- Reviews are conversations and the PR author should feel comfortable
discussing and pushing back on changes before making them
- Reviewers are encouraged to ask for tests where they believe it is reasonable
- Core team should lead by example through their tone and language
- Take the time to thank and point out good code changes
- Using softer language like "please" and "what do you think?" goes a long way
towards making others feel like colleagues working towards a common goal
* Use empathetic language
* See also [Mindful Communication in Code
Reviews](https://kickstarter.engineering/a-guide-to-mindful-communication-in-code-reviews-48aab5282e5e)
and [How to Do Code Reviews Like a Human](https://mtlynch.io/human-code-reviews-1/)
* Authors should prefer smaller commits for easier reviewing and bisection
* Reviewers should be explicit about required versus optional changes
* Reviews are conversations and the PR author should feel comfortable
discussing and pushing back on changes before making them
* Reviewers are encouraged to ask for tests where they believe it is reasonable
* Core team should lead by example through their tone and language
* Take the time to thank and point out good code changes
* Using softer language like "please" and "what do you think?" goes a long way
towards making others feel like colleagues working towards a common goal
### Workflow
- Authors should request review from the element-web team by default (if someone on
the team is clearly the expert in an area, a direct review request to them may
be more appropriate)
- Reviewers should remove the team review request and request review from
themselves when starting a review to avoid double review
- If there are multiple related PRs authors should reference each of the PRs in
the others before requesting review. Reviewers might start reviewing from
different places and could miss other required PRs.
- Avoid force pushing to a PR after the first round of review
- Use the GitHub default of merge commits when landing (avoid alternate options
like squash or rebase)
- PR author merges after review (assuming they have write access)
- Assign issues only when in progress to indicate to others what can be picked
up
* Authors should request review from the element-web team by default (if someone on
the team is clearly the expert in an area, a direct review request to them may
be more appropriate)
* Reviewers should remove the team review request and request review from
themselves when starting a review to avoid double review
* If there are multiple related PRs authors should reference each of the PRs in
the others before requesting review. Reviewers might start reviewing from
different places and could miss other required PRs.
* Avoid force pushing to a PR after the first round of review
* Use the GitHub default of merge commits when landing (avoid alternate options
like squash or rebase)
* PR author merges after review (assuming they have write access)
* Assign issues only when in progress to indicate to others what can be picked
up
## Code Quality
@ -64,10 +64,10 @@ In the past, we have occasionally written different kinds of tests for
Element and the SDKs, but it hasn't been a consistent focus. Going forward, we'd
like to change that.
- For new features, code reviewers will expect some form of automated testing to
be included by default
- For bug fixes, regression tests are of course great to have, but we don't want
to block fixes on this, so we won't require them at this time
* For new features, code reviewers will expect some form of automated testing to
be included by default
* For bug fixes, regression tests are of course great to have, but we don't want
to block fixes on this, so we won't require them at this time
The above policy is not a strict rule, but instead it's meant to be a
conversation between the author and reviewer. As an author, try to think about
@ -104,10 +104,10 @@ perspective.
In more detail, our usual process for changes that affect the UI or alter user
functionality is:
- For changes that will go live when merged, always flag Design and Product
teams as appropriate
- For changes guarded by a feature flag, Design and Product review is not
required (though may still be useful) since we can continue tweaking
* For changes that will go live when merged, always flag Design and Product
teams as appropriate
* For changes guarded by a feature flag, Design and Product review is not
required (though may still be useful) since we can continue tweaking
As it can be difficult to review design work from looking at just the changed
files in a PR, a [preview site](./pr-previews.md) that includes your changes

68
docs/skinning thoughts.md Normal file
View file

@ -0,0 +1,68 @@
== Skinning refactor ==
matrix-react-sdk
- base images
- base CSS
- all the components needed to build a workable app (including the top layer)
element-web: the Element skin
- Element-specific classes (e.g. login header/footer)
- Element-specific themes
- light
- dark
i.e. the only things which should go into element-web are bits which apply vector-specific skinning
specifically "Stuff that any other brand would not want to use. (e.g. Element logos, links, T&Cs)"
- Questions:
- Electron app? (should probably be a separate repo in its own right? but might as well go here for now)
- index.html & index.js? (should be in matrix-react-sdk, given the SDK is useless without them?)
ideally matrix-react-sdk itself should ship with a default skin which actually works built in.
status skin (can go in the same app for now)
- has status theme
- which inherits from Element light theme
- how do we share graphics between skins?
- shove them into react-sdk, or...
- guess we do ../../vector/img
- this means keeping the skin name in the images (unless /img is a shortcut to the right skin's images)
out of scope:
- making the components more independent, so they can be used in isolation.
- that said, the bits which should probably be used by being embeded into a different app:
- login/reg
- RoomView + RoomSettings
- MessageComposer
- RoomList
- MemberList
- MemberInfo
- Voip UI
- UserSettings
- sharing different js-sdks between the different isolated modules
other changes:
- how do we handle i18n?
- each skin should really be its own i18n project. As long as all the commonality stuff is in matrix-react-sdk this shouldn't be too bad.
- ability to associate components with a given skin
- skins/vector/src <-- components
- skins/vector/css
- skins/vector/img
- skins/vector/fonts
- gather together themes (per skin) into a single place too
- skins/vector/themes/foo/css
- skins/vector/themes/foo/img
- skins/vector/themes/foo/fonts
- ideally element-web would contain almost nothing but skins/vector directory.
- ability to entirely replace CSS rather than override it for a given theme
- e.g. if we replace `Login.js` with `StatusLogin.js`, then we should similarly be able to replace `_Login.scss` with `_StatusLogin.scss`.
random thoughts;
- should we be able to change the entire skin at runtime (more like wordpress) - to the extent of replacing entire components?
- might pose security issues if a theme can be swapped out to replace MatrixChat or other fundamental functionality at runtime
- if so, perhaps skins & themes should converge...
-----------------
Immediate plan for Status:
* Implement it as a theme for the Element skin
* Ideally move skins to a sensible level (possibly even including src?)

View file

@ -1,29 +1,31 @@
# Theming Element
Theming Element
============
Themes are a very basic way of providing simple alternative look & feels to the
Element app via CSS & custom imagery.
They are _NOT_ co be confused with 'skins', which describe apps which sit on top
They are *NOT* co be confused with 'skins', which describe apps which sit on top
of matrix-react-sdk - e.g. in theory Element itself is a react-sdk skin.
As of March 2022, skins are not fully supported; Element is the only available skin.
As of Jan 2017, skins are not fully supported; Element is the only available skin.
To define a theme for Element:
1. Pick a name, e.g. `teal`. at time of writing we have `light` and `dark`.
2. Fork `src/skins/vector/css/themes/dark.pcss` to be `teal.pcss`
3. Fork `src/skins/vector/css/themes/_base.pcss` to be `_teal.pcss`
4. Override variables in `_teal.pcss` as desired. You may wish to delete ones
which don't differ from `_base.pcss`, to make it clear which are being
overridden. If every single colour is being changed (as per `_dark.pcss`)
1. Pick a name, e.g. `teal`. at time of writing we have `light` and `dark`.
2. Fork `src/skins/vector/css/themes/dark.scss` to be `teal.scss`
3. Fork `src/skins/vector/css/themes/_base.scss` to be `_teal.scss`
4. Override variables in `_teal.scss` as desired. You may wish to delete ones
which don't differ from `_base.scss`, to make it clear which are being
overridden. If every single colour is being changed (as per `_dark.scss`)
then you might as well keep them all.
5. Add the theme to the list of entrypoints in webpack.config.js
6. Add the theme to the list of themes in matrix-react-sdk's UserSettings.js
7. Sit back and admire your handywork.
5. Add the theme to the list of entrypoints in webpack.config.js
6. Add the theme to the list of themes in matrix-react-sdk's UserSettings.js
7. Sit back and admire your handywork.
In future, the assets for a theme will probably be gathered together into a
single directory tree.
# Custom Themes
Custom Themes
=============
Themes derived from the built in themes may also be defined in settings.
@ -31,10 +33,10 @@ To avoid name collisions, the internal name of a theme is
`custom-${theme.name}`. So if you want to set the custom theme below as the
default theme, you would use `default_theme: "custom-Electric Blue"`.
e.g. in config.json:
eg. in config.json:
```
"setting_defaults": {
"settingDefaults": {
"custom_themes": [
{
"name": "Electric Blue",
@ -63,10 +65,8 @@ e.g. in config.json:
"timeline-text-color": "#2e2f32",
"timeline-text-secondary-color": "#61708b",
"timeline-highlights-color": "#f3f8fd",
},
"compound": {
"--cpd-color-icon-accent-tertiary": "var(--cpd-color-blue-800)",
"--cpd-color-text-action-accent": "var(--cpd-color-blue-900)"
"username-colors": ["#ff0000", ...]
"avatar-background-colors": ["#cc0000", ...]
}
}, {
"name": "Deep Purple",
@ -91,6 +91,8 @@ e.g. in config.json:
}
```
`compound` may contain overrides for any [semantic design token](https://compound.element.io/?path=/docs/tokens-semantic-colors--docs) belonging to our design system. The above example shows how you might change the accent color to blue by setting the relevant semantic tokens to refer to blue [base tokens](https://compound.element.io/?path=/docs/tokens-color-palettes--docs).
`username-colors` is expected to contain 8 colors. `avatar-background-colors` is expected to contain 3 colors. Both values are optional and have fallbacks from the built-in theme.
These are exposed as `--username-colors_0`, ... and `--avatar-background-colors_0`, ... respectively in CSS.
All properties in `fonts` are optional, and will default to the standard Riot fonts.

View file

@ -2,25 +2,19 @@
## Requirements
- A working [Development Setup](../README.md#setting-up-a-dev-environment)
- Including up-to-date versions of matrix-react-sdk and matrix-js-sdk
- Latest LTS version of Node.js installed
- Be able to understand English
- A working [Development Setup](../README.md#setting-up-a-dev-environment)
- Including up-to-date versions of matrix-react-sdk and matrix-js-sdk
- Latest LTS version of Node.js installed
- Be able to understand English
- Be able to understand the language you want to translate Element into
## Translating strings vs. marking strings for translation
Translating strings are done with the `_t()` function found in matrix-react-sdk/lib/languageHandler.js.
It is recommended to call this function wherever you introduce a string constant which should be translated.
However, translating can not be performed until after the translation system has been initialized.
Thus, sometimes translation must be performed at a different location in the source code than where the string is introduced.
This breaks some tooling and makes it difficult to find translatable strings.
Therefore, there is the alternative `_td()` function which is used to mark strings for translation,
without actually performing the translation (which must still be performed separately, and after the translation system has been initialized).
Translating strings are done with the `_t()` function found in matrix-react-sdk/lib/languageHandler.js. It is recommended to call this function wherever you introduce a string constant which should be translated. However, translating can not be performed until after the translation system has been initialized. Thus, sometimes translation must be performed at a different location in the source code than where the string is introduced. This breaks some tooling and makes it difficult to find translatable strings. Therefore, there is the alternative `_td()` function which is used to mark strings for translation, without actually performing the translation (which must still be performed separately, and after the translation system has been initialized).
Basically, whenever a translatable string is introduced, you should call either `_t()` immediately OR `_td()` and later `_t()`.
Example:
```
// Module-level constant
const COLORS = {
@ -34,49 +28,36 @@ function getColorName(hex) {
}
```
## Key naming rules
These rules are based on https://github.com/element-hq/element-x-android/blob/develop/tools/localazy/README.md
At this time we are not trying to have a translation key per UI element as some methodologies use,
whilst that would offer the greatest flexibility, it would also make reuse between projects nigh impossible.
We are aiming for a set of common strings to be shared then some more localised translations per context they may appear in.
1. Ensure the string doesn't already exist in a related project, such as https://localazy.com/p/element
2. Keys for common strings, i.e. strings that can be used at multiple places must start by `action_` if this is a verb, or `common_` if not
3. Keys for common accessibility strings must start by `a11y_`. Example: `a11y_hide_password`
4. Otherwise, try to group keys logically and nest where appropriate, such as `keyboard_` for strings relating to keyboard shortcuts.
5. Ensure your translation keys do not include `.` or `|` or ` `. Try to balance string length against descriptiveness.
## Adding new strings
1. Check if the import `import { _t } from 'matrix-react-sdk/src/languageHandler';` is present. If not add it to the other import statements. Also import `_td` if needed.
1. Add `_t()` to your string passing the translation key you come up with based on the rules above. If the string is introduced at a point before the translation system has not yet been initialized, use `_td()` instead, and call `_t()` at the appropriate time.
1. Run `yarn i18n` to add the keys to `src/i18n/strings/en_EN.json`
1. Modify the new entries in `src/i18n/strings/en_EN.json` with the English (UK) translations for the added keys.
1. Check if the import ``import { _t } from 'matrix-react-sdk/lib/languageHandler';`` is present. If not add it to the other import statements. Also import `_td` if needed.
1. Add ``_t()`` to your string. (Don't forget curly braces when you assign an expression to JSX attributes in the render method). If the string is introduced at a point before the translation system has not yet been initialized, use `_td()` instead, and call `_t()` at the appropriate time.
1. Run `yarn i18n` to update ``src/i18n/strings/en_EN.json``
1. If you added a string with a plural, you can add other English plural variants to ``src/i18n/strings/en_EN.json`` (remeber to edit the one in the same project as the source file containing your new translation).
## Editing existing strings
Edits to existing strings should be performed only via Localazy.
There you can also require all translations to be redone if the meaning of the string has changed significantly.
1. Edit every occurrence of the string inside `_t()` and `_td()` in the JSX files.
1. Run `yarn i18n` to update `src/i18n/strings/en_EN.json`. (Be sure to run this in the same project as the JSX files you just edited.)
1. Run `yarn prunei18n` to remove the old string from `src/i18n/strings/*.json`.
## Adding variables inside a string.
1. Extend your `_t()` call. Instead of `_t(TKEY)` use `_t(TKEY, {})`
1. Extend your ``_t()`` call. Instead of ``_t(STRING)`` use ``_t(STRING, {})``
1. Decide how to name it. Please think about if the person who has to translate it can understand what it does. E.g. using the name 'recipient' is bad, because a translator does not know if it is the name of a person, an email address, a user ID, etc. Rather use e.g. recipientEmailAddress.
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.
1. Add it to the array in ``_t`` for example ``_t(STRING, {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).
- 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> })`.
- 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> })``.
## Things to know/Style Guides
- Do not use `_t()` inside `getDefaultProps`: the translations aren't loaded when `getDefaultProps` is called, leading to missing translations. Use `_td()` to indicate that `_t()` will be called on the string later.
- If using translated strings as constants, translated strings can't be in constants loaded at class-load time since the translations won't be loaded. Mark the strings using `_td()` instead and perform the actual translation later.
- If a string is presented in the UI with punctuation like a full stop, include this in the translation strings, since punctuation varies between languages too.
- Avoid "translation in parts", i.e. concatenating translated strings or using translated strings in variable substitutions. Context is important for translations, and translating partial strings this way is simply not always possible.
- Concatenating strings often also introduces an implicit assumption about word order (e.g. that the subject of the sentence comes first), which is incorrect for many languages.
- Translation 'smell test': If you have a string that does not begin with a capital letter (is not the start of a sentence) or it ends with e.g. ':' or a preposition (e.g. 'to') you should recheck that you are not trying to translate a partial sentence.
- If you have multiple strings, that are almost identical, except some part (e.g. a word or two) it is still better to translate the full sentence multiple times. It may seem like inefficient repetition, but unlike programming where you try to minimize repetition, translation is much faster if you have many, full, clear, sentences to work with, rather than fewer, but incomplete sentence fragments.
- Don't forget curly braces when you assign an expression to JSX attributes in the render method)
- Do not use `_t()` inside ``getDefaultProps``: the translations aren't loaded when `getDefaultProps` is called, leading to missing translations. Use `_td()` to indicate that `_t()` will be called on the string later.
- If using translated strings as constants, translated strings can't be in constants loaded at class-load time since the translations won't be loaded. Mark the strings using `_td()` instead and perform the actual translation later.
- If a string is presented in the UI with punctuation like a full stop, include this in the translation strings, since punctuation varies between languages too.
- Avoid "translation in parts", i.e. concatenating translated strings or using translated strings in variable substitutions. Context is important for translations, and translating partial strings this way is simply not always possible.
- Concatenating strings often also introduces an implicit assumption about word order (e.g. that the subject of the sentence comes first), which is incorrect for many languages.
- Translation 'smell test': If you have a string that does not begin with a capital letter (is not the start of a sentence) or it ends with e.g. ':' or a preposition (e.g. 'to') you should recheck that you are not trying to translate a partial sentence.
- If you have multiple strings, that are almost identical, except some part (e.g. a word or two) it is still better to translate the full sentence multiple times. It may seem like inefficient repetion, but unlike programming where you try to minimize repetition, translation is much faster if you have many, full, clear, sentences to work with, rather than fewer, but incomplete sentence fragments.

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