Compare commits
43 Commits
pse-335/do
...
jryans/p2p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7fd26c3af9 | ||
|
|
9d1bed29b2 | ||
|
|
1e051365b1 | ||
|
|
13251a4d6c | ||
|
|
b28708fbf3 | ||
|
|
46d659a936 | ||
|
|
9e19d910c1 | ||
|
|
92fe2b8935 | ||
|
|
7e15090364 | ||
|
|
d83c475bb7 | ||
|
|
b4c7d54fc0 | ||
|
|
e10d5eb0be | ||
|
|
ff6c4ac837 | ||
|
|
bcba891df1 | ||
|
|
708a7146d5 | ||
|
|
e4c67f39a6 | ||
|
|
a5ba31e127 | ||
|
|
f6aceba566 | ||
|
|
35bcc152ea | ||
|
|
ec45bb7976 | ||
|
|
b0fb043c2b | ||
|
|
4828869515 | ||
|
|
671315c36e | ||
|
|
9994c9ea65 | ||
|
|
9328519c29 | ||
|
|
330aa285e6 | ||
|
|
5c3f11a7c7 | ||
|
|
cdd32590fe | ||
|
|
52641c5674 | ||
|
|
6f43a14c43 | ||
|
|
d80285d971 | ||
|
|
3d74d336bf | ||
|
|
1f1f0f1264 | ||
|
|
bf13ec2285 | ||
|
|
4d1f969c4d | ||
|
|
0935ccd737 | ||
|
|
d2635bd282 | ||
|
|
462fa91938 | ||
|
|
836236ea9b | ||
|
|
3fcc3c8bfd | ||
|
|
349d3e3d47 | ||
|
|
8a41f956f6 | ||
|
|
80411d38f7 |
16
.env.example
16
.env.example
@@ -1,16 +0,0 @@
|
||||
# To enable CSS hot-reload, set the following variable to 1.
|
||||
CSS_HOT_RELOAD=1
|
||||
# To use the full page error dialog, set this to 1. Please report false positives to
|
||||
# the issue tracker for handling.
|
||||
FULL_PAGE_ERRORS=0
|
||||
# To use a single theme, uncomment the line with the theme you want to hot-reload.
|
||||
MATRIX_THEMES='light'
|
||||
#MATRIX_THEMES='dark'
|
||||
#MATRIX_THEMES='legacy-light'
|
||||
#MATRIX_THEMES='legacy-dark'
|
||||
#MATRIX_THEMES='light-custom'
|
||||
#MATRIX_THEMES='dark-custom'
|
||||
# You can also enable multiple themes by using a comma-separated list.
|
||||
# When multiple themes are enabled, switching between them may require a full page reload.
|
||||
# Note that compilation times are proportional to the number of enabled themes.
|
||||
#MATRIX_THEMES='light,dark'
|
||||
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
@@ -1 +0,0 @@
|
||||
* @vector-im/element-web
|
||||
48
.github/ISSUE_TEMPLATE.md
vendored
Normal file
48
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,48 @@
|
||||
<!-- A picture's worth a thousand words: PLEASE INCLUDE A SCREENSHOT :P -->
|
||||
|
||||
<!-- Please report security issues by email to security@matrix.org -->
|
||||
|
||||
<!-- This is a bug report template. By following the instructions below and
|
||||
filling out the sections with your information, you will help the us to get all
|
||||
the necessary data to fix your issue.
|
||||
|
||||
You can also preview your report before submitting it. You may remove sections
|
||||
that aren't relevant to your particular case.
|
||||
|
||||
Text between <!-- and --> marks will be invisible in the report.
|
||||
-->
|
||||
|
||||
### Description
|
||||
|
||||
Describe here the problem that you are experiencing, or the feature you are requesting.
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
- For bugs, list the steps
|
||||
- that reproduce the bug
|
||||
- using hyphens as bullet points
|
||||
|
||||
Describe how what happens differs from what you expected.
|
||||
|
||||
Log: sent/not sent? <!-- You can send us the app's logs via the 'Report bug'
|
||||
link on the 'Settings' page. Very important for hard-to-reproduce bugs. Please
|
||||
file a bug here too! -->
|
||||
|
||||
<!-- Include screenshots if possible: you can drag and drop images below. -->
|
||||
|
||||
### Version information
|
||||
|
||||
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
|
||||
|
||||
- **Platform**: web (in-browser) or desktop?
|
||||
|
||||
For the web app:
|
||||
|
||||
- **Browser**: Chrome, Firefox, Safari, Edge? which version?
|
||||
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
|
||||
- **URL**: develop.element.io / app.element.io / somewhere else? If a private server, what version of Element Web?
|
||||
|
||||
For the desktop app:
|
||||
|
||||
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
|
||||
- **Version**: 1.x.y <!-- check the user settings panel if unsure -->
|
||||
76
.github/ISSUE_TEMPLATE/bug-desktop.yml
vendored
76
.github/ISSUE_TEMPLATE/bug-desktop.yml
vendored
@@ -1,76 +0,0 @@
|
||||
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!
|
||||
|
||||
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
|
||||
84
.github/ISSUE_TEMPLATE/bug-web.yml
vendored
84
.github/ISSUE_TEMPLATE/bug-web.yml
vendored
@@ -1,84 +0,0 @@
|
||||
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!
|
||||
|
||||
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
|
||||
58
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
58
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: T-Defect
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
<!-- A picture's worth a thousand words: PLEASE INCLUDE A SCREENSHOT :P -->
|
||||
|
||||
<!-- Please report security issues by email to security@matrix.org -->
|
||||
|
||||
<!-- This is a bug report template. By following the instructions below and
|
||||
filling out the sections with your information, you will help the us to get all
|
||||
the necessary data to fix your issue.
|
||||
|
||||
You can also preview your report before submitting it. You may remove sections
|
||||
that aren't relevant to your particular case.
|
||||
|
||||
Text between <!-- and --> marks will be invisible in the report.
|
||||
-->
|
||||
|
||||
### Description
|
||||
|
||||
Describe here the problem that you are experiencing, or the feature you are requesting.
|
||||
|
||||
### Steps to reproduce
|
||||
|
||||
- For bugs, list the steps
|
||||
- that reproduce the bug
|
||||
- using hyphens as bullet points
|
||||
|
||||
Describe how what happens differs from what you expected.
|
||||
|
||||
<!-- Please send us logs for your bug report. They're very important for bugs
|
||||
which are hard to reproduce. To do this, create this issue then go to your
|
||||
account settings and click 'Submit Debug Logs' from the Help & About tab -->
|
||||
Logs being sent: yes/no
|
||||
|
||||
<!-- Include screenshots if possible: you can drag and drop images below. -->
|
||||
|
||||
### Version information
|
||||
|
||||
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
|
||||
|
||||
- **Platform**: web (in-browser) or desktop?
|
||||
|
||||
For the web app:
|
||||
|
||||
- **Browser**: Chrome, Firefox, Safari, Edge? which version?
|
||||
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
|
||||
- **URL**: develop.element.io / app.element.io / somewhere else? If a private server, what version of Element Web?
|
||||
|
||||
For the desktop app:
|
||||
|
||||
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
|
||||
- **Version**: 1.x.y <!-- check the user settings panel if unsure -->
|
||||
8
.github/ISSUE_TEMPLATE/config.ylm
vendored
8
.github/ISSUE_TEMPLATE/config.ylm
vendored
@@ -1,8 +0,0 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: Report a security vulnerability
|
||||
url: https://github.com/vector-im/element-web/security/policy
|
||||
about: Please review our security policy for more details
|
||||
- name: Questions & support
|
||||
url: https://matrix.to/#/#element-web:matrix.org
|
||||
about: Please ask and answer questions here.
|
||||
36
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
36
.github/ISSUE_TEMPLATE/enhancement.yml
vendored
@@ -1,36 +0,0 @@
|
||||
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 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?
|
||||
|
||||
#### 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
|
||||
20
.github/ISSUE_TEMPLATE/suggestion-or-feature-request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/suggestion-or-feature-request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Suggestion or Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: T-Enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
#### Is your suggestion related to a problem? Please describe.
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
#### Describe the solution you'd like.
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
#### Describe alternatives you've considered.
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
#### Additional context
|
||||
Add any other context or screenshots about the feature request here.
|
||||
12
.github/PULL_REQUEST_TEMPLATE.md
vendored
12
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -1,11 +1,3 @@
|
||||
<!-- Please read https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md before submitting your pull request -->
|
||||
<!-- Please read CONTRIBUTING.md before submitting your pull request -->
|
||||
|
||||
<!-- Include a Sign-Off as described in https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md#sign-off -->
|
||||
|
||||
<!-- 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>
|
||||
-->
|
||||
<!-- Include a Sign-Off at the end of your Pull Request (as described in CONTRIBUTING.md), or on every commit -->
|
||||
|
||||
12
.github/workflows/preview_changelog.yaml
vendored
12
.github/workflows/preview_changelog.yaml
vendored
@@ -1,12 +0,0 @@
|
||||
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 }}
|
||||
26
.github/workflows/sentry-sourcemaps.yaml
vendored
26
.github/workflows/sentry-sourcemaps.yaml
vendored
@@ -1,26 +0,0 @@
|
||||
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
|
||||
15
.github/workflows/triage-incoming.yml
vendored
15
.github/workflows/triage-incoming.yml
vendored
@@ -1,15 +0,0 @@
|
||||
name: Move new issues into Issue triage board
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
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 }}
|
||||
192
.github/workflows/triage-labelled.yml
vendored
192
.github/workflows/triage-labelled.yml
vendored
@@ -1,192 +0,0 @@
|
||||
name: Move labelled issues to correct boards and columns
|
||||
|
||||
on:
|
||||
issues:
|
||||
types: [labeled]
|
||||
|
||||
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-Threads') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
|
||||
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')
|
||||
steps:
|
||||
- uses: actions/github-script@v5
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.addLabels({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
labels: ['Z-Labs']
|
||||
})
|
||||
|
||||
move_needs_info_issues:
|
||||
name: X-Needs-Info issues to Need info column 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: 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') &&
|
||||
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:ID!,$contentid:ID!) {
|
||||
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 }}
|
||||
|
||||
add_product_issues:
|
||||
name: X-Needs-Product to Design project board
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'X-Needs-Product')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
id: add_to_project
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc4AAg6N"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
|
||||
Delight_issues_to_board:
|
||||
name: Delight issues to 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') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-IA')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
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: A-Voice Messages to voice message board
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'A-Voice Messages')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
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: 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:ID!,$contentid:ID!) {
|
||||
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 }}
|
||||
|
||||
move_message_bubbles_issues:
|
||||
name: A-Message-Bubbles to Message bubbles board
|
||||
runs-on: ubuntu-latest
|
||||
if: >
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles')
|
||||
steps:
|
||||
- uses: octokit/graphql-action@v2.x
|
||||
with:
|
||||
headers: '{"GraphQL-Features": "projects_next_graphql"}'
|
||||
query: |
|
||||
mutation add_to_project($projectid:ID!,$contentid:ID!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.issue.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc3m-g"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
139
.github/workflows/triage-move-review-requests.yml
vendored
139
.github/workflows/triage-move-review-requests.yml
vendored
@@ -1,139 +0,0 @@
|
||||
name: Move pull requests asking for review to the relevant project
|
||||
on:
|
||||
pull_request_target:
|
||||
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: "vector-im") {
|
||||
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 "::set-output name=match::true"
|
||||
elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then
|
||||
echo "::set-output name=match::true"
|
||||
else
|
||||
echo "::set-output name=match::false"
|
||||
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!) {
|
||||
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 }}
|
||||
|
||||
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: "vector-im") {
|
||||
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 "::set-output name=match::true"
|
||||
elif [ $(join /tmp/team.txt /tmp/team_reviewers.txt | wc -l) != 0 ]; then
|
||||
echo "::set-output name=match::true"
|
||||
else
|
||||
echo "::set-output name=match::false"
|
||||
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!) {
|
||||
addProjectNextItem(input:{projectId:$projectid contentId:$contentid}) {
|
||||
projectNextItem {
|
||||
id
|
||||
}
|
||||
}
|
||||
}
|
||||
projectid: ${{ env.PROJECT_ID }}
|
||||
contentid: ${{ github.event.pull_request.node_id }}
|
||||
env:
|
||||
PROJECT_ID: "PN_kwDOAM0swc4AAg6N"
|
||||
TEAM: "product"
|
||||
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
|
||||
56
.github/workflows/triage-priority-bugs.yml
vendored
56
.github/workflows/triage-priority-bugs.yml
vendored
@@ -1,56 +0,0 @@
|
||||
name: Move P1 bugs to boards
|
||||
|
||||
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, 'Z-UISI') ||
|
||||
(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 }}
|
||||
61
.github/workflows/triage-unlabelled.yml
vendored
61
.github/workflows/triage-unlabelled.yml
vendored
@@ -1,61 +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: |
|
||||
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 }}
|
||||
|
||||
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-Threads') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Polls') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
|
||||
contains(github.event.issue.labels.*.name, 'A-Message-Bubbles') ||
|
||||
contains(github.event.issue.labels.*.name, 'Z-IA') ||
|
||||
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, 'Z-Labs')
|
||||
steps:
|
||||
- uses: actions/github-script@v5
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.removeLabel({
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
name: ['Z-Labs']
|
||||
})
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -19,6 +19,3 @@ electron/pub
|
||||
/src/component-index.js
|
||||
/.tmp
|
||||
/webpack-stats.json
|
||||
.vscode
|
||||
.vscode/
|
||||
.env
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
{
|
||||
"minify": true,
|
||||
"enableClasses": false,
|
||||
"classPrefix": "modernizr_",
|
||||
"options": [
|
||||
"setClasses"
|
||||
],
|
||||
"feature-detects": [
|
||||
"test/css/animations",
|
||||
"test/css/displaytable",
|
||||
|
||||
1243
CHANGELOG.md
1243
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -1,4 +0,0 @@
|
||||
Contributing code to Element
|
||||
============================
|
||||
|
||||
Element follows the same pattern as the [matrix-js-sdk](https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md).
|
||||
4
CONTRIBUTING.rst
Normal file
4
CONTRIBUTING.rst
Normal file
@@ -0,0 +1,4 @@
|
||||
Contributing code to Element
|
||||
============================
|
||||
|
||||
Element follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.rst.
|
||||
15
Dockerfile
15
Dockerfile
@@ -9,19 +9,25 @@ ARG REACT_SDK_BRANCH="master"
|
||||
ARG JS_SDK_REPO="https://github.com/matrix-org/matrix-js-sdk.git"
|
||||
ARG JS_SDK_BRANCH="master"
|
||||
|
||||
RUN apt-get update && apt-get install -y git dos2unix
|
||||
RUN apt-get update && apt-get install -y git dos2unix \
|
||||
# These packages are required for building Canvas on architectures like Arm
|
||||
# See https://www.npmjs.com/package/canvas#compiling
|
||||
build-essential libcairo2-dev libpango1.0-dev libjpeg-dev libgif-dev librsvg2-dev
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
COPY . /src
|
||||
RUN dos2unix /src/scripts/docker-link-repos.sh && bash /src/scripts/docker-link-repos.sh
|
||||
RUN yarn --network-timeout=100000 install
|
||||
|
||||
RUN dos2unix /src/scripts/docker-package.sh && bash /src/scripts/docker-package.sh
|
||||
RUN yarn build
|
||||
|
||||
# Copy the config now so that we don't create another layer in the app image
|
||||
RUN cp /src/config.sample.json /src/webapp/config.json
|
||||
|
||||
# Ensure we populate the version file
|
||||
RUN dos2unix /src/scripts/docker-write-version.sh && bash /src/scripts/docker-write-version.sh
|
||||
|
||||
|
||||
# App
|
||||
FROM nginx:alpine
|
||||
|
||||
@@ -30,8 +36,5 @@ 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
|
||||
|
||||
RUN rm -rf /usr/share/nginx/html \
|
||||
&& ln -s /app /usr/share/nginx/html
|
||||
|
||||
142
README.md
142
README.md
@@ -30,14 +30,14 @@ and [element-ios](https://github.com/vector-im/element-ios).
|
||||
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>
|
||||
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 copy of Element, the quickest bet is to use a pre-built
|
||||
released version of Element:
|
||||
|
||||
1. Download the latest version from <https://github.com/vector-im/element-web/releases>
|
||||
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)
|
||||
@@ -46,7 +46,7 @@ released version of Element:
|
||||
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.riot.im/element-release-key.asc>.
|
||||
at https://packages.riot.im/element-release-key.asc.
|
||||
|
||||
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
|
||||
@@ -72,7 +72,7 @@ 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/vector-im/element-web/issues/1977> for more details.
|
||||
https://github.com/vector-im/element-web/issues/1977 for more details.
|
||||
|
||||
Configuration best practices
|
||||
----------------------------
|
||||
@@ -80,15 +80,15 @@ 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
|
||||
- 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`
|
||||
- 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
|
||||
- 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
|
||||
- The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in
|
||||
legacy browsers.
|
||||
|
||||
[mime-sniffing]:
|
||||
@@ -122,15 +122,15 @@ 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 v14.x.
|
||||
1. Install or update `node.js` so that your `node` is at least v10.x.
|
||||
1. Install `yarn` if not present already.
|
||||
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
|
||||
can use https://develop.element.io - the continuous integration release of
|
||||
the develop branch.
|
||||
1. Configure the app by copying `config.sample.json` to `config.json` and
|
||||
modifying it. See the [configuration docs](docs/config.md) for details.
|
||||
@@ -148,16 +148,15 @@ 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,
|
||||
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/vector-im/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.
|
||||
|
||||
Other options for running as a desktop app:
|
||||
|
||||
* @asdf:matrix.org points out that you can use nativefier and it just works(tm)
|
||||
* @asdf:matrix.org points out that you can use nativefier and it just works(tm)
|
||||
|
||||
```bash
|
||||
yarn global add nativefier
|
||||
@@ -172,7 +171,6 @@ 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
|
||||
```
|
||||
@@ -180,13 +178,11 @@ 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
|
||||
@@ -196,7 +192,6 @@ 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 \
|
||||
@@ -229,7 +224,6 @@ Caching requirements
|
||||
====================
|
||||
|
||||
Element requires the following URLs not to be cached, when/if you are serving Element from your own webserver:
|
||||
|
||||
```
|
||||
/config.*.json
|
||||
/i18n
|
||||
@@ -238,11 +232,6 @@ Element requires the following URLs not to be cached, when/if you are serving El
|
||||
/index.html
|
||||
```
|
||||
|
||||
We also recommend that you force browsers to re-validate any cached copy of Element on page load by configuring your
|
||||
webserver to return `Cache-Control: no-cache` for `/`. This ensures the browser will fetch a new version of Element on
|
||||
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
|
||||
===========
|
||||
|
||||
@@ -272,10 +261,6 @@ 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.
|
||||
|
||||
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
|
||||
============================
|
||||
|
||||
@@ -313,19 +298,17 @@ cd element-web
|
||||
yarn link matrix-js-sdk
|
||||
yarn link matrix-react-sdk
|
||||
yarn install
|
||||
yarn reskindex
|
||||
yarn start
|
||||
```
|
||||
|
||||
Wait a few seconds for the initial build to finish; you should see something like:
|
||||
|
||||
Wait a few seconds for the initial build to finish; you should see something like:
|
||||
```
|
||||
[element-js] <s> [webpack.Progress] 100%
|
||||
[element-js]
|
||||
[element-js] ℹ 「wdm」: 1840 modules
|
||||
[element-js] ℹ 「wdm」: Compiled successfully.
|
||||
```
|
||||
|
||||
Remember, the command will not terminate since it runs the web server
|
||||
and rebuilds source files when they change. This development server also
|
||||
disables caching, so do NOT use it in production.
|
||||
@@ -333,7 +316,7 @@ Wait a few seconds for the initial build to finish; you should see something lik
|
||||
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.
|
||||
Open http://127.0.0.1:8080/ in your browser to see your newly built Element.
|
||||
|
||||
**Note**: The build script uses inotify by default on Linux to monitor directories
|
||||
for changes. If the inotify limits are too low your build will fail silently or with
|
||||
@@ -375,11 +358,20 @@ 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
|
||||
|
||||
@@ -397,6 +389,76 @@ For a developer guide, see the [translating dev doc](docs/translating-dev.md).
|
||||
Triaging 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 strive to completely cover all applicable issues with these core labels:
|
||||
|
||||
We use [issue labels](https://github.com/vector-im/element-meta/wiki/Issue-labelling) to sort all incoming issues.
|
||||
1. __Type__ — Every issue is assigned a type:
|
||||
- __[T-Defect](https://github.com/vector-im/element-web/labels/T-Defect):__
|
||||
Bugs, crashes, hangs, vulnerabilities, or other reported problems
|
||||
- __[T-Enhancement](https://github.com/vector-im/element-web/labels/T-Enhancement):__
|
||||
New features, changes in functionality, performance boosts, user-facing
|
||||
improvements
|
||||
- __[T-Task](https://github.com/vector-im/element-web/labels/T-Task):__
|
||||
Refactoring, enabling or disabling functionality, other engineering tasks
|
||||
- __[T-Other](https://github.com/vector-im/element-web/labels/T-Other):__
|
||||
Questions, user support, anything else
|
||||
|
||||
2. __Severity__ — All issues labeled `T-Defect` are also assigned a severity:
|
||||
* __[S-Critical](https://github.com/vector-im/element-web/labels/S-Critical):__
|
||||
Prevents work, causes data loss, affects many users, and/or has no
|
||||
workaround
|
||||
* __[S-Major](https://github.com/vector-im/element-web/labels/S-Major):__
|
||||
Severely degrades major functionality or product features, with no
|
||||
satisfactory workaround
|
||||
* __[S-Minor](https://github.com/vector-im/element-web/labels/S-Minor):__
|
||||
Impairs non-critical functionality, or suitable workarounds exist
|
||||
* __[S-Tolerable](https://github.com/vector-im/element-web/labels/S-Tolerable):__
|
||||
Purely cosmetic or low / no impact to users
|
||||
|
||||
3. __Priority__ — All issues which are not `T-Other` are assigned a priority:
|
||||
* __[P1](https://github.com/vector-im/element-web/labels/P1):__ Next
|
||||
* __[P2](https://github.com/vector-im/element-web/labels/P2):__ Later
|
||||
* __[P3](https://github.com/vector-im/element-web/labels/P3):__ Eventually
|
||||
* __[P4](https://github.com/vector-im/element-web/labels/P4):__ Interesting —
|
||||
Not yet scheduled, will accept patches
|
||||
* __[P5](https://github.com/vector-im/element-web/labels/P5):__ Dubious —
|
||||
Will not schedule, would consider patches
|
||||
|
||||
4. __Area__ — Most issues are assigned one or several "areas" using one of the
|
||||
many `A-` prefixed labels, e.g. `A-Composer` or `A-Spaces`. Each area label
|
||||
maps to a group of features or portion of the UI surface in the app.
|
||||
|
||||
### Other common labels
|
||||
|
||||
We have a handful of other labels which are added on an as-needed basis, and not expected to be exhaustive:
|
||||
|
||||
* __Exceptions__ — Special flags for issues and pull requests:
|
||||
* __[X-Needs-Info](https://github.com/vector-im/element-web/labels/X-Needs-Info):__
|
||||
This issue is blocked pending further information from the reporter
|
||||
* __[X-Regression](https://github.com/vector-im/element-web/labels/X-Regression):__
|
||||
Denotes things breaking which previously worked
|
||||
* __[X-Release-Blocker](https://github.com/vector-im/element-web/labels/X-Release-Blocker):__
|
||||
Issues which must be resolved before making a release
|
||||
|
||||
* __[Easy](https://github.com/vector-im/element-web/labels/Easy)__ / __[Help
|
||||
Wanted](https://github.com/vector-im/element-web/labels/Help%20Wanted)__ —
|
||||
Well-defined issues which are suitable for folks new to the codebase
|
||||
|
||||
* __[A11y](https://github.com/vector-im/element-web/labels/A11y)__ /
|
||||
__[Meta](https://github.com/vector-im/element-web/labels/Meta)__ /
|
||||
__[I18n](https://github.com/vector-im/element-web/labels/I18n)__ /
|
||||
__[Privacy](https://github.com/vector-im/element-web/labels/Privacy)__ /
|
||||
__[Security](https://github.com/vector-im/element-web/labels/Security)__ —
|
||||
Issues which fall under these conceptual themes (which apply to many software
|
||||
projects and are not specific to Element)
|
||||
|
||||
* __[Sponsored](https://github.com/vector-im/element-web/labels/Sponsored)__ —
|
||||
Used internally by Element to denote issues with external funding
|
||||
|
||||
### Ad hoc labels (`Z-`)
|
||||
|
||||
We have reserved the `Z-` prefix for ad hoc labels.
|
||||
|
||||
Any member of the core team is welcome to create labels beginning with `Z-` for
|
||||
any purpose, such as tracking personal areas of interest or providing a common
|
||||
way to label cross-repo initiatives. The prefix avoids interference with the
|
||||
project's main labels.
|
||||
|
||||
@@ -23,7 +23,6 @@
|
||||
"https://scalar-staging.riot.im/scalar/api"
|
||||
],
|
||||
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||
"uisi_autorageshake_app": "element-auto-uisi",
|
||||
"defaultCountryCode": "GB",
|
||||
"showLabsSettings": false,
|
||||
"features": { },
|
||||
@@ -48,6 +47,6 @@
|
||||
"breadcrumbs": true
|
||||
},
|
||||
"jitsi": {
|
||||
"preferredDomain": "meet.element.io"
|
||||
"preferredDomain": "jitsi.riot.im"
|
||||
}
|
||||
}
|
||||
|
||||
107
docs/config.md
107
docs/config.md
@@ -22,19 +22,9 @@ For a good example, see https://develop.element.io/config.json.
|
||||
`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. `sso_immediate_redirect`: When `true`, Element will assume the default server supports SSO
|
||||
and attempt to send the user there to continue (if they aren't already logged in). Default
|
||||
`false`. Note that this disables all usage of the welcome page.
|
||||
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
|
||||
@@ -93,7 +83,7 @@ For a good example, see https://develop.element.io/config.json.
|
||||
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). See [Settings section](#settings)
|
||||
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.
|
||||
@@ -103,7 +93,7 @@ For a good example, see https://develop.element.io/config.json.
|
||||
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 `meet.element.io`. This is used whenever a user clicks on the voice/video
|
||||
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
|
||||
@@ -146,16 +136,6 @@ For a good example, see https://develop.element.io/config.json.
|
||||
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
|
||||
1. `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'
|
||||
1. `analyticsOwner`: The entity that analytics data is being sent to. Used in copy
|
||||
when explaining to the user where data is being sent. If not set, defaults to `brand`.
|
||||
|
||||
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
|
||||
@@ -200,80 +180,8 @@ Desktop app configuration
|
||||
|
||||
See https://github.com/vector-im/element-desktop#user-specified-configjson
|
||||
|
||||
# Settings
|
||||
|
||||
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).
|
||||
|
||||
## Supported settings
|
||||
|
||||
* `alwaysShowTimestamps`: boolean
|
||||
* `analyticsOptIn`: boolean
|
||||
* `autocompleteDelay`: number
|
||||
* `automaticErrorReporting`: boolean
|
||||
* `autoplayGifs`: boolean
|
||||
* `autoplayVideo`: boolean
|
||||
* `baseFontSize`: number
|
||||
* `breadcrumbs`: boolean
|
||||
* `ctrlFForSearch`: boolean
|
||||
* `custom_themes`
|
||||
* `developerMode`: boolean
|
||||
* `enableSyntaxHighlightLanguageDetection`: boolean
|
||||
* `enableWidgetScreenshots`: boolean
|
||||
* `expandCodeByDefault`: boolean
|
||||
* `forceRoomExportParameters` - Override room export parameters. Accepts an object:
|
||||
```
|
||||
{
|
||||
range: 'Beginning' | 'Timeline' | 'LastNMessages',
|
||||
sizeMb: number, // max 100gb
|
||||
format: 'Html' | 'PlainText' | 'Json',
|
||||
numberOfMessages: number,
|
||||
includeAttachments: boolean,
|
||||
}
|
||||
```
|
||||
* `Images.size`: 'normal' | 'large'
|
||||
* `language`: ISO language code
|
||||
* `layout`: 'irc' | 'group' | 'bubble'
|
||||
* `lowBandwidth`: boolean
|
||||
* `MessageComposerInput.autoReplaceEmoji`: boolean
|
||||
* `MessageComposerInput.ctrlEnterToSend`: boolean
|
||||
* `MessageComposerInput.isRichTextEnabled`: boolean
|
||||
* `MessageComposerInput.showFormatting`: boolean
|
||||
* `MessageComposerInput.showLocationButton`: boolean
|
||||
* `MessageComposerInput.showStickersButton`: boolean
|
||||
* `MessageComposerInput.suggestEmoji`: boolean
|
||||
* `MessageComposerInput.surroundWith`: boolean
|
||||
* `Pill.shouldShowPillAvatar`: boolean
|
||||
* `promptBeforeInviteUnknownUsers`: boolean
|
||||
* `readMarkerInViewThresholdMs`: number
|
||||
* `readMarkerOutOfViewThresholdMs`: number
|
||||
* `RoomList.backgroundImage`
|
||||
* `scrollToBottomOnMessageSent`: boolean
|
||||
* `showAvatarChanges`: boolean
|
||||
* `showCallButtonsInComposer`: boolean
|
||||
* `showChatEffects`: boolean
|
||||
* `showCodeLineNumbers`: boolean
|
||||
* `showCookieBar`: boolean
|
||||
* `showDeveloperTools`: boolean
|
||||
* `showDisplaynameChanges`: boolean
|
||||
* `showImages`: boolean
|
||||
* `showJoinLeaves`: boolean
|
||||
* `showReadReceipts`: boolean
|
||||
* `showRedactions`: boolean
|
||||
* `showTwelveHourTimestamps`: boolean
|
||||
* `showTypingNotifications`: boolean
|
||||
* `Spaces.allRoomsInHome`: boolean
|
||||
* `TagPanel.enableTagPanel`: boolean
|
||||
* `TextualBody.enableBigEmoji`: boolean
|
||||
* `urlPreviewsEnabled`: boolean
|
||||
* `useCustomFontSize`: number
|
||||
* `VideoView.flipVideoHorizontally`: boolean
|
||||
* `webRtcAllowPeerToPeer`: boolean
|
||||
* `Widgets.leftPanel`
|
||||
|
||||
## UI Features
|
||||
UI Features
|
||||
===========
|
||||
|
||||
Parts of the UI can be disabled using UI features. These are settings which appear
|
||||
under `settingDefaults` and can only be `true` (default) or `false`. When `false`,
|
||||
@@ -312,4 +220,3 @@ Currently, the following UI feature flags are supported:
|
||||
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.
|
||||
|
||||
@@ -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,10 +16,6 @@ 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.
|
||||
@@ -34,17 +30,17 @@ to your [config](./config.md) the following:
|
||||
}
|
||||
```
|
||||
|
||||
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
|
||||
{
|
||||
@@ -59,12 +55,19 @@ 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/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.json` (meet.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.
|
||||
|
||||
Element Android manages allowed native widgets permissions a bit differently than web widgets (as the data shared are different and never shared with the widget URL). For Jitsi widgets, permissions are requested only once per domain (consent saved in account data).
|
||||
|
||||
## Element iOS
|
||||
|
||||
Currently the Element mobile apps do not support custom Jitsi servers and will instead
|
||||
use the default `jitsi.riot.im` server. When users on the mobile apps join the call,
|
||||
they will be joining a different conference which has the same name, but not the same
|
||||
participants. This is a known bug and which needs to be fixed.
|
||||
|
||||
@@ -84,7 +84,7 @@ Then you can deploy it to your cluster with something like `kubectl apply -f my-
|
||||
"breadcrumbs": true
|
||||
},
|
||||
"jitsi": {
|
||||
"preferredDomain": "meet.element.io"
|
||||
"preferredDomain": "jitsi.riot.im"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
67
docs/labs.md
67
docs/labs.md
@@ -12,6 +12,14 @@ dropped. Ask in the room if you are unclear about any details here.**
|
||||
A new version of the "Report" dialog that lets users send abuse reports directly to room moderators,
|
||||
if the room supports it.
|
||||
|
||||
## Matrix Spaces [MSC1772](https://github.com/matrix-org/matrix-doc/pull/1772) support (`feature_spaces`)
|
||||
|
||||
Enables showing, using, creating, and managing spaces. Create Spaces from the all new Space Panel (to left of Room List).
|
||||
|
||||
Incompatible with (will disable) `feature_custom_tags`, `feature_communities_v2_prototypes` and stable Communities/Groups support.
|
||||
|
||||
Still in heavy development.
|
||||
|
||||
## Render LaTeX maths in messages (`feature_latex_maths`)
|
||||
|
||||
Enables rendering of LaTeX maths in messages using [KaTeX](https://katex.org/). LaTeX between single dollar-signs is interpreted as inline maths and double dollar-signs as display maths (i.e. centred on its own line).
|
||||
@@ -117,58 +125,15 @@ or feedback for this functionality at this time.
|
||||
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).
|
||||
|
||||
## Voice messages (`feature_voice_messages`)
|
||||
|
||||
Offers a way to send more time-sensitive information through the power of voice. When enabled, use the microphone
|
||||
icon on the lower right to start recording your message. You will have a chance to review after you're done recording,
|
||||
and if it sounds fine then send it off for the rest of the room to hear.
|
||||
|
||||
Voice messages are automatically downloaded to ensure they are ready for playback as soon as possible.
|
||||
|
||||
## Do not disturb (`feature_dnd`)
|
||||
|
||||
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.
|
||||
|
||||
## Hidden read receipts (`feature_hidden_read_receipts`)
|
||||
|
||||
Enables sending hidden read receipts as per [MSC2285](https://github.com/matrix-org/matrix-doc/pull/2285)
|
||||
|
||||
## Location sharing (`feature_location_share`) [In Development]
|
||||
|
||||
Allows users to send and display location data using [maplibre](https://maplibre.org).
|
||||
|
||||
The current implementation is a quick in-progress development spike to
|
||||
demonstrate viability and prove [MSC3488](https://github.com/matrix-org/matrix-doc/pull/3488)
|
||||
and [MSC3489](https://github.com/matrix-org/matrix-doc/pull/3489) - **the UI has not yet
|
||||
been designed, and it will not exit labs until it has**.
|
||||
|
||||
For this to work, you must specify the URL of a valid map tile server style file in
|
||||
the `map_style_url` setting in config.json.
|
||||
For example: "https://api.maptiler.com/maps/streets/style.json?key=YOUR_KEY_GOES_HERE"`
|
||||
|
||||
## Breadcrumbs v2 (`feature_breadcrumbs_v2`)
|
||||
|
||||
Instead of showing the horizontal list of breadcrumbs under the filter field, the new UX is an interactive context menu
|
||||
triggered by the button to the right of the filter field.
|
||||
|
||||
## Spotlight search (`feature_spotlight`) [In Development]
|
||||
|
||||
Switches to a new room search experience.
|
||||
|
||||
## Extensible events rendering (`feature_extensible_events`) [In Development]
|
||||
|
||||
*Intended for developer use only at the moment.*
|
||||
|
||||
Extensible Events are a [new event format](https://github.com/matrix-org/matrix-doc/pull/1767) which
|
||||
supports graceful fallback in unknown event types. Instead of rendering nothing or a blank space, events
|
||||
can define a series of other events which represent the event's information but in different ways. The
|
||||
base of these fallbacks being text.
|
||||
|
||||
Turning this flag on indicates that, when possible, the extensible events structure should be parsed on
|
||||
supported event types. This should lead to zero perceptual change in the timeline except in cases where
|
||||
the sender is using unknown/unrecognised event types.
|
||||
|
||||
Sending events with extensible events structure is always enabled - this should not affect any downstream
|
||||
client.
|
||||
|
||||
## Right panel stays open (`feature_right_panel_default_open`)
|
||||
|
||||
This is an experimental default open right panel mode as a quick fix for those
|
||||
who prefer to have the right panel open consistently across rooms.
|
||||
|
||||
If no right panel state is known for the room or it was closed on the last room
|
||||
visit, it will default to the room member list. Otherwise, the saved card last
|
||||
used in that room is shown.
|
||||
|
||||
@@ -5,7 +5,10 @@ automatically set up a preview site with a full deployment of Element with the
|
||||
changes from the pull request added in so that anyone can easily test and review
|
||||
them. This is especially useful for checking visual and interactive changes.
|
||||
|
||||
To access the preview site, click the link in the description of the PR.
|
||||
To access the preview site, scroll down to the bottom of the PR where the
|
||||
various CI results are displayed:
|
||||
|
||||

|
||||
|
||||
The checks section could be collapsed at first, so you may need to click "Show
|
||||
all checks" to reveal them. Look for an entry that mentions `deploy-preview`. It
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
## Requirements
|
||||
|
||||
- A working [Development Setup](../README.md#setting-up-a-dev-environment)
|
||||
- A working [Development Setup](../../#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
|
||||
|
||||
@@ -8,9 +8,8 @@
|
||||
|
||||
## Step 0: Join #element-translations:matrix.org
|
||||
|
||||
1. Come and join https://matrix.to/#/#element-translations:matrix.org for general discussion
|
||||
2. Join https://matrix.to/#/#element-translators:matrix.org for language-specific rooms
|
||||
3. Read scrollback and/or ask if anyone else is working on your language, and co-ordinate if needed. In general little-or-no coordination is needed though :)
|
||||
1. Come and join https://matrix.to/#/#element-translations:matrix.org
|
||||
2. Read scrollback and/or ask if anyone else is working on your language, and co-ordinate if needed. In general little-or-no coordination is needed though :)
|
||||
|
||||
## Step 1: Preparing your Weblate Profile
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
],
|
||||
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
|
||||
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||
"uisi_autorageshake_app": "element-auto-uisi",
|
||||
"showLabsSettings": false,
|
||||
"piwik": {
|
||||
"url": "https://piwik.riot.im/",
|
||||
@@ -49,9 +48,5 @@
|
||||
"privacyPolicyUrl": "https://element.io/privacy",
|
||||
"termsOfServiceUrl": "https://element.io/terms-of-service",
|
||||
"url": "https://ems.element.io/element-home/in-app-loader"
|
||||
},
|
||||
"posthog": {
|
||||
"projectApiKey": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
|
||||
"apiHost": "https://posthog.hss.element.io"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
],
|
||||
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
|
||||
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||
"uisi_autorageshake_app": "element-auto-uisi",
|
||||
"showLabsSettings": true,
|
||||
"piwik": {
|
||||
"url": "https://piwik.riot.im/",
|
||||
@@ -49,15 +48,5 @@
|
||||
"privacyPolicyUrl": "https://element.io/privacy",
|
||||
"termsOfServiceUrl": "https://element.io/terms-of-service",
|
||||
"url": "https://ems.element.io/element-home/in-app-loader"
|
||||
},
|
||||
"sentry": {
|
||||
"dsn": "https://029a0eb289f942508ae0fb17935bd8c5@sentry.matrix.org/6",
|
||||
"environment": "develop"
|
||||
},
|
||||
"posthog": {
|
||||
"projectApiKey": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
|
||||
"apiHost": "https://posthog.hss.element.io"
|
||||
},
|
||||
"features": {},
|
||||
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name localhost;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
index index.html;
|
||||
|
||||
# Set no-cache for the index.html only so that browsers always check for a new copy of Element Web.
|
||||
location = /index.html {
|
||||
add_header Cache-Control "no-cache";
|
||||
}
|
||||
|
||||
# redirect server error pages to the static page /50x.html
|
||||
#
|
||||
error_page 500 502 503 504 /50x.html;
|
||||
}
|
||||
|
||||
66
package.json
66
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "element-web",
|
||||
"version": "1.9.9",
|
||||
"version": "1.7.31",
|
||||
"description": "A feature-rich client for Matrix.org",
|
||||
"author": "New Vector Ltd.",
|
||||
"repository": {
|
||||
@@ -46,27 +46,29 @@
|
||||
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n reskindex,reskindex-react,res,element-js \"yarn reskindex:watch\" \"yarn reskindex:watch-react\" \"yarn start:res\" \"yarn start:js\"",
|
||||
"start:https": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n reskindex,reskindex-react,res,element-js \"yarn reskindex:watch\" \"yarn reskindex:watch-react\" \"yarn start:res\" \"yarn start:js --https\"",
|
||||
"start:res": "yarn build:jitsi && node scripts/copy-res.js -w",
|
||||
"start:js": "webpack-dev-server --host=0.0.0.0 --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --mode development --disable-host-check --hot",
|
||||
"start:js": "webpack-dev-server --host=0.0.0.0 --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --progress --mode development --disable-host-check",
|
||||
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
|
||||
"lint:js": "eslint --max-warnings 0 src",
|
||||
"lint:js-fix": "eslint --fix src",
|
||||
"lint:js": "eslint src",
|
||||
"lint:types": "tsc --noEmit --jsx react",
|
||||
"lint:style": "stylelint 'res/css/**/*.scss'",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.8.tgz",
|
||||
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz",
|
||||
"browser-request": "^0.3.3",
|
||||
"gfm.css": "^1.1.2",
|
||||
"highlight.js": "^10.5.0",
|
||||
"jsrsasign": "^10.2.0",
|
||||
"katex": "^0.12.0",
|
||||
"localforage": "^1.7.3",
|
||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
|
||||
"matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop",
|
||||
"matrix-widget-api": "^0.1.0-beta.18",
|
||||
"matrix-widget-api": "^0.1.0-beta.15",
|
||||
"prop-types": "^15.7.2",
|
||||
"react": "17.0.2",
|
||||
"react-dom": "17.0.2",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"sanitize-html": "^2.3.2",
|
||||
"sql.js": "github:neilalexander/sql.js#252a72bf57b0538cbd49bbd6f70af71e516966ae",
|
||||
"ua-parser-js": "^0.7.24"
|
||||
},
|
||||
"devDependencies": {
|
||||
@@ -87,31 +89,26 @@
|
||||
"@babel/preset-typescript": "^7.12.7",
|
||||
"@babel/register": "^7.12.10",
|
||||
"@babel/runtime": "^7.12.5",
|
||||
"@pmmmwh/react-refresh-webpack-plugin": "^0.4.3",
|
||||
"@principalstudio/html-webpack-inject-preload": "^1.2.7",
|
||||
"@sentry/webpack-plugin": "^1.18.1",
|
||||
"@types/flux": "^3.1.9",
|
||||
"@types/jest": "^27.0.2",
|
||||
"@types/modernizr": "^3.5.3",
|
||||
"@types/node": "^14.14.22",
|
||||
"@types/react": "17.0.14",
|
||||
"@types/react-dom": "17.0.9",
|
||||
"@types/react": "^17.0.2",
|
||||
"@types/react-dom": "^17.0.2",
|
||||
"@types/sanitize-html": "^2.3.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.6.0",
|
||||
"@typescript-eslint/parser": "^5.6.0",
|
||||
"allchange": "^1.0.6",
|
||||
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||
"@typescript-eslint/parser": "^4.17.0",
|
||||
"autoprefixer": "^9.8.6",
|
||||
"babel-jest": "^26.6.3",
|
||||
"babel-loader": "^8.2.2",
|
||||
"canvas": "^2.6.1",
|
||||
"chokidar": "^3.5.1",
|
||||
"concurrently": "^5.3.0",
|
||||
"cpx": "^1.5.0",
|
||||
"css-loader": "^3.6.0",
|
||||
"dotenv": "^10.0.0",
|
||||
"eslint": "7.18.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-matrix-org": "^0.4.0",
|
||||
"eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main",
|
||||
"eslint-plugin-react": "^7.22.0",
|
||||
"eslint-plugin-react-hooks": "^4.2.0",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
@@ -121,18 +118,18 @@
|
||||
"html-webpack-plugin": "^4.5.2",
|
||||
"jest": "^26.6.3",
|
||||
"jest-environment-jsdom-sixteen": "^1.0.3",
|
||||
"jest-raw-loader": "^1.0.1",
|
||||
"json-loader": "^0.5.7",
|
||||
"loader-utils": "^1.4.0",
|
||||
"matrix-mock-request": "^1.2.3",
|
||||
"matrix-react-test-utils": "^0.2.3",
|
||||
"matrix-web-i18n": "^1.2.0",
|
||||
"matrix-web-i18n": "github:matrix-org/matrix-web-i18n",
|
||||
"mini-css-extract-plugin": "^0.12.0",
|
||||
"minimist": "^1.2.5",
|
||||
"mkdirp": "^1.0.4",
|
||||
"modernizr": "^3.11.7",
|
||||
"node-fetch": "^2.6.7",
|
||||
"modernizr": "^3.11.4",
|
||||
"node-fetch": "^2.6.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||
"postcss-calc": "^7.0.5",
|
||||
"postcss-easings": "^2.0.0",
|
||||
"postcss-extend": "^1.0.5",
|
||||
"postcss-hexrgba": "^2.0.1",
|
||||
@@ -144,31 +141,20 @@
|
||||
"postcss-scss": "^2.1.1",
|
||||
"postcss-simple-vars": "^5.0.2",
|
||||
"postcss-strip-inline-comments": "^0.1.5",
|
||||
"raw-loader": "^4.0.2",
|
||||
"react-refresh": "^0.10.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"shell-escape": "^0.2.0",
|
||||
"simple-proxy-agent": "^1.1.0",
|
||||
"string-replace-loader": "2",
|
||||
"style-loader": "2",
|
||||
"stylelint": "^13.9.0",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint-scss": "^3.18.0",
|
||||
"terser-webpack-plugin": "^2.3.8",
|
||||
"typescript": "^4.5.3",
|
||||
"typescript": "^4.1.3",
|
||||
"webpack": "^4.46.0",
|
||||
"webpack-cli": "^3.3.12",
|
||||
"webpack-dev-server": "^3.11.2",
|
||||
"worker-loader": "^2.0.0",
|
||||
"worklet-loader": "^2.0.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/react": "17.0.14"
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
},
|
||||
"jest": {
|
||||
"testEnvironment": "jest-environment-jsdom-sixteen",
|
||||
"testMatch": [
|
||||
"<rootDir>/test/**/*-test.[tj]s?(x)"
|
||||
"<rootDir>/test/**/*-test.js"
|
||||
],
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/node_modules/matrix-react-sdk/test/setupTests.js"
|
||||
@@ -185,11 +171,7 @@
|
||||
"decoderWorker\\.min\\.js": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||
"decoderWorker\\.min\\.wasm": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||
"waveWorker\\.min\\.js": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||
"context-filter-polyfill": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||
"FontManager.ts": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/FontManager.js",
|
||||
"workers/(.+)\\.worker\\.ts": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/workerMock.js",
|
||||
"^!!raw-loader!.*": "jest-raw-loader",
|
||||
"RecorderWorklet": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js"
|
||||
"context-filter-polyfill": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js"
|
||||
},
|
||||
"transformIgnorePatterns": [
|
||||
"/node_modules/(?!matrix-js-sdk).+$",
|
||||
|
||||
@@ -1,4 +1 @@
|
||||
signing_id: releases@riot.im
|
||||
subprojects:
|
||||
matrix-react-sdk:
|
||||
includeByDefault: true
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
|
||||
<!--<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>-->
|
||||
<script crossorigin src="https://unpkg.com/rxjs/dist/bundles/rxjs.umd.min.js"></script>
|
||||
<script crossorigin src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>
|
||||
<script src="datatypes.js"></script>
|
||||
<script src="decoder.js"></script>
|
||||
|
||||
|
||||
@@ -12,20 +12,20 @@ const ProxyAgent = require("simple-proxy-agent");
|
||||
console.log("Making webapp directory");
|
||||
mkdirp.sync("webapp");
|
||||
|
||||
// curl -s https://meet.element.io/libs/external_api.min.js > ./webapp/jitsi_external_api.min.js
|
||||
// curl -s https://jitsi.riot.im/libs/external_api.min.js > ./webapp/jitsi_external_api.min.js
|
||||
console.log("Downloading Jitsi script");
|
||||
const fname = path.join("webapp", "jitsi_external_api.min.js");
|
||||
|
||||
const options = {};
|
||||
if (process.env.HTTPS_PROXY) {
|
||||
options.agent = new ProxyAgent(process.env.HTTPS_PROXY, { tunnel: true });
|
||||
options.agent = new ProxyAgent(process.env.HTTPS_PROXY, {tunnel: true});
|
||||
}
|
||||
|
||||
fetch("https://meet.element.io/libs/external_api.min.js", options).then(res => {
|
||||
const stream = fs.createWriteStream(fname);
|
||||
return new Promise((resolve, reject) => {
|
||||
res.body.pipe(stream);
|
||||
res.body.on('error', err => reject(err));
|
||||
res.body.on('finish', () => resolve());
|
||||
});
|
||||
fetch("https://jitsi.riot.im/libs/external_api.min.js", options).then(res => {
|
||||
const stream = fs.createWriteStream(fname);
|
||||
return new Promise((resolve, reject) => {
|
||||
res.body.pipe(stream);
|
||||
res.body.on('error', err => reject(err));
|
||||
res.body.on('finish', () => resolve());
|
||||
});
|
||||
}).then(() => console.log('Done with Jitsi download'));
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Runs package.sh, passing DIST_VERSION determined by git
|
||||
# Runs package.sh setting the version to git hashes of the element-web,
|
||||
# react-sdk & js-sdk checkouts, for the case where these dependencies
|
||||
# are git checkouts.
|
||||
|
||||
set -ex
|
||||
|
||||
rm dist/element-*.tar.gz || true # rm previous artifacts without failing if it doesn't exist
|
||||
|
||||
DIST_VERSION=`$(dirname $0)/get-version-from-git.sh`
|
||||
# Since the deps are fetched from git, we can rev-parse
|
||||
REACT_SHA=$(cd node_modules/matrix-react-sdk; git rev-parse --short=12 HEAD)
|
||||
JSSDK_SHA=$(cd node_modules/matrix-js-sdk; git rev-parse --short=12 HEAD)
|
||||
|
||||
CI_PACKAGE=true DIST_VERSION=$DIST_VERSION scripts/package.sh
|
||||
VECTOR_SHA=$(git rev-parse --short=12 HEAD) # use the ACTUAL SHA rather than assume develop
|
||||
|
||||
CI_PACKAGE=true DIST_VERSION=$VECTOR_SHA-react-$REACT_SHA-js-$JSSDK_SHA scripts/package.sh
|
||||
|
||||
@@ -29,7 +29,6 @@ const INCLUDE_LANGS = [
|
||||
{'value': 'he', 'label': 'עברית'},
|
||||
{'value': 'hi', 'label': 'हिन्दी'},
|
||||
{'value': 'hu', 'label': 'Magyar'},
|
||||
{'value': 'id', 'label': 'Bahasa Indonesia'},
|
||||
{'value': 'is', 'label': 'íslenska'},
|
||||
{'value': 'it', 'label': 'Italiano'},
|
||||
{'value': 'ja', 'label': '日本語'},
|
||||
@@ -53,7 +52,6 @@ const INCLUDE_LANGS = [
|
||||
{'value': 'th', 'label': 'ไทย'},
|
||||
{'value': 'tr', 'label': 'Türkçe'},
|
||||
{'value': 'uk', 'label': 'українська мова'},
|
||||
{'value': 'vi', 'label': 'Tiếng Việt'},
|
||||
{'value': 'vls', 'label': 'West-Vlaams'},
|
||||
{'value': 'zh_Hans', 'label': '简体中文'}, // simplified chinese
|
||||
{'value': 'zh_Hant', 'label': '繁體中文'}, // traditional chinese
|
||||
|
||||
7
scripts/docker-package.sh → scripts/docker-write-version.sh
Executable file → Normal file
7
scripts/docker-package.sh → scripts/docker-write-version.sh
Executable file → Normal file
@@ -13,9 +13,10 @@ DIST_VERSION=$TAG
|
||||
# for an appropriately tagged branch as well (heads/v1.2.3).
|
||||
if [[ $BRANCH != HEAD && ! $BRANCH =~ heads/v.+ ]]
|
||||
then
|
||||
DIST_VERSION=`$(dirname $0)/get-version-from-git.sh`
|
||||
REACT_SHA=$(cd node_modules/matrix-react-sdk; git rev-parse --short=12 HEAD)
|
||||
JSSDK_SHA=$(cd node_modules/matrix-js-sdk; git rev-parse --short=12 HEAD)
|
||||
VECTOR_SHA=$(git rev-parse --short=12 HEAD) # use the ACTUAL SHA rather than assume develop
|
||||
DIST_VERSION=$VECTOR_SHA-react-$REACT_SHA-js-$JSSDK_SHA
|
||||
fi
|
||||
|
||||
DIST_VERSION=`$(dirname $0)/normalize-version.sh ${DIST_VERSION}`
|
||||
VERSION=$DIST_VERSION yarn build
|
||||
echo $DIST_VERSION > /src/webapp/version
|
||||
@@ -25,8 +25,7 @@ function clone() {
|
||||
if [ -n "$branch" ]
|
||||
then
|
||||
echo "Trying to use $org/$repo#$branch"
|
||||
# Disable auth prompts: https://serverfault.com/a/665959
|
||||
GIT_TERMINAL_PROMPT=0 git clone https://github.com/$org/$repo.git $repo --branch $branch \
|
||||
git clone git://github.com/$org/$repo.git $repo --branch $branch \
|
||||
"${GIT_CLONE_ARGS[@]}"
|
||||
return $?
|
||||
fi
|
||||
@@ -77,7 +76,7 @@ dodep matrix-org matrix-js-sdk
|
||||
|
||||
pushd matrix-js-sdk
|
||||
yarn link
|
||||
yarn install --pure-lockfile
|
||||
yarn install
|
||||
popd
|
||||
|
||||
yarn link matrix-js-sdk
|
||||
@@ -91,7 +90,7 @@ dodep matrix-org matrix-react-sdk
|
||||
pushd matrix-react-sdk
|
||||
yarn link
|
||||
yarn link matrix-js-sdk
|
||||
yarn install --pure-lockfile
|
||||
yarn install
|
||||
yarn reskindex
|
||||
popd
|
||||
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Echoes a version based on the git hashes of the element-web, react-sdk & js-sdk checkouts, for the case where
|
||||
# these dependencies are git checkouts.
|
||||
|
||||
# Since the deps are fetched from git, we can rev-parse
|
||||
REACT_SHA=$(cd node_modules/matrix-react-sdk; git rev-parse --short=12 HEAD)
|
||||
JSSDK_SHA=$(cd node_modules/matrix-js-sdk; git rev-parse --short=12 HEAD)
|
||||
VECTOR_SHA=$(git rev-parse --short=12 HEAD) # use the ACTUAL SHA rather than assume develop
|
||||
echo $VECTOR_SHA-react-$REACT_SHA-js-$JSSDK_SHA
|
||||
@@ -1,8 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# If $1 looks like v1.2.3 or v1.2.3-foo, strip the leading v, then print it to stdout
|
||||
if [[ $1 =~ ^v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+(-.+)?$ ]]; then
|
||||
echo ${1:1}
|
||||
else
|
||||
echo $1
|
||||
fi
|
||||
@@ -9,7 +9,7 @@ else
|
||||
fi
|
||||
|
||||
yarn clean
|
||||
VERSION=$version yarn build
|
||||
yarn build
|
||||
|
||||
# include the sample config in the tarball. Arguably this should be done by
|
||||
# `yarn build`, but it's just too painful.
|
||||
@@ -21,7 +21,12 @@ cp -r webapp element-$version
|
||||
# Just in case you have a local config, remove it before packaging
|
||||
rm element-$version/config.json || true
|
||||
|
||||
$(dirname $0)/normalize-version.sh ${version} > element-$version/version
|
||||
# if $version looks like semver with leading v, strip it before writing to file
|
||||
if [[ ${version} =~ ^v[[:digit:]]+\.[[:digit:]]+\.[[:digit:]]+(-.+)?$ ]]; then
|
||||
echo ${version:1} > element-$version/version
|
||||
else
|
||||
echo ${version} > element-$version/version
|
||||
fi
|
||||
|
||||
tar chvzf dist/element-$version.tar.gz element-$version
|
||||
rm -r element-$version
|
||||
|
||||
4
src/@types/global.d.ts
vendored
4
src/@types/global.d.ts
vendored
@@ -16,7 +16,6 @@ limitations under the License.
|
||||
|
||||
import "matrix-react-sdk/src/@types/global"; // load matrix-react-sdk's type extensions first
|
||||
import type { Renderer } from "react-dom";
|
||||
import type { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
type ElectronChannel =
|
||||
"app_onAction" |
|
||||
@@ -32,12 +31,11 @@ type ElectronChannel =
|
||||
"setBadgeCount" |
|
||||
"update-downloaded" |
|
||||
"userDownloadCompleted" |
|
||||
"userDownloadAction";
|
||||
"userDownloadOpen";
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
mxSendRageshake: (text: string, withLogs?: boolean) => void;
|
||||
matrixLogger: typeof logger;
|
||||
matrixChat: ReturnType<Renderer>;
|
||||
|
||||
// electron-only
|
||||
|
||||
4
src/@types/raw-loader.d.ts
vendored
4
src/@types/raw-loader.d.ts
vendored
@@ -1,4 +0,0 @@
|
||||
declare module '!!raw-loader!*' {
|
||||
const contents: string;
|
||||
export default contents;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
|
||||
android = [];
|
||||
}
|
||||
|
||||
let mobileHeader = <h2 id="step2_heading">{ _t("Use %(brand)s on mobile", { brand }) }</h2>;
|
||||
let mobileHeader = <h2 id="step2_heading">{_t("Use %(brand)s on mobile", { brand })}</h2>;
|
||||
if (!android.length && !ios) {
|
||||
mobileHeader = null;
|
||||
}
|
||||
@@ -102,11 +102,11 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
|
||||
'or <safariLink>Safari</safariLink> for the best experience.',
|
||||
{},
|
||||
{
|
||||
'chromeLink': (sub) => <a href="https://www.google.com/chrome">{ sub }</a>,
|
||||
'firefoxLink': (sub) => <a href="https://firefox.com">{ sub }</a>,
|
||||
'safariLink': (sub) => <a href="https://apple.com/safari">{ sub }</a>,
|
||||
'chromeLink': (sub) => <a href="https://www.google.com/chrome">{sub}</a>,
|
||||
'firefoxLink': (sub) => <a href="https://firefox.com">{sub}</a>,
|
||||
'safariLink': (sub) => <a href="https://apple.com/safari">{sub}</a>,
|
||||
},
|
||||
) }
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{ _t(
|
||||
@@ -124,9 +124,9 @@ const CompatibilityView: React.FC<IProps> = ({ onAccept }) => {
|
||||
<div className="mx_HomePage_col">
|
||||
<div className="mx_HomePage_row">
|
||||
<div>
|
||||
{ mobileHeader }
|
||||
{ ios }
|
||||
{ android }
|
||||
{mobileHeader}
|
||||
{ios}
|
||||
{android}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -40,9 +40,9 @@ const ErrorView: React.FC<IProps> = ({ title, messages }) => {
|
||||
<div className="mx_HomePage_row">
|
||||
<div>
|
||||
<h2 id="step1_heading">{ title }</h2>
|
||||
{ messages && messages.map(msg => <p key={msg}>
|
||||
{messages && messages.map(msg => <p key={msg}>
|
||||
{ msg }
|
||||
</p>) }
|
||||
</p>)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,14 +35,14 @@ const VectorAuthFooter = () => {
|
||||
for (const linkEntry of links) {
|
||||
authFooterLinks.push(
|
||||
<a href={linkEntry.url} key={linkEntry.text} target="_blank" rel="noreferrer noopener">
|
||||
{ linkEntry.text }
|
||||
{linkEntry.text}
|
||||
</a>,
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="mx_AuthFooter">
|
||||
{ authFooterLinks }
|
||||
{authFooterLinks}
|
||||
<a href="https://matrix.org" target="_blank" rel="noreferrer noopener">{ _t('Powered by Matrix') }</a>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -32,7 +32,5 @@
|
||||
"I understand the risks and wish to continue": "أفهم المخاطرة وأود المواصلة",
|
||||
"Go to element.io": "انتقل إلى element.io",
|
||||
"Failed to start": "فشل البدء",
|
||||
"Powered by Matrix": "تدعمه «ماترِكس»",
|
||||
"Use %(brand)s on mobile": "استعمل %(brand)s على المحمول",
|
||||
"Switch to space by number": "التبديل إلى المساحة بالرقم"
|
||||
"Powered by Matrix": "تدعمه «ماترِكس»"
|
||||
}
|
||||
|
||||
@@ -1,5 +1 @@
|
||||
{
|
||||
"Your Element is misconfigured": "আপনার এলিমেন্ট টি ভুল ভাবে কনফিগার করা হয়েছে",
|
||||
"Invalid configuration: no default server specified.": "ভুল কনফিগারেশনঃ কোনো মূল সার্ভার উল্লেখ করা হয়নি।",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "ভুল কনফিগারেশনঃ এদের মধ্যে কেবলমাত্র একটাই উল্লেখ করা যেতে পারেঃ default_server_config, default_server_name অথবা default_hs_url."
|
||||
}
|
||||
{}
|
||||
|
||||
@@ -32,7 +32,5 @@
|
||||
"I understand the risks and wish to continue": "Entenc els riscos i vull continuar",
|
||||
"Go to element.io": "Vés a element.io",
|
||||
"Failed to start": "Ha fallat l'inici",
|
||||
"Missing indexeddb worker script!": "Falta l'script del treballador indexeddb!",
|
||||
"Use %(brand)s on mobile": "Utilitza %(brand)s al mòbil",
|
||||
"Switch to space by number": "Canvia d'espai per número"
|
||||
"Missing indexeddb worker script!": "Falta l'script del treballador indexeddb!"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Powered by Matrix": "Běží na Matrixu",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s pro desktopový počítač (%(platformName)s)",
|
||||
"Missing indexeddb worker script!": "Nenačetl se skript spravující indexdb!",
|
||||
"Use %(brand)s on mobile": "Používání %(brand)s v mobilních zařízeních",
|
||||
"Switch to space by number": "Přepnout na prostor podle čísla"
|
||||
"Use %(brand)s on mobile": "Používání %(brand)s v mobilních zařízeních"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s verwendet erweiterte Browserfunktionen, die von deinem Browser nicht unterstützt werden.",
|
||||
"Your browser can't run %(brand)s": "Dein Browser kann %(brand)s nicht ausführen",
|
||||
"Powered by Matrix": "Betrieben mit Matrix",
|
||||
"Use %(brand)s on mobile": "Verwende %(brand)s am Handy",
|
||||
"Switch to space by number": "Zum n-ten Space wechseln"
|
||||
"Use %(brand)s on mobile": "Verwende %(brand)s am Handy"
|
||||
}
|
||||
|
||||
@@ -32,7 +32,5 @@
|
||||
"Failed to start": "Αποτυχία έναρξης",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)",
|
||||
"Missing indexeddb worker script!": "Απουσία indexeddb worker script!",
|
||||
"Use %(brand)s on mobile": "Χρήση %(brand)s σε κινητό",
|
||||
"Switch to space by number": "Εναλλαγή σε space με αριθμό"
|
||||
"Missing indexeddb worker script!": "Απουσία indexeddb worker script!"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"Missing indexeddb worker script!": "Missing indexeddb worker script!",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "Invalid configuration: no default server specified.",
|
||||
"Your Element is misconfigured": "Your Element is misconfigured",
|
||||
@@ -12,8 +13,7 @@
|
||||
"Dismiss": "Dismiss",
|
||||
"Switch to space by number": "Switch to space by number",
|
||||
"Open user settings": "Open user settings",
|
||||
"Previous recently visited room or community": "Previous recently visited room or community",
|
||||
"Next recently visited room or community": "Next recently visited room or community",
|
||||
"Previous/next recently visited room or community": "Previous/next recently visited room or community",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)",
|
||||
"Go to your browser to complete Sign In": "Go to your browser to complete Sign In",
|
||||
"Unknown device": "Unknown device",
|
||||
|
||||
@@ -32,6 +32,5 @@
|
||||
"Unable to load config file: please refresh the page to try again.": "Unable to load config file: please refresh the page to try again.",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Your Element configuration contains invalid JSON. Please correct the problem and reload the page.",
|
||||
"Your Element is misconfigured": "Your Element is misconfigured",
|
||||
"Missing indexeddb worker script!": "Missing indexeddb worker script!",
|
||||
"Switch to space by number": "Switch to space by number"
|
||||
"Missing indexeddb worker script!": "Missing indexeddb worker script!"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Via foliumilo ne povas ruli %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s uzas specialajn funkciojn de foliumilo, kiujn via nuna foliumilo ne subtenas.",
|
||||
"Powered by Matrix": "Povigata de Matrix",
|
||||
"Use %(brand)s on mobile": "Uzi %(brand)s telefone",
|
||||
"Switch to space by number": "Baskuli al aro laŭ numero"
|
||||
"Use %(brand)s on mobile": "Uzi %(brand)s telefone"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Tu navegador no es compatible con %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s usa funciones avanzadas que su navegador actual no soporta.",
|
||||
"Powered by Matrix": "Funciona con Matrix",
|
||||
"Use %(brand)s on mobile": "Usar %(brand)s en modo móvil",
|
||||
"Switch to space by number": "Cambiar a espacio por número"
|
||||
"Use %(brand)s on mobile": "Usar %(brand)s en modo móvil"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "%(brand)s ei toimi sinu brauseris",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s kasutab mitmeid uusi brauseri-põhiseid tehnoloogiaid, mis ei ole veel sinu veebibrauseris toetatud.",
|
||||
"Powered by Matrix": "Põhineb Matrix'il",
|
||||
"Use %(brand)s on mobile": "Kasuta rakendust %(brand)s nutiseadmes",
|
||||
"Switch to space by number": "Vaata kogukonnakeskust tema numbri alusel"
|
||||
"Use %(brand)s on mobile": "Kasuta %(brand)s rakendust nutiseadmes"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Go to element.io": "برو به element.io",
|
||||
"Failed to start": "مشکل در آغاز",
|
||||
"Powered by Matrix": "قدرتگرفته از ماتریکس",
|
||||
"Use %(brand)s on mobile": "استفاده از %(brand)s روی گوشی",
|
||||
"Switch to space by number": "تغییر به فضا با شماره"
|
||||
"Use %(brand)s on mobile": "استفاده از %(brand)s روی گوشی"
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"Dismiss": "Hylkää",
|
||||
"Unknown device": "Tuntematon laite",
|
||||
"Welcome to Element": "Tervetuloa Element-sovellukseen",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Sinun täytyy käyttää HTTPS-yhteyttä, jotta voit jakaa näytön puhelussa.",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Sinun täytyy käyttää HTTPS-yhteyttä, jotta voit jakaa ruudun puhelussa.",
|
||||
"powered by Matrix": "moottorina Matrix",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Hajautettua ja salattua viestintää Matrix-teknologialla",
|
||||
"Sign In": "Kirjaudu",
|
||||
@@ -32,7 +32,5 @@
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Element-asetuksesi sisältävät epäkelpoa JSONia. Korjaa ongelma ja lataa sivu uudelleen.",
|
||||
"Powered by Matrix": "Moottorina Matrix",
|
||||
"Your browser can't run %(brand)s": "%(brand)s ei toimi selaimessasi",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s käyttää edistyneitä selaimen ominaisuuksia, joita nykyinen selaimesi ei tue.",
|
||||
"Use %(brand)s on mobile": "Käytä %(brand)sia mobiilisti",
|
||||
"Switch to space by number": "Vaihda avaruuteen käyttäen numeroa"
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s käyttää edistyneitä selaimen ominaisuuksia, joita nykyinen selaimesi ei tue."
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Votre navigateur ne peut pas exécuter %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s nécessite des fonctionnalités avancées que votre navigateur actuel ne prend pas en charge.",
|
||||
"Powered by Matrix": "Propulsé par Matrix",
|
||||
"Use %(brand)s on mobile": "Utiliser %(brand)s sur téléphone",
|
||||
"Switch to space by number": "Afficher un espace par son numéro"
|
||||
"Use %(brand)s on mobile": "Utiliser %(brand)s sur téléphone"
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
{
|
||||
"Sign In": "Oanmelde",
|
||||
"Failed to start": "Opstarten mislearre",
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Jo kinne fierder gean mei jo eigen browser, mar guon funksjes kinne net wurkje en uterlik kin de applikaasje der ôfwikend útsjen.",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Graach <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, of<safariLink>Safari</safariLink> ynstallearje foar de beste ûnderfining.",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s brûkt avansearre browserfunksjes dy’t net stipe wurde troch de browser dy’t jo no brûke.",
|
||||
"Powered by Matrix": "Mooglik makke troch Matrix",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)",
|
||||
"Previous/next recently visited room or community": "Foarige/Folgjende resintlik besochte keamer as mienskip",
|
||||
"Switch to space by number": "Wikselje fan romte mei nûmer",
|
||||
"Unexpected error preparing the app. See console for details.": "Unferwachte flater by it klearmeitsjen fan de applikaasje. Sjoch yn de console foar details.",
|
||||
"The message from the parser is: %(message)s": "It berjocht fan de ferwurker is: %(message)s",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Jo Element-konfiguraasje hat ûnjildige JSON. Nei dat jo dit oplost ha, kin dizze side ferfarske wurde.",
|
||||
"Use %(brand)s on mobile": "Brûk %(brand)s op mobyl",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Desintralisearre, fersifere chat & gearwurking fersoarge troch [matrix]",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Oproppen mei skerm dielen fereasket HTTPS.",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"Go to your browser to complete Sign In": "Gean nei jo browser om it ynskriuwen te foltôgjen",
|
||||
"Download Completed": "Download foltôge",
|
||||
"Unable to load config file: please refresh the page to try again.": "Kin konfiguraasjebestân net lade: ferfarskje de side en probearje it nochris.",
|
||||
"Open user settings": "Brûkersynstellingen iepenje",
|
||||
"Dismiss": "Slute",
|
||||
"Explore rooms": "Keamers ûntdekke",
|
||||
"Create Account": "Registrearje",
|
||||
"Welcome to Element": "Wolkom by Element",
|
||||
"I understand the risks and wish to continue": "Ik begryp de risiko's en wol graach fierder gean",
|
||||
"Go to element.io": "Gean nei element.io",
|
||||
"Your browser can't run %(brand)s": "Jo browser kin %(brand)s net útfiere",
|
||||
"Unsupported browser": "Net stipe browser",
|
||||
"Unknown device": "Unbekend apparaat",
|
||||
"Open": "Iepenje",
|
||||
"Invalid JSON": "Unjildige JSON",
|
||||
"Your Element is misconfigured": "Jo Element is net goed konfigurearre",
|
||||
"Invalid configuration: no default server specified.": "Unjildiche konfiguraasje: gjin standertserver selektearre.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Unjildige konfiguraasje: kin allinnich kieze út default_server_config, default_server_name, as default_hs_url."
|
||||
}
|
||||
@@ -33,6 +33,5 @@
|
||||
"Go to element.io": "Téigh go element.io",
|
||||
"Open user settings": "Oscail socruithe úsáideora",
|
||||
"Open": "Oscail",
|
||||
"Use %(brand)s on mobile": "Úsáid %(brand)s ar guthán póca",
|
||||
"Switch to space by number": "Athraigh go spás de réir uimhreach"
|
||||
"Use %(brand)s on mobile": "Úsáid %(brand)s ar guthán póca"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "O teu navegador non pode executar %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s utiliza características avanzadas do navegador que non están dispoñibles no teu navegador.",
|
||||
"Powered by Matrix": "Funciona grazas a Matrix",
|
||||
"Use %(brand)s on mobile": "Utiliza %(brand)s no móbil",
|
||||
"Switch to space by number": "Cambiar a espazo polo número"
|
||||
"Use %(brand)s on mobile": "Utiliza %(brand)s no móbil"
|
||||
}
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
"Unknown device": "מכשיר לא ידוע",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "עליך להשתמש ב HTTPS בכדי לבצע שיחת ווידאו משותפת.",
|
||||
"Welcome to Element": "ברוכים הבאים ל Element",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "צא'ט וכלי שיתוף פעולה מבוזר ומוצפן & מופעל באמצעות [matrix]",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "צ'ט מוצפן & ושת\"פ נעשה ע\"י ה [matrix]",
|
||||
"Invalid JSON": "JSON לא חוקי",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "תצורה שגויה: ניתן לציין רק אחד מהערכים הבאים, default_server_config, default_server_name, או default_hs_url.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "תצורה שגויה: ניתן לציין רק אחד מהבאים, default_server_config, default_server_name, או default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "תצורה שגויה: לא צוין שרת ברירת מחדל.",
|
||||
"Open user settings": "פתח הגדרות משתמש",
|
||||
"Go to your browser to complete Sign In": "עבור לדפדפן להמשך ההתחברות",
|
||||
"Explore rooms": "גלה חדרים",
|
||||
"Explore rooms": "שיטוט בחדרים",
|
||||
"Create Account": "יצירת חשבון",
|
||||
"Sign In": "התחברות",
|
||||
"Sign In": "כניסה",
|
||||
"Previous/next recently visited room or community": "הבא\\קודם חדרים וקהילות שביקרתם לאחרונה",
|
||||
"Open": "פתח",
|
||||
"Download Completed": "ההורדה הושלמה",
|
||||
"Unexpected error preparing the app. See console for details.": "שגיאה לא צפויה במהלך טעינת האפליקציה. ראו קונסול לפרטים נוספים.",
|
||||
"Unable to load config file: please refresh the page to try again.": "לא ניתן לטעון את קובץ ההגדרות: יש לרענן את הדף כדי לנסות שנית.",
|
||||
"Unexpected error preparing the app. See console for details.": "שגיאה לא צפויה במהלך הכנת האפליקציה. ראו קונסול לפרטים נוספים.",
|
||||
"Unable to load config file: please refresh the page to try again.": "לא יכול לקרוא את קובץ ההגדרות: אנא אתחלו את הדף לנסות שנית.",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "האלמנט מכיל הגדרת JSON שגויה, אנא תקנו את הבעיה ואתחלו את הדף.",
|
||||
"Your Element is misconfigured": "האלמנט מוגדר באופן שגוי",
|
||||
"Go to element.io": "חזור לאתר הראשי: element.io",
|
||||
@@ -31,8 +31,6 @@
|
||||
"Powered by Matrix": "מופעל על ידי מטריקס",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s שולחן עבודה %(platformName)s",
|
||||
"The message from the parser is: %(message)s": "ההודעה מהמנתח היא: %(message)s",
|
||||
"Missing indexeddb worker script!": "סקריפט indexeddb worker חסר!",
|
||||
"Switch to space by number": "עבור 'למרחב' על פי המספר שלו",
|
||||
"Use %(brand)s on mobile": "השתמש ב%(brand)s במכשיר הנייד"
|
||||
"The message from the parser is: %(message)s": "ההודעה מהניתוח היא: %(message)s",
|
||||
"Missing indexeddb worker script!": "סקריפט indexeddb worker חסר!"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "A böngészője nem tudja futtatni ezt: %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s speciális böngészőfunkciókat használ, amelyeket a jelenlegi böngészője nem támogat.",
|
||||
"Powered by Matrix": "A gépházban: Matrix",
|
||||
"Use %(brand)s on mobile": "Mobilon használd ezt: %(brand)s",
|
||||
"Switch to space by number": "Tér váltás számmal"
|
||||
"Use %(brand)s on mobile": "Mobilon használd ezt: %(brand)s"
|
||||
}
|
||||
|
||||
@@ -1,38 +1,11 @@
|
||||
{
|
||||
"Dismiss": "Abaikan",
|
||||
"powered by Matrix": "didukung oleh Matrix",
|
||||
"Unknown device": "Perangkat tidak dikenal",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Anda perlu menggunakan HTTPS untuk melakukan panggilan berbagi layar.",
|
||||
"Unknown device": "Perangkat Tidak Diketahui",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Anda perlu menggunakan HTTPS untuk melakukan panggilan berbagi-layar.",
|
||||
"Welcome to Element": "Selamat datang di Element",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Obrolan & kolaborasi terdecentralisasi dan terenkripsi, diberdayakan oleh [matrix]",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Konfigurasi Element Anda berisi JSON yang tidak valid. Mohon perbaiki masalahnya dan muat ulang halamannya.",
|
||||
"Invalid configuration: no default server specified.": "Konfigurasi tidak valid: server bawaan belum ditentukan.",
|
||||
"Missing indexeddb worker script!": "Tidak ada script worker indexeddb!",
|
||||
"Explore rooms": "Jelajahi ruangan",
|
||||
"Create Account": "Buat Akun",
|
||||
"Switch to space by number": "Beralih ke space bedasarkan angka",
|
||||
"Go to your browser to complete Sign In": "Buka browser Anda untuk menyelesaikan Sign In",
|
||||
"Sign In": "Masuk",
|
||||
"Failed to start": "Gagal untuk memulai",
|
||||
"Go to element.io": "Buka element.io",
|
||||
"I understand the risks and wish to continue": "Saya memahami risikonya dan ingin melanjutkan",
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Anda dapat lanjut menggunakan browser Anda saat ini, tetapi beberapa atau semua fitur mungkin tidak berfungsi dan tampilan serta nuansa aplikasi mungkin salah.",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Mohon instal <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, atau <safariLink>Safari</safariLink> untuk pengalaman yang terbaik.",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s menggunakan fitur browser lanjutan yang tidak didukung oleh browser Anda saat ini.",
|
||||
"Your browser can't run %(brand)s": "Browser Anda tidak dapat menjalankan %(brand)s",
|
||||
"Unsupported browser": "Browser tidak didukung",
|
||||
"Use %(brand)s on mobile": "Gunakan %(brand)s di ponsel",
|
||||
"Powered by Matrix": "Diberdayakan oleh Matrix",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)",
|
||||
"Previous/next recently visited room or community": "Ruangan atau komunitas yang baru saja dikunjungi sebelumnya/berikutnya",
|
||||
"Open user settings": "Buka pengaturan pengguna",
|
||||
"Open": "Buka",
|
||||
"Download Completed": "Unduhan Selesai",
|
||||
"Unexpected error preparing the app. See console for details.": "Kesalahan tak terduga saat menyiapkan aplikasi. Lihat konsol untuk detail.",
|
||||
"Unable to load config file: please refresh the page to try again.": "Tidak dapat memuat file konfigurasi: mohon muat ulang halaman ini untuk mencoba lagi.",
|
||||
"Invalid JSON": "JSON tidak valid",
|
||||
"The message from the parser is: %(message)s": "Pesan dari pengurai adalah: %(message)s",
|
||||
"Your Element is misconfigured": "Anda mengatur Element dengan salah",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Konfigurasi tidak valid: hanya bisa menentukan satu dari default_server_config, default_server_name, atau default_hs_url."
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Obrolan terenkripsi, terdesentralisasi & kolaborasi didukung oleh [matrix]",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Konfigurasi Element Anda mengandung JSON yang tidak valid. Mohon perbaiki masalahnya dan muat ulang halaman nya.",
|
||||
"Invalid configuration: no default server specified.": "Konfigurasi tidak valid: server default belum ditentukan.",
|
||||
"Missing indexeddb worker script!": "Tidak ada script worker indexeddb!"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Il tuo browser non può eseguire %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s usa funzionalità avanzate del browser che non sono supportate dal tuo browser attuale.",
|
||||
"Powered by Matrix": "Offerto da Matrix",
|
||||
"Use %(brand)s on mobile": "Usa %(brand)s su mobile",
|
||||
"Switch to space by number": "Passa allo spazio per numero"
|
||||
"Use %(brand)s on mobile": "Usa %(brand)s su mobile"
|
||||
}
|
||||
|
||||
@@ -32,7 +32,5 @@
|
||||
"Open": "Ldi",
|
||||
"Your browser can't run %(brand)s": "Iminig-inek·inem ur isselkan ara %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s isseqdac timahilin n yiminig leqqayen ur yessefrak ara yiminig-ik·im amiran.",
|
||||
"Powered by Matrix": "Iteddu s lmendad n Matrix",
|
||||
"Use %(brand)s on mobile": "Seqdec %(brand)s deg tiliɣri",
|
||||
"Switch to space by number": "Ddu ɣer space s uṭṭun"
|
||||
"Powered by Matrix": "Iteddu s lmendad n Matrix"
|
||||
}
|
||||
|
||||
@@ -24,14 +24,5 @@
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "현재 사용중이신 브라우저를 계속 사용하셔도 됩니다, 다만 일부 기능들이 작동하지 않을 수 있으며 애플리케이션이 잘못돼 보일 수 있습니다.",
|
||||
"I understand the risks and wish to continue": "위험하다는 것을 이해했으며 계속하고 싶습니다",
|
||||
"Go to element.io": "element.io으로 가기",
|
||||
"Failed to start": "시작 실패",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s 는 당신의 브라우저에서 지원되지 않는 고급 기능을 사용합니다.",
|
||||
"Your browser can't run %(brand)s": "당신의 브라우저는 %(brand)s 를 작동할 수 없습니다",
|
||||
"Use %(brand)s on mobile": "모바일에서 %(brand)s 사용",
|
||||
"Powered by Matrix": "Matrix로 지원됨",
|
||||
"Switch to space by number": "숫자로 스페이스 전환하기",
|
||||
"Open": "열기",
|
||||
"Download Completed": "다운로드 완료",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "당신의 Element 설정은 유효하지 않은 JSON을 포함합니다. 이 문제를 해결하고 페이지를 새로고침해주세요.",
|
||||
"Your Element is misconfigured": "당신의 Element가 잘못 설정되었습니다"
|
||||
"Failed to start": "시작 실패"
|
||||
}
|
||||
|
||||
@@ -2,37 +2,35 @@
|
||||
"Dismiss": "Aizvērt",
|
||||
"powered by Matrix": "Tiek darbināta ar Matrix",
|
||||
"Unknown device": "Nezināma ierīce",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Ekrāna kopīgošanai nepieciešams izmantot HTTPS savienojumu.",
|
||||
"Welcome to Element": "Esiet laipni gaidīti Elementā",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralizēta, šifrēta tērziņu & kopdarbības vide uz [matrix] bāzes",
|
||||
"Sign In": "Ierakstīties",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Lai veiktu ekrāna kopīgošanas zvanu, nepieciešams izmantot HTTPS savienojumu.",
|
||||
"Welcome to Element": "Esiet laipni gaidīti Element",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralizēta, šifrēta čata & kopdarbošanās sistēma uz [matrix] bāzes",
|
||||
"Sign In": "Pierakstīties",
|
||||
"Create Account": "Izveidot kontu",
|
||||
"Explore rooms": "Pārlūkot istabas",
|
||||
"Unexpected error preparing the app. See console for details.": "Negaidīta kļūda, sagatavojot lietotni. Sīkāku informāciju skatiet konsolē.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Kļūdaina konfigurācija: var norādīt tikai vienu no parametriem default_server_config, default_server_name, vai default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "Kļūdaina konfigurācija: nav norādīts noklusējuma serveris.",
|
||||
"The message from the parser is: %(message)s": "No pārsētāja ir ziņa: %(message)s",
|
||||
"The message from the parser is: %(message)s": "Ziņojums no parsētāja ir: %(message)s",
|
||||
"Invalid JSON": "Kļūdains JSON",
|
||||
"Unable to load config file: please refresh the page to try again.": "Neizdevās ielādēt konfigurācijas failu. Lai atkārtotu mēģinātu, lūdzu pārlādējiet lapu.",
|
||||
"Unable to load config file: please refresh the page to try again.": "Neizdevās ielādēt konfigurācijas datni. Lūdzu, pārlādējiet lapu, lai mēģinātu vēlreiz.",
|
||||
"Open user settings": "Atvērt lietotāja iestatījumus",
|
||||
"Go to your browser to complete Sign In": "Dodieties uz pārlūku, lai pabeigtu pierakstīšanos",
|
||||
"Go to your browser to complete Sign In": "Pārejiet uz pārlūku, lai pabeigtu pierakstīšanos",
|
||||
"Unsupported browser": "Neatbalstīts pārlūks",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Lai gūtu labāko lietošanas pieredzi, lūdzu, instalējiet <chromeLink>Chromium</chromeLink>, <firefoxLink>Firefox</firefoxLink> vai <safariLink>Safari</safariLink> pārlūku.",
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Jūs varat turpināt lietot savu pašreizējo pārlūku, bet dažas funkcijas nestrādās un lietotnes izskats/saskarne var būt atspoguļoti nekorekti.",
|
||||
"I understand the risks and wish to continue": "Es apzinos riskus un vēlos turpināt",
|
||||
"Go to element.io": "Doties uz element.io",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Labākajai izmantošanas pieredzei, lūdzu, instalējiet <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink> vai <safariLink>Safari</safariLink> pārlūku.",
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Jūs varat turpināt lietot savu pašreizējo pārlūku, bet dažas vai visas funkcijas nestrādās, un lietotnes izskats var būt nepareizs.",
|
||||
"I understand the risks and wish to continue": "Es pieņemu riskus un vēlos turpināt",
|
||||
"Go to element.io": "Ej uz element.io",
|
||||
"Failed to start": "Neizdevās palaist",
|
||||
"Powered by Matrix": "Griežas uz Matrix tehnoloģijas",
|
||||
"Powered by Matrix": "Darbojas uz Matrix",
|
||||
"Previous/next recently visited room or community": "Iepriekšējā/nākošā nesen apmeklētā istaba vai kopiena",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s izmanto pārlūku papildfunkcijas, kuras netiek atbalstītas šajā pārlūkā.",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s izmanto pārlūku papildus funkcijas, kas netiek atbalstītas šajā pārlūkā.",
|
||||
"Your browser can't run %(brand)s": "Jūsu pārlūks nevar palaist %(brand)s",
|
||||
"Missing indexeddb worker script!": "Trūkst indexeddb worker skripta!",
|
||||
"Open": "Atvērt",
|
||||
"Download Completed": "Lejuplāde pabeigta",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Jūsu Element konfigurācija satur kļūdainu JSON. Lūdzu, izlabojiet un pārlādējiet lapu.",
|
||||
"Download Completed": "Lejupielāde pabeigta",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Jūsu Element konfigurācija satur kļūdainu JSON. Lūdzu, salabojiet problēmu un pārlādējiet lapu.",
|
||||
"Your Element is misconfigured": "Jūsu Element ir nokonfigurēts kļūdaini",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Galdvirsmas (%(platformName)s)",
|
||||
"Switch to space by number": "Pārslēgties uz atstarpi/tukšumu ar numuru",
|
||||
"Use %(brand)s on mobile": "Mobilajā tālrunī izmanojiet %(brand)s"
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)"
|
||||
}
|
||||
|
||||
@@ -32,7 +32,5 @@
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s bruker avanserte nettleserfunksjoner som ikke støttes av din nåværende nettleser.",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Skrivebord (%(platformName)s)",
|
||||
"Open": "Åpne",
|
||||
"Use %(brand)s on mobile": "Bruk %(brand)s på mobil",
|
||||
"Switch to space by number": "Bytt til plass etter nummer"
|
||||
"Open": "Åpne"
|
||||
}
|
||||
|
||||
@@ -4,10 +4,10 @@
|
||||
"Unknown device": "Onbekend apparaat",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Oproepen met schermdelen vergen HTTPS.",
|
||||
"Welcome to Element": "Welkom bij Element",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentrale en versleutelde chat & samenwerken dankzij [matrix]",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Gedecentraliseerd en versleuteld chatten & samenwerken dankzij [matrix]",
|
||||
"Sign In": "Inloggen",
|
||||
"Create Account": "Registreren",
|
||||
"Explore rooms": "Ontdek kamers",
|
||||
"Create Account": "Registeren",
|
||||
"Explore rooms": "Gesprekken ontdekken",
|
||||
"Unexpected error preparing the app. See console for details.": "Er is een onverwachte fout opgetreden bij het voorbereiden van de app. Zie de console voor details.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuratiefout: kan slechts één van default_server_config, default_server_name, of default_hs_url opgeven.",
|
||||
"Invalid configuration: no default server specified.": "Configuratie ongeldig: geen standaardserver opgegeven.",
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Uw browser kan %(brand)s niet starten",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s gebruikt geavanceerde functies die niet ondersteund worden in uw huidige browser.",
|
||||
"Powered by Matrix": "Mogelijk gemaakt door Matrix",
|
||||
"Use %(brand)s on mobile": "Gebruik %(brand)s op uw mobiel",
|
||||
"Switch to space by number": "Wissel naar Space met nummer"
|
||||
"Use %(brand)s on mobile": "Gebruik %(brand)s op uw mobiel"
|
||||
}
|
||||
|
||||
@@ -12,26 +12,11 @@
|
||||
"Invalid JSON": "Ugyldig JSON",
|
||||
"Unexpected error preparing the app. See console for details.": "Uventa feil under lasting av programmet. Sjå konsollen for detaljar.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Ugyldig oppsett: berre muleg å berre spesifiere ein av default_server_config, default_server_name eller default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "Ugyldig oppsett: Ingen standardserver er spesifisert.",
|
||||
"Invalid configuration: no default server specified.": "Ugyldig oppsett: ingen \"default server\" er spesifisert.",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Oppsettet for din Element inneheld ugyldig JSON. Sjekk konfigurasjonsfila, deretter last om sida.",
|
||||
"Unable to load config file: please refresh the page to try again.": "Fekk ikkje til å lasta konfigurasjonsfila: last inn sida for å prøva om att.",
|
||||
"Go to your browser to complete Sign In": "Opna nettlesaren din for å fullføra innlogginga",
|
||||
"Unsupported browser": "Nettlesaren er ikkje støtta",
|
||||
"Your browser can't run %(brand)s": "Din nettlesar kan ikkje køyra %(brand)s",
|
||||
"Go to element.io": "Gå til element.io",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Du kan fortsetja å bruka gjeldande nettlesar, men nokre eller alle funksjonane fungerer kanskje ikkje, og utsjånaden og kjensla av applikasjonen kan vera feil.",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Installer <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, eller <safariLink>Safari</safariLink> for den beste opplevinga.",
|
||||
"I understand the risks and wish to continue": "Eg forstår risikoen og ynskjer å fortsetja",
|
||||
"Previous/next recently visited room or community": "Føregåande/neste nyleg besøkte rom eller samfunn",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s brukar avanserte nettlesarfunksjonar som ikkje er støtta av den gjeldande nettlesaren din.",
|
||||
"Use %(brand)s on mobile": "Bruk %(brand)s på mobil",
|
||||
"Powered by Matrix": "Driven av Matrix",
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Skrivebord (%(platformName)s)",
|
||||
"Your Element is misconfigured": "Element er feilkonfigurert",
|
||||
"Failed to start": "Klarte ikkje å starta",
|
||||
"Open user settings": "Opna brukarinnstillingar",
|
||||
"Switch to space by number": "Byt til plass etter nummer",
|
||||
"Open": "Opna",
|
||||
"Download Completed": "Nedlasting Fullført"
|
||||
"Go to element.io": "Gå til element.io"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Konfiguracja Elementa zawiera niepoprawny JSON. Popraw konfiguracje i odśwież stronę.",
|
||||
"Your Element is misconfigured": "Element jest nieprawidłowo skonfigurowany",
|
||||
"Powered by Matrix": "Zasilane przez Matrix",
|
||||
"Use %(brand)s on mobile": "Użyj %(brand)s w telefonie",
|
||||
"Switch to space by number": "Przełącz na przestrzeń według numeru"
|
||||
"Use %(brand)s on mobile": "Użyj %(brand)s w telefonie"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Seu browser não consegue rodar %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s usa funcionalidade de browser avançada que não é suportada por seu browser atual.",
|
||||
"Powered by Matrix": "Powered by Matrix",
|
||||
"Use %(brand)s on mobile": "Usar %(brand)s em celular",
|
||||
"Switch to space by number": "Trocar para espaço por número"
|
||||
"Use %(brand)s on mobile": "Usar %(brand)s em celular"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Unable to load config file: please refresh the page to try again.": "Nu se poate încărca fișierul de configurație: vă rugăm sa reîncărcați pagina și să încercați din nou.",
|
||||
"The message from the parser is: %(message)s": "Mesajul de la parser este: %(message)s",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Configurația ta Element conține JSON invalid. Vă rugăm sa corectați problema și să reîncărcați pagina.",
|
||||
"Invalid configuration: no default server specified.": "Configurație invalidă: niciun server implicit specificat.",
|
||||
"Switch to space by number": "Comută spațiul folosind un număr"
|
||||
"Invalid configuration: no default server specified.": "Configurație invalidă: niciun server implicit specificat."
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"Create Account": "Создать учётную запись",
|
||||
"Explore rooms": "Список комнат",
|
||||
"Unexpected error preparing the app. See console for details.": "Неожиданная ошибка при подготовке приложения. Подробности см. в консоли.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Неверная конфигурация: можно указывать только один из следующих параметров: default_server_config, default_server_name или default_hs_url.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Неверная конфигурация: может указывать только один из следующих параметров: default_server_config, default_server_name или default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "Неверная конфигурация: сервер по умолчанию не указан.",
|
||||
"The message from the parser is: %(message)s": "Сообщение из парсера: %(message)s",
|
||||
"Invalid JSON": "Нерабочий JSON",
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Ваш браузер не может запустить %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s использует расширенные возможности, которые не поддерживаются вашим браузером.",
|
||||
"Powered by Matrix": "На технологии Matrix",
|
||||
"Use %(brand)s on mobile": "Воспользуйтесь %(brand)s на мобильном телефоне",
|
||||
"Switch to space by number": "Переключение на пространство по номеру"
|
||||
"Use %(brand)s on mobile": "Воспользуйтесь %(brand)s на мобильном телефоне"
|
||||
}
|
||||
|
||||
@@ -4,15 +4,5 @@
|
||||
"Welcome to Element": "ඉලමන්ට් වෙත සාදරයෙන් පිළිගනිමු",
|
||||
"Open": "විවෘත කරන්න",
|
||||
"Powered by Matrix": "මැට්රික්ස් මඟින් බලගන්වා ඇත",
|
||||
"Sign In": "පිවිසෙන්න",
|
||||
"Dismiss": "ඉවතලන්න",
|
||||
"Explore rooms": "කාමර බලන්න",
|
||||
"Create Account": "ගිණුමක් සාදන්න",
|
||||
"Failed to start": "ඇරඹීමට අපොහොසත් විය",
|
||||
"Go to element.io": "element.io වෙත යන්න",
|
||||
"Your browser can't run %(brand)s": "ඔබගේ අතිරික්සුවට %(brand)s ධාවනය කළ නොහැකිය",
|
||||
"Unsupported browser": "සහය නොදක්වන අතිරික්සුව කි",
|
||||
"Go to your browser to complete Sign In": "පිවිසීම සම්පූර්ණ කිරීමට ඔබගේ අතිරික්සුව වෙත යන්න",
|
||||
"Download Completed": "බාගැනීම සම්පූර්ණයි",
|
||||
"Open user settings": "පරිශීලක සැකසුම් විවෘත කරන්න"
|
||||
"Sign In": "පිවිසෙන්න"
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"Dismiss": "Zamietnuť",
|
||||
"powered by Matrix": "poháňa Matrix",
|
||||
"Welcome to Element": "Víta vás Element",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralizované, šifrované konverzácie a spolupráca na platforme [matrix]",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Decentralizovaný, šifrovaný chat a spolupráca na platforme [matrix]",
|
||||
"Sign In": "Prihlásiť sa",
|
||||
"Create Account": "Vytvoriť účet",
|
||||
"Explore rooms": "Preskúmať miestnosti",
|
||||
@@ -32,7 +32,5 @@
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Vaša konfigurácia Elementu obsahuje nesprávny údaj JSON. Prosím, opravte chybu a obnovte stránku.",
|
||||
"Your browser can't run %(brand)s": "Váš prehliadač nerozbehne %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s používa pokročilé funkcie prehliadača, ktoré nie sú podporované vaším aktuálnym prehliadačom.",
|
||||
"Powered by Matrix": "používa protokol Matrix",
|
||||
"Use %(brand)s on mobile": "Používať %(brand)s pri mobilných zariadeniach",
|
||||
"Switch to space by number": "Prepnúť do priestoru podľa čísla"
|
||||
"Powered by Matrix": "používa protokol Matrix"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "Shfletuesi juaj s’mund të xhirojë %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s përdor veçori të thelluara të shfletuesit, të cilat shfletuesi juaj i tanishëm s’i mbulon.",
|
||||
"Powered by Matrix": "Bazuar në Matrix",
|
||||
"Use %(brand)s on mobile": "Përdor %(brand)s në celular",
|
||||
"Switch to space by number": "Kalo te hapësira me numrin"
|
||||
"Use %(brand)s on mobile": "Përdor %(brand)s në celular"
|
||||
}
|
||||
|
||||
@@ -33,6 +33,5 @@
|
||||
"Powered by Matrix": "Drivs av Matrix",
|
||||
"Your browser can't run %(brand)s": "Din webbläsare kan inte köra %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s använder avancerade webbläsarfunktioner som inte stöds av din aktuella webbläsare.",
|
||||
"Use %(brand)s on mobile": "Använd %(brand)s på mobilen",
|
||||
"Switch to space by number": "Byt till utrymme med nummer"
|
||||
"Use %(brand)s on mobile": "Använd %(brand)s på mobilen"
|
||||
}
|
||||
|
||||
@@ -15,16 +15,5 @@
|
||||
"Go to element.io": "ไปยัง element.io",
|
||||
"Failed to start": "ไม่สามารถเริ่ม",
|
||||
"Open": "เปิด",
|
||||
"Powered by Matrix": "ขับเคลื่อนโดย Matrix",
|
||||
"Unexpected error preparing the app. See console for details.": "เกิดข้อผิดพลาดที่ไม่คาดคิดขณะการเตรียมพร้อมโปรแกรม. คุณสามารถดูรายละเอียดข้อผิดพลาดได้ที่หน้าคอนโซล.",
|
||||
"Unable to load config file: please refresh the page to try again.": "ไม่สามารถโหลดการตั้งค่า: โปรดรีเฟรชหน้าเว็บเพื่อลองใหม่อีกครั้ง.",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "การตั้งค่าของ Element จะต้องอยู่ในรูปแบบ JSON. โปรดแก้ไขการตั้งค่าและโหลดหน้านี้ใหม่อีกครั้ง.",
|
||||
"Your Element is misconfigured": "การตั้งค่าของคุณไม่ถูกต้อง",
|
||||
"Invalid configuration: no default server specified.": "คุณยังไม่ได้ตั้งค่าเซิฟเวอร์หลักในการตั้งค่า.",
|
||||
"I understand the risks and wish to continue": "ฉันเข้าใจความเสี่ยง และดำเนินการต่อ",
|
||||
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "กรุณาติดตั้ง <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, หรือ <safariLink>Safari</safariLink> เพื่อประสิทธิภาพการใช้งานที่ดีที่สุด.",
|
||||
"Your browser can't run %(brand)s": "เบราว์เซอร์ของคุณไม่สามารถใช้งาน %(brand)s ได้",
|
||||
"Unsupported browser": "เบราว์เซอร์ไม่รองรับ",
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"Previous/next recently visited room or community": "ห้อง/ชุมชน ที่เคยเยี่ยมชมไปก่อนหน้า"
|
||||
"Powered by Matrix": "ขับเคลื่อนโดย Matrix"
|
||||
}
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
"Sign In": "Giriş Yap",
|
||||
"Create Account": "Hesap Oluştur",
|
||||
"Explore rooms": "Odaları keşfet",
|
||||
"Invalid JSON": "Hatalı JSON",
|
||||
"Invalid JSON": "JSON geçersiz",
|
||||
"Unexpected error preparing the app. See console for details.": "Uygulama hazırlanırken beklenmeyen bir hata oldu. Detaylar için konsola bakın.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Hatalı ayarlar: default_server_config, default_server_name ve default_hs_url ayarlarından en fazla biri girilebilir.",
|
||||
"Invalid configuration: no default server specified.": "Hatalı ayarlar: varsayılan sunucu belirlenmemiş.",
|
||||
"Invalid configuration: no default server specified.": "Geçersiz yapılandırma: varsayılan sunucu seçilmemiş.",
|
||||
"The message from the parser is: %(message)s": "Ayrıştırıcıdan gelen mesaj: %(message)s",
|
||||
"Go to your browser to complete Sign In": "Oturum açmayı tamamlamak için tarayıcınıza gidin",
|
||||
"Open user settings": "Kullanıcı ayarlarını aç",
|
||||
@@ -33,6 +33,5 @@
|
||||
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Masaüstü (%(platformName)s)",
|
||||
"Open": "Aç",
|
||||
"Missing indexeddb worker script!": "Indexeddb worker kodu eksik!",
|
||||
"Use %(brand)s on mobile": "Mobilde %(brand)s kullan",
|
||||
"Switch to space by number": "Sayı ile belirtilen alana geç"
|
||||
"Use %(brand)s on mobile": "Mobilde %(brand)s kullan"
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"You can continue using your current browser, but some or all features may not work and the look and feel of the application may be incorrect.": "Ви можете продовжити, користуючись вашим поточним браузером, але деякі функції можуть не працювати, а застосунок може виглядати неправильно.",
|
||||
"I understand the risks and wish to continue": "Я усвідомлюю ризик і бажаю продовжити",
|
||||
"Go to element.io": "Перейти на element.io",
|
||||
"Failed to start": "Не вдалося запустити",
|
||||
"Failed to start": "Запуск не вдався",
|
||||
"Download Completed": "Завантаження завершено",
|
||||
"Missing indexeddb worker script!": "Відсутній робочий сценарій IndexedDB!",
|
||||
"Your Element is misconfigured": "Ваш Element налаштовано неправильно",
|
||||
@@ -33,6 +33,5 @@
|
||||
"Powered by Matrix": "Працює на Matrix",
|
||||
"Your browser can't run %(brand)s": "Ваш переглядач неспроможний запустити %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s використовує передові властивості, які ваш браузер не підтримує.",
|
||||
"Use %(brand)s on mobile": "Користуйтеся %(brand)s на мобільному",
|
||||
"Switch to space by number": "Перейдіть до простору за номером"
|
||||
"Use %(brand)s on mobile": "Користуйтеся %(brand)s на мобільному"
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{}
|
||||
@@ -33,6 +33,5 @@
|
||||
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
|
||||
"Missing indexeddb worker script!": "Thiếu tệp lệnh làm việc của indexeddb!",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Thiết lập Element của bạn chứa JSON không hợp lệ. Vui lòng sửa vấn đề và tải lại trang.",
|
||||
"Your Element is misconfigured": "Element của bạn bị thiết lập sai",
|
||||
"Switch to space by number": "Chuyển sang Space bằng số"
|
||||
"Your Element is misconfigured": "Element của bạn bị thiết lập sai"
|
||||
}
|
||||
|
||||
@@ -11,8 +11,8 @@
|
||||
"The message from the parser is: %(message)s": "语法分析器的信息:%(message)s",
|
||||
"Invalid JSON": "无效的 JSON",
|
||||
"Unexpected error preparing the app. See console for details.": "软件准备时出错,详细信息请查看控制台。",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "配置无效: 只能设置 default_server_config、default_server_name 或 default_hs_url。",
|
||||
"Invalid configuration: no default server specified.": "配置无效:没有设置默认服务器。",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "无效的配置:只能设置 default_server_config,default_server_name 或 default_hs_url 中的一个。",
|
||||
"Invalid configuration: no default server specified.": "无效的配置:没有设置默认服务器。",
|
||||
"Missing indexeddb worker script!": "缺少 IndexedDB 辅助脚本!",
|
||||
"Unable to load config file: please refresh the page to try again.": "无法加载配置文件:请再次刷新页面。",
|
||||
"Open user settings": "打开用户设置",
|
||||
@@ -33,6 +33,5 @@
|
||||
"Your browser can't run %(brand)s": "浏览器无法运行 %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "当前浏览器不支持 %(brand)s 所需的高级浏览器特性。",
|
||||
"Powered by Matrix": "由 Matrix 驱动",
|
||||
"Use %(brand)s on mobile": "在移动设备上使用 %(brand)s",
|
||||
"Switch to space by number": "按数字切换空间"
|
||||
"Use %(brand)s on mobile": "在移动设备上使用 %(brand)s"
|
||||
}
|
||||
|
||||
@@ -30,9 +30,8 @@
|
||||
"Open": "開啟",
|
||||
"Your Element is misconfigured": "Element 配置錯誤",
|
||||
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Element 的配置中包含無效JSON,請更正錯誤並重新加載網頁。",
|
||||
"Your browser can't run %(brand)s": "您的瀏覽器無法執行 %(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s 使用了您目前的瀏覽器不支援的進階瀏覽器功能。",
|
||||
"Your browser can't run %(brand)s": "當前瀏覽器無法運行%(brand)s",
|
||||
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "當前瀏覽器不支持%(brand)s使用的高級特性。",
|
||||
"Powered by Matrix": "由 Matrix 提供",
|
||||
"Use %(brand)s on mobile": "在行動裝置上使用 %(brand)s",
|
||||
"Switch to space by number": "依數字切換至空間"
|
||||
"Use %(brand)s on mobile": "在行動裝置上使用 %(brand)s"
|
||||
}
|
||||
|
||||
@@ -19,30 +19,33 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import * as sdk from 'matrix-react-sdk';
|
||||
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
||||
import { _td, newTranslatableError } from 'matrix-react-sdk/src/languageHandler';
|
||||
import AutoDiscoveryUtils from 'matrix-react-sdk/src/utils/AutoDiscoveryUtils';
|
||||
import { AutoDiscovery } from "matrix-js-sdk/src/autodiscovery";
|
||||
import * as Lifecycle from "matrix-react-sdk/src/Lifecycle";
|
||||
import SdkConfig, { parseSsoRedirectOptions } from "matrix-react-sdk/src/SdkConfig";
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
import { createClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
import type MatrixChatType from "matrix-react-sdk/src/components/structures/MatrixChat";
|
||||
import { parseQs, parseQsFromFragment } from './url_utils';
|
||||
import VectorBasePlatform from "./platform/VectorBasePlatform";
|
||||
|
||||
// add React and ReactPerf to the global namespace, to make them easier to access via the console
|
||||
// this incidentally means we can forget our React imports in JSX files without penalty.
|
||||
window.React = React;
|
||||
|
||||
import * as sdk from 'matrix-react-sdk';
|
||||
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
||||
import { _t, _td, newTranslatableError } from 'matrix-react-sdk/src/languageHandler';
|
||||
import AutoDiscoveryUtils from 'matrix-react-sdk/src/utils/AutoDiscoveryUtils';
|
||||
import { AutoDiscovery } from "matrix-js-sdk/src/autodiscovery";
|
||||
import * as Lifecycle from "matrix-react-sdk/src/Lifecycle";
|
||||
import type MatrixChatType from "matrix-react-sdk/src/components/structures/MatrixChat";
|
||||
import { MatrixClientPeg } from 'matrix-react-sdk/src/MatrixClientPeg';
|
||||
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
||||
|
||||
// P2P only, probably should be relocated
|
||||
import Modal from 'matrix-react-sdk/src/Modal';
|
||||
import { IDialogProps } from 'matrix-react-sdk/src/components/views/dialogs/IDialogProps';
|
||||
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
|
||||
import { getCachedRoomIDForAlias } from 'matrix-react-sdk/src/RoomAliasCache';
|
||||
import { Room } from "matrix-js-sdk/src/models/room";
|
||||
|
||||
import { parseQs, parseQsFromFragment } from './url_utils';
|
||||
import VectorBasePlatform from "./platform/VectorBasePlatform";
|
||||
import { createClient } from "matrix-js-sdk/src/matrix";
|
||||
|
||||
let lastLocationHashSet: string = null;
|
||||
|
||||
logger.log(`Application is running in ${process.env.NODE_ENV} mode`);
|
||||
|
||||
window.matrixLogger = logger;
|
||||
|
||||
// Parse the given window.location and return parameters that can be used when calling
|
||||
// MatrixChat.showScreen(screen, params)
|
||||
function getScreenFromLocation(location: Location) {
|
||||
@@ -58,7 +61,7 @@ function getScreenFromLocation(location: Location) {
|
||||
function routeUrl(location: Location) {
|
||||
if (!window.matrixChat) return;
|
||||
|
||||
logger.log("Routing URL ", location.href);
|
||||
console.log("Routing URL ", location.href);
|
||||
const s = getScreenFromLocation(location);
|
||||
(window.matrixChat as MatrixChatType).showScreen(s.screen, s.params);
|
||||
}
|
||||
@@ -74,23 +77,193 @@ function onHashChange(ev: HashChangeEvent) {
|
||||
// This will be called whenever the SDK changes screens,
|
||||
// so a web page can update the URL bar appropriately.
|
||||
function onNewScreen(screen: string, replaceLast = false) {
|
||||
logger.log("newscreen " + screen);
|
||||
console.log("newscreen " + screen);
|
||||
const hash = '#/' + screen;
|
||||
lastLocationHashSet = hash;
|
||||
|
||||
// if the new hash is a substring of the old one then we are stripping fields e.g `via` so replace history
|
||||
if (screen.startsWith("room/") &&
|
||||
window.location.hash.includes("/$") === hash.includes("/$") && // only if both did or didn't contain event link
|
||||
window.location.hash.startsWith(hash)
|
||||
) {
|
||||
replaceLast = true;
|
||||
}
|
||||
|
||||
if (replaceLast) {
|
||||
window.location.replace(hash);
|
||||
} else {
|
||||
window.location.assign(hash);
|
||||
}
|
||||
|
||||
if (!window.matrixChat) {
|
||||
return;
|
||||
}
|
||||
let creds = null;
|
||||
if (screen === "register" || screen === "login" || screen === "welcome") {
|
||||
autoRegister().then((newCreds) => {
|
||||
creds = newCreds;
|
||||
return (window.matrixChat as MatrixChatType).onUserCompletedLoginFlow(
|
||||
newCreds, "-",
|
||||
);
|
||||
}, (err) => {
|
||||
console.error("Failed to auto-register:", err);
|
||||
}).then(() => {
|
||||
// first time user
|
||||
if (creds._registered) {
|
||||
p2pFirstTimeSetup();
|
||||
}
|
||||
});
|
||||
} else if (screen.startsWith("room/")) {
|
||||
// room/!foo:bar
|
||||
// room/#foo:bar
|
||||
// if this room is public then make sure it is published.
|
||||
p2pEnsurePublished(screen.split("/")[1]);
|
||||
}
|
||||
}
|
||||
|
||||
const P2PDisplayNameDialog: React.FC<IDialogProps> = ({ onFinished }) => {
|
||||
const BaseDialog = sdk.getComponent('views.dialogs.BaseDialog');
|
||||
const ChangeDisplayName = sdk.getComponent('settings.ChangeDisplayName');
|
||||
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
|
||||
|
||||
return <BaseDialog
|
||||
onFinished={onFinished}
|
||||
title={_t('Set a display name:')}
|
||||
>
|
||||
<ChangeDisplayName onFinished={onFinished} />
|
||||
<DialogButtons
|
||||
primaryButton={_t('OK')}
|
||||
onPrimaryButtonClick={onFinished}
|
||||
hasCancel={false}
|
||||
/>
|
||||
</BaseDialog>;
|
||||
};
|
||||
|
||||
function p2pFirstTimeSetup() {
|
||||
// Prompt them to set a display name
|
||||
Modal.createDialog(P2PDisplayNameDialog,
|
||||
{
|
||||
onFinished: () => {
|
||||
// View the room directory after display name has been sorted out
|
||||
dis.dispatch({
|
||||
action: 'view_room_directory',
|
||||
});
|
||||
},
|
||||
}, null, /* priority = */ false, /* static = */ true,
|
||||
);
|
||||
}
|
||||
|
||||
async function fetchRoom(roomId: string): Room {
|
||||
const client = MatrixClientPeg.get();
|
||||
let room = client.getRoom(roomId);
|
||||
if (room) {
|
||||
return room;
|
||||
}
|
||||
console.log("p2pEnsurePublished fetchRoom waiting for room... ", roomId);
|
||||
room = await new Promise((resolve, reject) => {
|
||||
let fulfilled = false;
|
||||
const cb = function(room) {
|
||||
if (fulfilled) {
|
||||
return;
|
||||
}
|
||||
const newRoomId = room.roomId;
|
||||
if (roomId === newRoomId) {
|
||||
fulfilled = true;
|
||||
console.log("p2pEnsurePublished fetchRoom found ", roomId);
|
||||
resolve(room);
|
||||
}
|
||||
};
|
||||
client.on("Room", cb);
|
||||
setTimeout(() => {
|
||||
if (fulfilled) {
|
||||
return;
|
||||
}
|
||||
console.log("p2pEnsurePublished fetchRoom timed out ", roomId);
|
||||
fulfilled = true;
|
||||
client.removeListener("Room", cb);
|
||||
reject(new Error("timed out waiting to see room " + roomId));
|
||||
}, 60 * 1000); // wait 60s
|
||||
});
|
||||
return room;
|
||||
}
|
||||
|
||||
async function p2pEnsurePublished(roomIdOrAlias: string) {
|
||||
// If the room has just been created, we need to wait for the join_rules to come down /sync
|
||||
// If the app has just been refreshed, we need to wait for the DB to be loaded.
|
||||
// Since we don't really care when this is done, just sleep a bit.
|
||||
await sleep(3000);
|
||||
console.log("p2pEnsurePublished ", roomIdOrAlias);
|
||||
try {
|
||||
const client = MatrixClientPeg.get();
|
||||
// convert alias to room ID
|
||||
let roomId;
|
||||
let aliasLocalpart;
|
||||
if (roomIdOrAlias.startsWith("!")) {
|
||||
roomId = roomIdOrAlias;
|
||||
} else {
|
||||
roomId = getCachedRoomIDForAlias(roomIdOrAlias);
|
||||
// extract the localpart so we can republish this alias on our server
|
||||
aliasLocalpart = roomIdOrAlias.split(":")[0].substring(1);
|
||||
}
|
||||
|
||||
// fetch the join_rules, check if public
|
||||
const room = await fetchRoom(roomId);
|
||||
if (!room) {
|
||||
throw new Error("No room for room ID: " + roomId);
|
||||
}
|
||||
if (!aliasLocalpart) {
|
||||
const roomName = room.currentState.getStateEvents("m.room.name", "");
|
||||
if (roomName) {
|
||||
aliasLocalpart = roomName.getContent().name;
|
||||
// room alias grammar is poorly defined. Synapse rejects whitespace, Riot barfs on slashes, it's a mess.
|
||||
// so for now, let's just do A-Za-z0-9_-
|
||||
aliasLocalpart = aliasLocalpart.replace(/[^A-Za-z0-9_-]/g, "");
|
||||
} else {
|
||||
// use the random part of the room ID as a fallback.
|
||||
aliasLocalpart = roomId.split(":")[0].substring(1);
|
||||
}
|
||||
}
|
||||
|
||||
const joinRules = room.currentState.getStateEvents("m.room.join_rules", "");
|
||||
if (!joinRules) {
|
||||
throw new Error("No join_rules for room ID: " + roomId);
|
||||
}
|
||||
const isPublic = joinRules.getContent().join_rule === "public";
|
||||
|
||||
if (isPublic) {
|
||||
// make sure that there is an alias mapping
|
||||
try {
|
||||
for (let i = 0; i < 2; i++) {
|
||||
const newRoomAlias = `#${aliasLocalpart}:${client.getDomain()}`;
|
||||
let exists = false;
|
||||
let matches = false;
|
||||
try {
|
||||
const aliasResponse = await client.getRoomIdForAlias(newRoomAlias);
|
||||
matches = aliasResponse.room_id === roomId;
|
||||
exists = true;
|
||||
} catch (err) {}
|
||||
console.log(
|
||||
"p2pEnsurePublished: room ID:", roomId, " want alias: ", newRoomAlias,
|
||||
" exists=", exists, " matches=", matches,
|
||||
);
|
||||
if (!exists) {
|
||||
await client.createAlias(newRoomAlias, roomId);
|
||||
break;
|
||||
} else if (!matches) {
|
||||
// clashing room alias, use the room ID.
|
||||
aliasLocalpart = roomId.split(":")[0].substring(1);
|
||||
} else {
|
||||
// exists and matches, do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("p2pEnsurePublished: problem creating alias: ", err);
|
||||
}
|
||||
|
||||
// publish the room
|
||||
await client.setRoomDirectoryVisibility(roomId, "public");
|
||||
console.log("p2pEnsurePublished: Now published.");
|
||||
} else {
|
||||
// unpublish the room
|
||||
await client.setRoomDirectoryVisibility(roomId, "private");
|
||||
console.log("p2pEnsurePublished: Now hidden.");
|
||||
}
|
||||
} catch (err) {
|
||||
console.log("p2pEnsurePublished encountered an error: ", err);
|
||||
}
|
||||
}
|
||||
|
||||
// We use this to work out what URL the SDK should
|
||||
@@ -136,11 +309,116 @@ function onTokenLoginCompleted() {
|
||||
|
||||
url.searchParams.delete("loginToken");
|
||||
|
||||
logger.log(`Redirecting to ${url.href} to drop loginToken from queryparams`);
|
||||
console.log(`Redirecting to ${url.href} to drop loginToken from queryparams`);
|
||||
window.history.replaceState(null, "", url.href);
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
async function autoRegister() {
|
||||
console.log("dendrite: Auto-registration in progress");
|
||||
const cli = createClient({
|
||||
baseUrl: window.location.origin,
|
||||
});
|
||||
const password = "this should be really really secure";
|
||||
|
||||
// Make sure the server is up (active service worker)
|
||||
await navigator.serviceWorker.ready;
|
||||
// On Firefox, the ready promise resolves just prior to activation.
|
||||
// On Chrome, the ready promise resolves just after activation.
|
||||
// We need to make requests AFTER we have been activated, else the /register request
|
||||
// will fail.
|
||||
await sleep(10);
|
||||
|
||||
let response = null;
|
||||
let didRegister = false;
|
||||
try {
|
||||
response = await cli.registerRequest({
|
||||
username: "p2p",
|
||||
password,
|
||||
auth: {
|
||||
type: "m.login.dummy",
|
||||
},
|
||||
});
|
||||
console.log("dendrite: Auto-registration done ", response);
|
||||
didRegister = true;
|
||||
} catch (err) {
|
||||
console.error("dendrite: failed to register, trying to login:", err);
|
||||
response = await cli.login("m.login.password", {
|
||||
identifier: {
|
||||
type: "m.id.user",
|
||||
user: "p2p",
|
||||
},
|
||||
password,
|
||||
initial_device_display_name: "p2p-dendrite",
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
userId: response.user_id,
|
||||
deviceId: response.device_id,
|
||||
homeserverUrl: cli.getHomeserverUrl(),
|
||||
identityServerUrl: cli.getIdentityServerUrl(),
|
||||
accessToken: response.access_token,
|
||||
guest: cli.isGuest(),
|
||||
_registered: didRegister,
|
||||
};
|
||||
}
|
||||
|
||||
export async function loadApp(fragParams: {}) {
|
||||
// XXX: the way we pass the path to the worker script from webpack via html in body's dataset is a hack
|
||||
// but alternatives seem to require changing the interface to passing Workers to js-sdk
|
||||
const vectorIndexeddbWorkerScript = document.body.dataset.vectorIndexeddbWorkerScript;
|
||||
if (!vectorIndexeddbWorkerScript) {
|
||||
// If this is missing, something has probably gone wrong with
|
||||
// the bundling. The js-sdk will just fall back to accessing
|
||||
// indexeddb directly with no worker script, but we want to
|
||||
// make sure the indexeddb script is present, so fail hard.
|
||||
throw newTranslatableError(_td("Missing indexeddb worker script!"));
|
||||
}
|
||||
// MatrixClientPeg.setIndexedDbWorkerScript(vectorIndexeddbWorkerScript);
|
||||
|
||||
// load dendrite, if available
|
||||
const vectorDendriteWorkerScript = document.body.dataset.vectorDendriteWorkerScript;
|
||||
if (vectorDendriteWorkerScript && 'serviceWorker' in navigator) {
|
||||
console.log("dendrite code exec... ", document.readyState);
|
||||
const loadDendriteSw = () => {
|
||||
console.log("Registering dendrite sw...", vectorDendriteWorkerScript);
|
||||
console.log("swjs: invoke navigator.serviceWorker.register");
|
||||
navigator.serviceWorker.register(vectorDendriteWorkerScript, { scope: "/" }).then(function(registration) {
|
||||
console.log("swjs: navigator.serviceWorker.register resolved", registration);
|
||||
// Registration was successful
|
||||
console.log('ServiceWorker sw.js registration successful with scope: ', registration.scope);
|
||||
// periodically check for updates
|
||||
setInterval(function() {
|
||||
console.log("swjs invoke registration.update");
|
||||
registration.update();
|
||||
}, 1000 * 60 * 30); // once every 30 minutes
|
||||
}, (err) => {
|
||||
// registration failed :(
|
||||
console.log('dendrite: ServiceWorker registration failed: ', err);
|
||||
});
|
||||
// First, do a one-off check if there's currently a
|
||||
// service worker in control.
|
||||
if (navigator.serviceWorker.controller) {
|
||||
console.log('dendrite: This page is currently controlled by:', navigator.serviceWorker.controller);
|
||||
}
|
||||
|
||||
// Then, register a handler to detect when a new or
|
||||
// updated service worker takes control.
|
||||
navigator.serviceWorker.oncontrollerchange = function() {
|
||||
console.log('dendrite: This page is now controlled by:', navigator.serviceWorker.controller);
|
||||
};
|
||||
};
|
||||
if (document.readyState === "loading") {
|
||||
window.addEventListener('DOMContentLoaded', loadDendriteSw);
|
||||
} else {
|
||||
loadDendriteSw();
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('hashchange', onHashChange);
|
||||
|
||||
const platform = PlatformPeg.get();
|
||||
@@ -148,7 +426,7 @@ export async function loadApp(fragParams: {}) {
|
||||
const params = parseQs(window.location);
|
||||
|
||||
const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
||||
logger.log("Vector starting at " + urlWithoutQuery);
|
||||
console.log("Vector starting at " + urlWithoutQuery);
|
||||
|
||||
(platform as VectorBasePlatform).startUpdater();
|
||||
|
||||
@@ -159,15 +437,9 @@ export async function loadApp(fragParams: {}) {
|
||||
const [userId] = await Lifecycle.getStoredSessionOwner();
|
||||
const hasPossibleToken = !!userId;
|
||||
const isReturningFromSso = !!params.loginToken;
|
||||
const ssoRedirects = parseSsoRedirectOptions(config);
|
||||
let autoRedirect = ssoRedirects.immediate === true;
|
||||
// XXX: This path matching is a bit brittle, but better to do it early instead of in the app code.
|
||||
const isWelcomeOrLanding = window.location.hash === '#/welcome' || window.location.hash === '#';
|
||||
if (!autoRedirect && ssoRedirects.on_welcome_page && isWelcomeOrLanding) {
|
||||
autoRedirect = true;
|
||||
}
|
||||
const autoRedirect = config['sso_immediate_redirect'] === true;
|
||||
if (!hasPossibleToken && !isReturningFromSso && autoRedirect) {
|
||||
logger.log("Bypassing app load to redirect to SSO");
|
||||
console.log("Bypassing app load to redirect to SSO");
|
||||
const tempCli = createClient({
|
||||
baseUrl: config['validated_server_config'].hsUrl,
|
||||
idBaseUrl: config['validated_server_config'].isUrl,
|
||||
@@ -197,7 +469,7 @@ export async function loadApp(fragParams: {}) {
|
||||
async function verifyServerConfig() {
|
||||
let validatedConfig;
|
||||
try {
|
||||
logger.log("Verifying homeserver configuration");
|
||||
console.log("Verifying homeserver configuration");
|
||||
|
||||
// Note: the query string may include is_url and hs_url - we only respect these in the
|
||||
// context of email validation. Because we don't respect them otherwise, we do not need
|
||||
@@ -228,8 +500,8 @@ async function verifyServerConfig() {
|
||||
}
|
||||
|
||||
if (hsUrl) {
|
||||
logger.log("Config uses a default_hs_url - constructing a default_server_config using this information");
|
||||
logger.warn(
|
||||
console.log("Config uses a default_hs_url - constructing a default_server_config using this information");
|
||||
console.warn(
|
||||
"DEPRECATED CONFIG OPTION: In the future, default_hs_url will not be accepted. Please use " +
|
||||
"default_server_config instead.",
|
||||
);
|
||||
@@ -248,13 +520,13 @@ async function verifyServerConfig() {
|
||||
|
||||
let discoveryResult = null;
|
||||
if (wkConfig) {
|
||||
logger.log("Config uses a default_server_config - validating object");
|
||||
console.log("Config uses a default_server_config - validating object");
|
||||
discoveryResult = await AutoDiscovery.fromDiscoveryConfig(wkConfig);
|
||||
}
|
||||
|
||||
if (serverName) {
|
||||
logger.log("Config uses a default_server_name - doing .well-known lookup");
|
||||
logger.warn(
|
||||
console.log("Config uses a default_server_name - doing .well-known lookup");
|
||||
console.warn(
|
||||
"DEPRECATED CONFIG OPTION: In the future, default_server_name will not be accepted. Please " +
|
||||
"use default_server_config instead.",
|
||||
);
|
||||
@@ -265,10 +537,10 @@ async function verifyServerConfig() {
|
||||
} catch (e) {
|
||||
const { hsUrl, isUrl, userId } = await Lifecycle.getStoredSessionVars();
|
||||
if (hsUrl && userId) {
|
||||
logger.error(e);
|
||||
logger.warn("A session was found - suppressing config error and using the session's homeserver");
|
||||
console.error(e);
|
||||
console.warn("A session was found - suppressing config error and using the session's homeserver");
|
||||
|
||||
logger.log("Using pre-existing hsUrl and isUrl: ", { hsUrl, isUrl });
|
||||
console.log("Using pre-existing hsUrl and isUrl: ", { hsUrl, isUrl });
|
||||
validatedConfig = await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(hsUrl, isUrl, true);
|
||||
} else {
|
||||
// the user is not logged in, so scream
|
||||
@@ -279,10 +551,10 @@ async function verifyServerConfig() {
|
||||
validatedConfig.isDefault = true;
|
||||
|
||||
// Just in case we ever have to debug this
|
||||
logger.log("Using homeserver config:", validatedConfig);
|
||||
console.log("Using homeserver config:", validatedConfig);
|
||||
|
||||
// Add the newly built config to the actual config for use by the app
|
||||
logger.log("Updating SdkConfig with validated discovery information");
|
||||
console.log("Updating SdkConfig with validated discovery information");
|
||||
SdkConfig.add({ "validated_server_config": validatedConfig });
|
||||
|
||||
return SdkConfig.get();
|
||||
|
||||
279
src/vector/dendrite-sw.js
Normal file
279
src/vector/dendrite-sw.js
Normal file
@@ -0,0 +1,279 @@
|
||||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
// Copyright 2020 New Vector Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
// Dendrite Service Worker version
|
||||
// Bumping the patch version of this has no side-effects.
|
||||
// Bumping the minor version of this will delete databases.
|
||||
const version = "0.2.0";
|
||||
|
||||
const isVersionBump = function(oldVer, newVer) {
|
||||
oldVer = oldVer || "";
|
||||
const newSegments = newVer.split(".");
|
||||
const oldSegments = oldVer.split(".");
|
||||
if (oldSegments.length != 3) {
|
||||
return true; // brand new
|
||||
}
|
||||
return newSegments[1] > oldSegments[1];
|
||||
}
|
||||
|
||||
const bundle_path = self.location.href.replace("/dendrite_sw.js", "")
|
||||
const id = Math.random();
|
||||
console.log("swjs: ", id," dendrite-sw.js file running...")
|
||||
self.registration.addEventListener('updatefound', () => {
|
||||
console.log("swjs: ", id," updatefound registration event fired")
|
||||
const newWorker = self.registration.installing;
|
||||
if (!newWorker) {
|
||||
console.log("swjs: ", id," updatefound registration event fired, no installing worker")
|
||||
return;
|
||||
}
|
||||
newWorker.addEventListener('statechange', () => {
|
||||
console.log("swjs: ", id," worker statechange: ", newWorker.state)
|
||||
});
|
||||
})
|
||||
|
||||
self.importScripts(`${bundle_path}/wasm_exec.js`,
|
||||
`${bundle_path}/sqlitejs.js`,
|
||||
`${bundle_path}/localforage.js`);
|
||||
|
||||
let isWriting = false;
|
||||
async function writeDatabasesToIndexedDB() {
|
||||
while (true) {
|
||||
await sleep(1000 * 30);
|
||||
try {
|
||||
await syncfs(false);
|
||||
}
|
||||
catch (err) {
|
||||
console.error("syncfs: failed to write to IDB:", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sleep(ms) {
|
||||
return new Promise(resolve => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
function syncfs(isStartup) {
|
||||
return new Promise((resolve, reject) => {
|
||||
global._go_sqlite.FS.syncfs(isStartup, function(err) {
|
||||
if (err) {
|
||||
console.error("syncfs failed:", err);
|
||||
reject(err);
|
||||
return;
|
||||
}
|
||||
console.log("syncfs OK");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function deleteDatabase(name) {
|
||||
return new Promise(function(resolve, reject) {
|
||||
const req = indexedDB.deleteDatabase(name);
|
||||
req.onsuccess = function () {
|
||||
console.log("Deleted database successfully: ", name);
|
||||
resolve();
|
||||
};
|
||||
req.onerror = function (event) {
|
||||
console.log("Couldn't delete database: ", name, event);
|
||||
reject(new Error("failed to delete database"));
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
async function initDendrite() {
|
||||
console.log(`dendrite-sw.js: v${version} SW init`)
|
||||
// check if we need to purge databases (minor version bump)
|
||||
const prevVer = await global.localforage.getItem("dendrite_version")
|
||||
if (prevVer != version) {
|
||||
const nukeDatabase = isVersionBump(prevVer, version);
|
||||
console.log(`dendrite-sw.js: previous ver ${prevVer} current ${version} nuke databases: ${nukeDatabase}`);
|
||||
if (nukeDatabase) {
|
||||
await deleteDatabase("/idb");
|
||||
}
|
||||
}
|
||||
|
||||
global.process = {
|
||||
pid: 1,
|
||||
env: {
|
||||
DEBUG: "*",
|
||||
}
|
||||
};
|
||||
// we do this for prometheus so it doesn't panic on init()
|
||||
global.fs.stat = function(path, cb) {
|
||||
cb({
|
||||
code: "EINVAL",
|
||||
});
|
||||
}
|
||||
|
||||
const config = {
|
||||
locateFile: filename => `${bundle_path}/../../sql-wasm.wasm`
|
||||
}
|
||||
|
||||
const go = new Go();
|
||||
await sqlitejs.init(config);
|
||||
|
||||
// periodically write databases to disk
|
||||
if (!isWriting) {
|
||||
isWriting = true;
|
||||
// have to do this before we start dendrite for hopefully obvious reasons...
|
||||
console.log("syncfs", global._go_sqlite.IDBFS);
|
||||
global._go_sqlite.FS.mkdir("/idb");
|
||||
//global._go_sqlite.FS.unmount("/");
|
||||
console.log("syncfs at /idb mkdir ok");
|
||||
global._go_sqlite.FS.mount(global._go_sqlite.IDBFS, {}, "/idb");
|
||||
console.log("syncfs mounted");
|
||||
await syncfs(true); // load from IDB
|
||||
writeDatabasesToIndexedDB();
|
||||
}
|
||||
|
||||
console.log(`dendrite-sw.js: v${version} starting dendrite.wasm...`)
|
||||
const result = await WebAssembly.instantiateStreaming(fetch(`${bundle_path}/../../dendrite.wasm`), go.importObject)
|
||||
go.run(result.instance).then(() => {
|
||||
console.log(`dendrite-sw.js: v${version} dendrite.wasm terminated, restarting...`);
|
||||
// purge databases and p2p nodes.
|
||||
global._go_js_server = undefined;
|
||||
global._go_sqlite_dbs.clear();
|
||||
initDendritePromise = initDendrite();
|
||||
});
|
||||
// make fetch calls go through this sw - notably if a page registers a sw, it does NOT go through any sw by default
|
||||
// unless you refresh or call this function.
|
||||
console.log(`dendrite-sw.js: v${version} claiming open browser tabs`)
|
||||
console.log("swjs: ", id," invoke self.clients.claim()")
|
||||
self.clients.claim();
|
||||
|
||||
let serverIsUp = false;
|
||||
for (let i = 0; i < 30; i++) { // 3s
|
||||
if (global._go_js_server) {
|
||||
console.log("swjs: ", id," init dendrite promise resolving");
|
||||
serverIsUp = true;
|
||||
break;
|
||||
}
|
||||
await sleep(100);
|
||||
}
|
||||
if (!serverIsUp) {
|
||||
throw new Error("Timed out waiting for _go_js_server to be set.");
|
||||
}
|
||||
// persist the new version
|
||||
await global.localforage.setItem("dendrite_version", version);
|
||||
}
|
||||
|
||||
let initDendritePromise = initDendrite();
|
||||
|
||||
self.addEventListener('install', function(event) {
|
||||
console.log("swjs: ", id," install event fired:", event)
|
||||
console.log(`dendrite-sw.js: v${version} SW install`)
|
||||
// Tell the browser to kill old sw's running in other tabs and replace them with this one
|
||||
// This may cause spontaneous logouts.
|
||||
console.log("swjs: ", id," invoke self.skipWaiting")
|
||||
self.skipWaiting();
|
||||
})
|
||||
|
||||
self.addEventListener('activate', function(event) {
|
||||
console.log("swjs: ", id," activate event fired")
|
||||
console.log(`dendrite-sw.js: v${version} SW activate`)
|
||||
event.waitUntil(initDendritePromise)
|
||||
})
|
||||
|
||||
async function sendRequestToGo(event) {
|
||||
await initDendritePromise; // this sets the global fetch listener
|
||||
if (!global._go_js_server || !global._go_js_server.fetch) {
|
||||
console.log(`dendrite-sw.js: v${version} no fetch listener present for ${event.request.url}`);
|
||||
return
|
||||
}
|
||||
console.log(`dendrite-sw.js: v${version} forwarding ${event.request.url} to Go`);
|
||||
const req = event.request
|
||||
let reqHeaders = ''
|
||||
if (req.headers) {
|
||||
for (const header of req.headers) {
|
||||
// FIXME: is this a safe header encoding?
|
||||
reqHeaders += `${header[0]}: ${header[1]}\n`
|
||||
}
|
||||
}
|
||||
let jj = null;
|
||||
if (req.method === "POST" || req.method === "PUT") {
|
||||
jj = await req.json();
|
||||
jj = JSON.stringify(jj);
|
||||
reqHeaders += `Content-Length: ${new Blob([jj]).size}`; // include utf-8 chars properly
|
||||
}
|
||||
|
||||
if (reqHeaders.length > 0) {
|
||||
reqHeaders = `\r\n${reqHeaders}`
|
||||
}
|
||||
|
||||
// Replace the timeout value for /sync calls to be 20s not 30s because Firefox
|
||||
// will aggressively cull service workers after a 30s idle period. Chrome doesn't.
|
||||
// See https://bugzilla.mozilla.org/show_bug.cgi?id=1378587
|
||||
const fullurl = req.url.replace("timeout=30000", "timeout=20000");
|
||||
|
||||
const reqString = `${req.method} ${fullurl} HTTP/1.0${reqHeaders}\r\n\r\n${jj ? jj : ''}`
|
||||
|
||||
const res = await global._go_js_server.fetch(reqString)
|
||||
if (res.error) {
|
||||
console.error(`dendrite-sw.js: v${version} Error for request: ${event.request.url} => ${res.error}`)
|
||||
return
|
||||
}
|
||||
const respString = res.result;
|
||||
|
||||
const m = respString.match(/^(HTTP\/1.[01]) ((.*?) (.*?))(\r\n([^]*?)?(\r\n\r\n([^]*?)))?$/)
|
||||
if (!m) {
|
||||
console.warn("couldn't parse resp", respString);
|
||||
return;
|
||||
}
|
||||
const response = {
|
||||
"proto": m[1],
|
||||
"status": m[2],
|
||||
"statusCode": parseInt(m[3]),
|
||||
"headers": m[6],
|
||||
"body": m[8],
|
||||
}
|
||||
|
||||
const respHeaders = new Headers()
|
||||
const headerLines = response.headers.split('\r\n')
|
||||
for (const headerLine of headerLines) {
|
||||
// FIXME: is this safe header parsing? Do we need to worry about line-wrapping?
|
||||
const match = headerLine.match(/^(.+?): *(.*?)$/)
|
||||
if (match) {
|
||||
respHeaders.append(match[1], match[2])
|
||||
}
|
||||
else {
|
||||
console.log("couldn't parse headerLine ", headerLine)
|
||||
}
|
||||
}
|
||||
|
||||
return new Response(response.body, {
|
||||
status: response.statusCode,
|
||||
headers: respHeaders,
|
||||
})
|
||||
}
|
||||
|
||||
self.addEventListener('fetch', function(event) {
|
||||
event.respondWith((async () => {
|
||||
/*
|
||||
// If this is a page refresh for the current page, then shunt in the new sw
|
||||
// https://github.com/w3c/ServiceWorker/issues/1238
|
||||
if (event.request.mode === "navigate" && event.request.method === "GET" && registration.waiting && (await clients.matchAll()).length < 2) {
|
||||
console.log("Forcing new sw.js into page")
|
||||
registration.waiting.postMessage('skipWaiting');
|
||||
return new Response("", {headers: {"Refresh": "0"}});
|
||||
} */
|
||||
|
||||
if (event.request.url.match(/\/_matrix\/client/)) {
|
||||
return await sendRequestToGo(event);
|
||||
}
|
||||
else {
|
||||
return fetch(event.request);
|
||||
}
|
||||
})());
|
||||
})
|
||||
BIN
src/vector/dendrite.wasm
Executable file
BIN
src/vector/dendrite.wasm
Executable file
Binary file not shown.
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
Copyright 2021 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* This code is removed on production builds.
|
||||
*
|
||||
* Webpack's `string-replace-loader` searches for the `use theming` string
|
||||
* in this specific file, and replaces it with CSS requires statements that
|
||||
* are specific to the themes we have enabled.
|
||||
*
|
||||
* Without this workaround, webpack would import the CSS of all themes, which
|
||||
* would defeat the purpose of hot-reloading since all themes would be compiled,
|
||||
* which would result in compilation times on the order of 30s, even on a
|
||||
* powerful machine.
|
||||
*
|
||||
* For more details, see webpack.config.js:184 (string-replace-loader)
|
||||
*/
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
("use theming");
|
||||
/**
|
||||
* Clean up old hot-module script injections as they hog up memory
|
||||
* and anything other than the newest one is really not needed at all.
|
||||
* We don't need to do it more frequently than every half a minute or so,
|
||||
* but it's done to delay full page reload due to app slowness.
|
||||
*/
|
||||
setInterval(() => {
|
||||
const elements = Array.from(document.querySelectorAll("script[src*=hot-update]"));
|
||||
if (elements.length > 1) {
|
||||
const oldInjects = elements.slice(0, elements.length - 1);
|
||||
oldInjects.forEach(e => e.remove());
|
||||
}
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
font-src 'self' data:;
|
||||
media-src * blob: data:;
|
||||
child-src * blob: data:;
|
||||
worker-src 'self' blob:;
|
||||
worker-src 'self';
|
||||
frame-src * blob: data:;
|
||||
form-action 'self';
|
||||
manifest-src 'self';
|
||||
@@ -43,7 +43,7 @@
|
||||
if (match) {
|
||||
var title = match[1].charAt(0).toUpperCase() + match[1].slice(1);
|
||||
%>
|
||||
<link rel="stylesheet" disabled="disabled" data-mx-theme="<%= title %>" title="<%= title %>" href="<%= file %>">
|
||||
<link rel="stylesheet" disabled="disabled" title="<%= title %>" href="<%= file %>">
|
||||
<% } else { %>
|
||||
<link rel="stylesheet" href="<%= file %>">
|
||||
<% }
|
||||
@@ -58,20 +58,25 @@
|
||||
} %>
|
||||
|
||||
</head>
|
||||
<body style="height: 100%; margin: 0;">
|
||||
<body
|
||||
style="height: 100%; margin: 0;"
|
||||
data-vector-indexeddb-worker-script="<%= htmlWebpackPlugin.files.js.find(entry => entry.includes("indexeddb-worker.js")) %>"
|
||||
data-vector-recorder-worklet-script="<%= htmlWebpackPlugin.files.js.find(entry => entry.includes("recorder-worklet.js")) %>"
|
||||
data-vector-dendrite-worker-script="<%= htmlWebpackPlugin.files.js.find(entry => entry.includes("dendrite_sw.js")) %>"
|
||||
>
|
||||
<noscript>Sorry, Element requires JavaScript to be enabled.</noscript> <!-- TODO: Translate this? -->
|
||||
<section id="matrixchat" style="height: 100%;" class="notranslate"></section>
|
||||
<script src="<%= htmlWebpackPlugin.files.js.find(entry => entry.includes("bundle.js")) %>"></script>
|
||||
|
||||
<!-- Legacy supporting Prefetch images -->
|
||||
<img src="<%= require('matrix-react-sdk/res/img/warning.svg') %>" aria-hidden alt="" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/e2e/warning.svg') %>" aria-hidden alt="" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/feather-customised/warning-triangle.svg') %>" aria-hidden alt="" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/bold.svg') %>" aria-hidden alt="" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/code.svg') %>" aria-hidden alt="" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/italics.svg') %>" aria-hidden alt="" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/quote.svg') %>" aria-hidden alt="" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/strikethrough.svg') %>" aria-hidden alt="" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/warning.svg') %>" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/e2e/warning.svg') %>" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/feather-customised/warning-triangle.svg') %>" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/bold.svg') %>" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/code.svg') %>" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/italics.svg') %>" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/quote.svg') %>" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/format/strikethrough.svg') %>" width="25" height="22" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
|
||||
<audio id="messageAudio">
|
||||
<source src="media/message.ogg" type="audio/ogg" />
|
||||
|
||||
@@ -18,41 +18,30 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { logger } from "matrix-js-sdk/src/logger";
|
||||
|
||||
// These are things that can run before the skin loads - be careful not to reference the react-sdk though.
|
||||
import { parseQsFromFragment } from "./url_utils";
|
||||
import './modernizr';
|
||||
|
||||
// Require common CSS here; this will make webpack process it into bundle.css.
|
||||
// Our own CSS (which is themed) is imported via separate webpack entry points
|
||||
// in webpack.config.js
|
||||
require('gfm.css/gfm.css');
|
||||
require('highlight.js/styles/github.css');
|
||||
require('katex/dist/katex.css');
|
||||
|
||||
/**
|
||||
* This require is necessary only for purposes of CSS hot-reload, as otherwise
|
||||
* webpack has some incredible problems figuring out which CSS files should be
|
||||
* hot-reloaded, even with proper hints for the loader.
|
||||
*
|
||||
* On production build it's going to be an empty module, so don't worry about that.
|
||||
*/
|
||||
require('./devcss');
|
||||
require('./localstorage-fix');
|
||||
// These are things that can run before the skin loads - be careful not to reference the react-sdk though.
|
||||
import { parseQsFromFragment } from "./url_utils";
|
||||
import './modernizr';
|
||||
|
||||
async function settled(...promises: Array<Promise<any>>) {
|
||||
for (const prom of promises) {
|
||||
try {
|
||||
await prom;
|
||||
} catch (e) {
|
||||
logger.error(e);
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function checkBrowserFeatures() {
|
||||
if (!window.Modernizr) {
|
||||
logger.error("Cannot check features - Modernizr global is missing.");
|
||||
console.error("Cannot check features - Modernizr global is missing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -79,14 +68,14 @@ function checkBrowserFeatures() {
|
||||
let featureComplete = true;
|
||||
for (let i = 0; i < featureList.length; i++) {
|
||||
if (window.Modernizr[featureList[i]] === undefined) {
|
||||
logger.error(
|
||||
console.error(
|
||||
"Looked for feature '%s' but Modernizr has no results for this. " +
|
||||
"Has it been configured correctly?", featureList[i],
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (window.Modernizr[featureList[i]] === false) {
|
||||
logger.error("Browser missing feature: '%s'", featureList[i]);
|
||||
console.error("Browser missing feature: '%s'", featureList[i]);
|
||||
// toggle flag rather than return early so we log all missing features rather than just the first.
|
||||
featureComplete = false;
|
||||
}
|
||||
@@ -175,13 +164,13 @@ async function start() {
|
||||
// ##########################
|
||||
if (!acceptBrowser) {
|
||||
await new Promise<void>(resolve => {
|
||||
logger.error("Browser is missing required features.");
|
||||
console.error("Browser is missing required features.");
|
||||
// take to a different landing page to AWOOOOOGA at the user
|
||||
showIncompatibleBrowser(() => {
|
||||
if (window.localStorage) {
|
||||
window.localStorage.setItem('mx_accepts_unsupported_browser', String(true));
|
||||
}
|
||||
logger.log("User accepts the compatibility risks.");
|
||||
console.log("User accepts the compatibility risks.");
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
@@ -224,7 +213,7 @@ async function start() {
|
||||
// run on the components.
|
||||
await loadApp(fragparts.params);
|
||||
} catch (err) {
|
||||
logger.error(err);
|
||||
console.error(err);
|
||||
// Like the compatibility page, AWOOOOOGA at the user
|
||||
// This uses the default brand since the app config is unavailable.
|
||||
await showError(_t("Your Element is misconfigured"), [
|
||||
@@ -234,7 +223,7 @@ async function start() {
|
||||
}
|
||||
|
||||
start().catch(err => {
|
||||
logger.error(err);
|
||||
console.error(err);
|
||||
// show the static error in an iframe to not lose any context / console data
|
||||
// with some basic styling to make the iframe full page
|
||||
delete document.body.style.height;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user