Compare commits

..

43 Commits

Author SHA1 Message Date
J. Ryan Stinnett
7fd26c3af9 Merge remote-tracking branch 'origin/develop' into jryans/p2p 2021-07-06 18:11:07 +01:00
J. Ryan Stinnett
9d1bed29b2 Use origin as the server to connect to 2021-07-05 14:51:49 +01:00
Neil Alexander
1e051365b1 Update dendrite.wasm 2021-06-25 14:59:46 +01:00
Neil Alexander
13251a4d6c Update dendrite.wasm 2021-06-25 14:52:09 +01:00
Neil Alexander
b28708fbf3 dendritejs-pinecone 2021-06-25 14:36:07 +01:00
Neil Alexander
46d659a936 Update sql.js (to SQLite 3.35.0) and wasm_exec.js (to Go 1.16.5) 2021-06-25 11:25:17 +01:00
Kegan Dougal
9e19d910c1 Bump to 0.2.0 and implement nuke db logic 2020-07-03 11:21:04 +01:00
Kegan Dougal
92fe2b8935 Only works on Go 1.14 now 2020-07-03 10:45:26 +01:00
Kegan Dougal
7e15090364 Wait for a room if it isn't there 2020-06-02 15:43:03 +01:00
Kegan Dougal
d83c475bb7 v0.1.1 2020-06-02 15:25:50 +01:00
Kegan Dougal
b4c7d54fc0 Add aliases automatically for pubilc rooms 2020-06-02 11:08:30 +01:00
Kegan Dougal
e10d5eb0be Pin to the commit so it picks it up 2020-05-29 18:59:26 +01:00
Kegan Dougal
ff6c4ac837 Use my fork so we can get IDBFS support 2020-05-29 18:26:47 +01:00
Kegan Dougal
bcba891df1 reskindex on react too 2020-05-29 17:48:15 +01:00
Kegan Dougal
708a7146d5 Maybe build p2p without relying on yarn start 2020-05-29 17:23:09 +01:00
Kegan Dougal
e4c67f39a6 Publish rooms where join_rule==public
- This currently doesn't add a room alias for the room, which should be fine
  provided the published room list returns data that includes servers in it.
2020-05-28 18:02:07 +01:00
Kegan Dougal
a5ba31e127 Automatically prompt to set display name then view the room directory on first login 2020-05-28 13:19:11 +01:00
Kegan Dougal
f6aceba566 Bump to 0.1.0 2020-05-22 14:28:48 +01:00
Kegan Dougal
35bcc152ea Write to indexeddb 2020-05-22 12:59:34 +01:00
Kegan Dougal
ec45bb7976 Write dendrite version to the database 2020-05-19 15:33:18 +01:00
Kegan Dougal
b0fb043c2b Add localforage support for persisting dendrite data 2020-05-19 11:54:08 +01:00
Kegan Dougal
4828869515 Restart dendrite when it exits 2020-05-18 18:26:30 +01:00
Kegan Dougal
671315c36e Use p2p branch of react-sdk 2020-04-17 11:28:59 +01:00
Kegan Dougal
9994c9ea65 Bugfixes for firefox 2020-04-02 18:20:34 +01:00
Kegan Dougal
9328519c29 Fix auto-register and constantly logging you out mess 2020-04-02 18:06:27 +01:00
Kegan Dougal
330aa285e6 Get login working on logout 2020-04-01 16:18:50 +01:00
Kegan Dougal
5c3f11a7c7 WIP: auto-registration 2020-03-31 18:05:34 +01:00
Kegan Dougal
cdd32590fe Make dendrite load again 2020-03-26 12:33:31 +00:00
Kegan Dougal
52641c5674 Merge tag 'v1.5.13' into matthew/p2p
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.13-rc.1...v1.5.13)
* Upgrade to JS SDK 5.1.1 and React SDK 2.2.3
2020-03-26 11:50:30 +00:00
Kegan Dougal
6f43a14c43 Remove go-sqlite-js and just use sql.js directly 2020-03-26 10:35:40 +00:00
Kegan Dougal
d80285d971 Spin up a new dendrite every time we get restarted 2020-03-16 12:57:15 +00:00
Kegan Dougal
3d74d336bf Use JSServer globals instead of fetchListener 2020-03-13 10:18:08 +00:00
Kegan Dougal
1f1f0f1264 Refresh service workers when new versions of sw.js come in
- Check once a minute
- When a new sw is here, skip waiting around for the old ones to die and claim the clients

NB: On Chrome, this results in a 2 minute wait with lost connectivity before logout. Refresh to
immediately use the new sw.

NBB: On Firefox, this automatically logs you out without needing to refresh.
2020-03-10 16:26:38 +00:00
Kegan Dougal
bf13ec2285 Claim clients to avoid the refresh 2020-03-10 14:46:18 +00:00
Kegan Dougal
4d1f969c4d Latest updates; set process stuff to make prometheus happy 2020-03-10 14:28:12 +00:00
Kegan Dougal
0935ccd737 Latest updates 2020-03-04 11:15:06 +00:00
Kegan Dougal
d2635bd282 Stuff from matrix meetup 2020-02-27 10:10:18 +00:00
Kegan Dougal
462fa91938 Better logging 2020-02-25 18:05:45 +00:00
Kegan Dougal
836236ea9b Rely on symlinking sqlite/libp2p 2020-02-25 16:46:41 +00:00
Kegan Dougal
3fcc3c8bfd Allow service workers to have the scope / which is needed for the interceptor 2020-02-25 15:27:31 +00:00
Matthew Hodgson
349d3e3d47 make it work 2020-01-23 20:16:08 -07:00
Matthew Hodgson
8a41f956f6 merge develop 2020-01-23 19:15:06 -07:00
Matthew Hodgson
80411d38f7 first cut at embedding dendrite into riot as a service-worker 2020-01-23 13:22:52 -07:00
77 changed files with 3824 additions and 3520 deletions

View File

@@ -1,14 +0,0 @@
# If you want to have proper hot-reload css experience, define one and set this on.
CSS_HOT_RELOAD=1
# Define which one theme you want to load for hot-reload purposes.
# To use a single theme just uncomment a line with the theme you want to use.
MATRIX_THEMES='light'
#MATRIX_THEMES='dark'
#MATRIX_THEMES='light-legacy'
#MATRIX_THEMES='dark-legacy'
#MATRIX_THEMES='light-custom'
#MATRIX_THEMES='dark-custom'
# You can load multiple themes at once, but switching between them may require full page reload.
# It will also multiple compliation times by the number of turned on themes.
# If you want to use multiple themes, define the combinations manually like below:
#MATRIX_THEMES='light,dark'

1
.github/CODEOWNERS vendored
View File

@@ -1 +0,0 @@
* @vector-im/element-web

48
.github/ISSUE_TEMPLATE.md vendored Normal file
View 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 -->

View File

@@ -1,59 +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: what-happened
attributes:
label: What happened?
placeholder: Tell us what went wrong
validations:
required: true
- type: textarea
id: expected-result
attributes:
label: What did you expect?
placeholder: Tell us what you expected to happen
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

View File

@@ -1,59 +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: what-happened
attributes:
label: What happened?
placeholder: Tell us what went wrong
validations:
required: true
- type: textarea
id: expected-result
attributes:
label: What did you expect?
placeholder: Tell us what you expected to happen
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

58
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View 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 -->

View File

@@ -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 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

View 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.

View File

@@ -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 -->

View File

@@ -1,14 +0,0 @@
on:
issues:
types: [labeled]
jobs:
move_issues:
name: Move issues to project board
runs-on: ubuntu-latest
steps:
- uses: konradpabjan/move-labeled-or-milestoned-issue@v2.0
with:
action-token: "${{ secrets.ELEMENT_BOT_TOKEN }}"
project-url: "https://github.com/orgs/vector-im/projects/14"
column-name: "📥 Inbox"
label-name: "X-Needs-Design"

View File

@@ -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 }}

View File

@@ -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@v0.8.1
with:
project: Issue triage
column: Incoming
repo-token: ${{ secrets.ELEMENT_BOT_TOKEN }}

View File

@@ -1,16 +0,0 @@
name: Move X-Needs-Info into Need info column in the Issue triage board
on:
issues:
types: [labeled]
jobs:
Move_Labeled_Issue_On_Project_Board:
runs-on: ubuntu-latest
steps:
- uses: konradpabjan/move-labeled-or-milestoned-issue@v2.0
with:
action-token: ${{ secrets.GITHUB_TOKEN }}
project-url: "https://github.com/vector-im/element-web/projects/27"
column-name: "Need info"
label-name: "X-Needs-Info"

3
.gitignore vendored
View File

@@ -19,6 +19,3 @@ electron/pub
/src/component-index.js
/.tmp
/webpack-stats.json
.vscode
.vscode/
.env

View File

@@ -1,6 +1,9 @@
{
"minify": true,
"enableClasses": false,
"classPrefix": "modernizr_",
"options": [
"setClasses"
],
"feature-detects": [
"test/css/animations",
"test/css/displaytable",

View File

@@ -1,280 +1,3 @@
Changes in [1.8.1](https://github.com/vector-im/element-desktop/releases/tag/v1.8.1) (2021-08-17)
=================================================================================================
## 🐛 Bug Fixes
* Fix multiple VoIP regressions ([matrix-org/matrix-js-sdk#1860](https://github.com/matrix-org/matrix-js-sdk/pull/1860)).
Changes in [1.8.0](https://github.com/vector-im/element-desktop/releases/tag/v1.8.0) (2021-08-16)
=================================================================================================
## ✨ Features
* Show how long a call was on call tiles ([\#6570](https://github.com/matrix-org/matrix-react-sdk/pull/6570)). Fixes #18405. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Add regional indicators to emoji picker ([\#6490](https://github.com/matrix-org/matrix-react-sdk/pull/6490)). Fixes #14963. Contributed by [robintown](https://github.com/robintown).
* Make call control buttons accessible to screen reader users ([\#6181](https://github.com/matrix-org/matrix-react-sdk/pull/6181)). Fixes #18358. Contributed by [pvagner](https://github.com/pvagner).
* Skip sending a thumbnail if it is not a sufficient saving over the original ([\#6559](https://github.com/matrix-org/matrix-react-sdk/pull/6559)). Fixes #17906.
* Increase PiP snapping speed ([\#6539](https://github.com/matrix-org/matrix-react-sdk/pull/6539)). Fixes #18371. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Improve and move the incoming call toast ([\#6470](https://github.com/matrix-org/matrix-react-sdk/pull/6470)). Fixes #17912. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Allow all of the URL schemes that Firefox allows ([\#6457](https://github.com/matrix-org/matrix-react-sdk/pull/6457)). Contributed by [aaronraimist](https://github.com/aaronraimist).
* Improve bubble layout colors ([\#6452](https://github.com/matrix-org/matrix-react-sdk/pull/6452)). Fixes #18081. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Spaces let users switch between Home and All Rooms behaviours ([\#6497](https://github.com/matrix-org/matrix-react-sdk/pull/6497)). Fixes #18093.
* Support for MSC2285 (hidden read receipts) ([\#6390](https://github.com/matrix-org/matrix-react-sdk/pull/6390)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Group pinned message events with MELS ([\#6349](https://github.com/matrix-org/matrix-react-sdk/pull/6349)). Fixes #17938. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Make version copiable ([\#6227](https://github.com/matrix-org/matrix-react-sdk/pull/6227)). Fixes #17603 and #18329. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Improve voice messages uploading state ([\#6530](https://github.com/matrix-org/matrix-react-sdk/pull/6530)). Fixes #18226 and #18224.
* Add surround with feature ([\#5510](https://github.com/matrix-org/matrix-react-sdk/pull/5510)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Improve call event tile wording ([\#6545](https://github.com/matrix-org/matrix-react-sdk/pull/6545)). Fixes #18376. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Show an avatar/a turned off microphone icon for muted users ([\#6486](https://github.com/matrix-org/matrix-react-sdk/pull/6486)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Prompt user to leave rooms/subspaces in a space when leaving space ([\#6424](https://github.com/matrix-org/matrix-react-sdk/pull/6424)). Fixes #18071.
* Add support for screen sharing in 1:1 calls ([\#5992](https://github.com/matrix-org/matrix-react-sdk/pull/5992)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
## 🐛 Bug Fixes
* Dismiss electron download toast when clicking Open ([\#18267](https://github.com/vector-im/element-web/pull/18267)). Fixes #18266.
* [Release] Fix glare related regressions ([\#6622](https://github.com/matrix-org/matrix-react-sdk/pull/6622)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* [Release] Fix PiP of held calls ([\#6612](https://github.com/matrix-org/matrix-react-sdk/pull/6612)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* [Release] Fix toast colors ([\#6607](https://github.com/matrix-org/matrix-react-sdk/pull/6607)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix [object Object] in Widget Permissions ([\#6560](https://github.com/matrix-org/matrix-react-sdk/pull/6560)). Fixes #18384. Contributed by [Palid](https://github.com/Palid).
* Fix right margin for events on IRC layout ([\#6542](https://github.com/matrix-org/matrix-react-sdk/pull/6542)). Fixes #18354.
* Mirror only usermedia feeds ([\#6512](https://github.com/matrix-org/matrix-react-sdk/pull/6512)). Fixes #5633. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix LogoutDialog warning + TypeScript migration ([\#6533](https://github.com/matrix-org/matrix-react-sdk/pull/6533)).
* Fix the wrong font being used in the room topic field ([\#6527](https://github.com/matrix-org/matrix-react-sdk/pull/6527)). Fixes #18339. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix inconsistent styling for links on hover ([\#6513](https://github.com/matrix-org/matrix-react-sdk/pull/6513)). Contributed by [janogarcia](https://github.com/janogarcia).
* Fix incorrect height for encoded placeholder images ([\#6514](https://github.com/matrix-org/matrix-react-sdk/pull/6514)). Contributed by [Palid](https://github.com/Palid).
* Fix call events layout for message bubble ([\#6465](https://github.com/matrix-org/matrix-react-sdk/pull/6465)). Fixes #18144.
* Improve subspaces and some utilities around room/space creation ([\#6458](https://github.com/matrix-org/matrix-react-sdk/pull/6458)). Fixes #18090 #18091 and #17256.
* Restore pointer cursor for SenderProfile in message bubbles ([\#6501](https://github.com/matrix-org/matrix-react-sdk/pull/6501)). Fixes #18249.
* Fix issues with the Call View ([\#6472](https://github.com/matrix-org/matrix-react-sdk/pull/6472)). Fixes #18221. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Align event list summary read receipts when using message bubbles ([\#6500](https://github.com/matrix-org/matrix-react-sdk/pull/6500)). Fixes #18143.
* Better positioning for unbubbled events in timeline ([\#6477](https://github.com/matrix-org/matrix-react-sdk/pull/6477)). Fixes #18132.
* Realign reactions row with messages in modern layout ([\#6491](https://github.com/matrix-org/matrix-react-sdk/pull/6491)). Fixes #18118. Contributed by [robintown](https://github.com/robintown).
* Fix CreateRoomDialog exploding when making public room outside of a space ([\#6492](https://github.com/matrix-org/matrix-react-sdk/pull/6492)). Fixes #18275.
* Fix call crashing because `element` was undefined ([\#6488](https://github.com/matrix-org/matrix-react-sdk/pull/6488)). Fixes #18270. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Upscale thumbnails to the container size ([\#6589](https://github.com/matrix-org/matrix-react-sdk/pull/6589)). Fixes #18307.
* Fix create room dialog in spaces no longer adding to the space ([\#6587](https://github.com/matrix-org/matrix-react-sdk/pull/6587)). Fixes #18465.
* Don't show a modal on call reject/user hangup ([\#6580](https://github.com/matrix-org/matrix-react-sdk/pull/6580)). Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fade Call View Buttons after `componentDidMount` ([\#6581](https://github.com/matrix-org/matrix-react-sdk/pull/6581)). Fixes #18439. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix missing expand button on codeblocks ([\#6565](https://github.com/matrix-org/matrix-react-sdk/pull/6565)). Fixes #18388. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* allow customizing the bubble layout colors ([\#6568](https://github.com/matrix-org/matrix-react-sdk/pull/6568)). Fixes #18408. Contributed by [benneti](https://github.com/benneti).
* Don't flash "Missed call" when accepting a call ([\#6567](https://github.com/matrix-org/matrix-react-sdk/pull/6567)). Fixes #18404. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix clicking whitespaces on replies ([\#6571](https://github.com/matrix-org/matrix-react-sdk/pull/6571)). Fixes #18327. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix composer not being disabled when sending voice messages ([\#6562](https://github.com/matrix-org/matrix-react-sdk/pull/6562)). Fixes #18413.
* Fix sizing issues of the screen picker ([\#6498](https://github.com/matrix-org/matrix-react-sdk/pull/6498)). Fixes #18281. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Stop voice messages that are playing when starting a recording ([\#6563](https://github.com/matrix-org/matrix-react-sdk/pull/6563)). Fixes #18410.
* Fix random box appearing when clicking room list headers. ([\#6561](https://github.com/matrix-org/matrix-react-sdk/pull/6561)). Fixes #18414.
* Null guard space inviter to prevent the app exploding ([\#6558](https://github.com/matrix-org/matrix-react-sdk/pull/6558)).
* Make the ringing sound mutable/disablable ([\#6534](https://github.com/matrix-org/matrix-react-sdk/pull/6534)). Fixes #15591. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix wrong cursor being used in PiP ([\#6551](https://github.com/matrix-org/matrix-react-sdk/pull/6551)). Fixes #18383. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Re-pin Jitsi if the widget already exists ([\#6226](https://github.com/matrix-org/matrix-react-sdk/pull/6226)). Fixes #17679. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix broken call notification regression ([\#6526](https://github.com/matrix-org/matrix-react-sdk/pull/6526)). Fixes #18335. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* createRoom, only send join rule event if we have a join rule to put in it ([\#6516](https://github.com/matrix-org/matrix-react-sdk/pull/6516)). Fixes #18301.
* Fix clicking pills inside replies ([\#6508](https://github.com/matrix-org/matrix-react-sdk/pull/6508)). Fixes #18283. Contributed by [SimonBrandner](https://github.com/SimonBrandner).
* Fix grecaptcha regression ([\#6503](https://github.com/matrix-org/matrix-react-sdk/pull/6503)). Fixes #18284. Contributed by [Palid](https://github.com/Palid).
* Fix compatibility with accounts where the security passphrase was created on a mobile device ([\#1819](https://github.com/matrix-org/matrix-js-sdk/pull/1819)).
Changes in [1.7.34](https://github.com/vector-im/element-desktop/releases/tag/v1.7.34) (2021-08-02)
===================================================================================================
## 🔒 SECURITY FIXES
* Sanitize untrusted variables from message previews before translation
Fixes vector-im/element-web#18314
## ✨ Features
* Fix editing of `<sub>` & `<sup`> & `<u>`
[\#6469](https://github.com/matrix-org/matrix-react-sdk/pull/6469)
Fixes #18211
* Zoom images in lightbox to where the cursor points
[\#6418](https://github.com/matrix-org/matrix-react-sdk/pull/6418)
Fixes #17870
* Avoid hitting the settings store from TextForEvent
[\#6205](https://github.com/matrix-org/matrix-react-sdk/pull/6205)
Fixes #17650
* Initial MSC3083 + MSC3244 support
[\#6212](https://github.com/matrix-org/matrix-react-sdk/pull/6212)
Fixes #17686 and #17661
* Navigate to the first room with notifications when clicked on space notification dot
[\#5974](https://github.com/matrix-org/matrix-react-sdk/pull/5974)
* Add matrix: to the list of permitted URL schemes
[\#6388](https://github.com/matrix-org/matrix-react-sdk/pull/6388)
* Add "Copy Link" to room context menu
[\#6374](https://github.com/matrix-org/matrix-react-sdk/pull/6374)
* 💭 Message bubble layout
[\#6291](https://github.com/matrix-org/matrix-react-sdk/pull/6291)
Fixes #4635, #17773 #16220 and #7687
* Play only one audio file at a time
[\#6417](https://github.com/matrix-org/matrix-react-sdk/pull/6417)
Fixes #17439
* Move download button for media to the action bar
[\#6386](https://github.com/matrix-org/matrix-react-sdk/pull/6386)
Fixes #17943
* Improved display of one-to-one call history with summary boxes for each call
[\#6121](https://github.com/matrix-org/matrix-react-sdk/pull/6121)
Fixes #16409
* Notification settings UI refresh
[\#6352](https://github.com/matrix-org/matrix-react-sdk/pull/6352)
Fixes #17782
* Fix EventIndex double handling events and erroring
[\#6385](https://github.com/matrix-org/matrix-react-sdk/pull/6385)
Fixes #18008
* Improve reply rendering
[\#3553](https://github.com/matrix-org/matrix-react-sdk/pull/3553)
Fixes vector-im/riot-web#9217, vector-im/riot-web#7633, vector-im/riot-web#7530, vector-im/riot-web#7169, vector-im/riot-web#7151, vector-im/riot-web#6692 vector-im/riot-web#6579 and #17440
* Improve performance of room name calculation
[\#1801](https://github.com/matrix-org/matrix-js-sdk/pull/1801)
## 🐛 Bug Fixes
* Fix browser history getting stuck looping back to the same room
[\#18053](https://github.com/vector-im/element-web/pull/18053)
* Fix space shortcuts on layouts with non-English keys in the places of numbers
[\#17780](https://github.com/vector-im/element-web/pull/17780)
Fixes #17776
* Fix CreateRoomDialog exploding when making public room outside of a space
[\#6493](https://github.com/matrix-org/matrix-react-sdk/pull/6493)
* Fix regression where registration would soft-crash on captcha
[\#6505](https://github.com/matrix-org/matrix-react-sdk/pull/6505)
Fixes #18284
* only send join rule event if we have a join rule to put in it
[\#6517](https://github.com/matrix-org/matrix-react-sdk/pull/6517)
* Improve the new download button's discoverability and interactions.
[\#6510](https://github.com/matrix-org/matrix-react-sdk/pull/6510)
* Fix voice recording UI looking broken while microphone permissions are being requested.
[\#6479](https://github.com/matrix-org/matrix-react-sdk/pull/6479)
Fixes #18223
* Match colors of room and user avatars in DMs
[\#6393](https://github.com/matrix-org/matrix-react-sdk/pull/6393)
Fixes #2449
* Fix onPaste handler to work with copying files from Finder
[\#5389](https://github.com/matrix-org/matrix-react-sdk/pull/5389)
Fixes #15536 and #16255
* Fix infinite pagination loop when offline
[\#6478](https://github.com/matrix-org/matrix-react-sdk/pull/6478)
Fixes #18242
* Fix blurhash rounded corners missing regression
[\#6467](https://github.com/matrix-org/matrix-react-sdk/pull/6467)
Fixes #18110
* Fix position of the space hierarchy spinner
[\#6462](https://github.com/matrix-org/matrix-react-sdk/pull/6462)
Fixes #18182
* Fix display of image messages that lack thumbnails
[\#6456](https://github.com/matrix-org/matrix-react-sdk/pull/6456)
Fixes #18175
* Fix crash with large audio files.
[\#6436](https://github.com/matrix-org/matrix-react-sdk/pull/6436)
Fixes #18149
* Make diff colors in codeblocks more pleasant
[\#6355](https://github.com/matrix-org/matrix-react-sdk/pull/6355)
Fixes #17939
* Show the correct audio file duration while loading the file.
[\#6435](https://github.com/matrix-org/matrix-react-sdk/pull/6435)
Fixes #18160
* Fix various timeline settings not applying immediately.
[\#6261](https://github.com/matrix-org/matrix-react-sdk/pull/6261)
Fixes #17748
* Fix issues with room list duplication
[\#6391](https://github.com/matrix-org/matrix-react-sdk/pull/6391)
Fixes #14508
* Fix grecaptcha throwing useless error sometimes
[\#6401](https://github.com/matrix-org/matrix-react-sdk/pull/6401)
Fixes #15142
* Update Emojibase and Twemoji and switch to IamCal (Slack-style) shortcodes
[\#6347](https://github.com/matrix-org/matrix-react-sdk/pull/6347)
Fixes #13857 and #13334
* Respect compound emojis in default avatar initial generation
[\#6397](https://github.com/matrix-org/matrix-react-sdk/pull/6397)
Fixes #18040
* Fix bug where the 'other homeserver' field in the server selection dialog would become briefly focus and then unfocus when clicked.
[\#6394](https://github.com/matrix-org/matrix-react-sdk/pull/6394)
Fixes #18031
* Standardise spelling and casing of homeserver, identity server, and integration manager
[\#6365](https://github.com/matrix-org/matrix-react-sdk/pull/6365)
* Fix widgets not receiving decrypted events when they have permission.
[\#6371](https://github.com/matrix-org/matrix-react-sdk/pull/6371)
Fixes #17615
* Prevent client hangs when calculating blurhashes
[\#6366](https://github.com/matrix-org/matrix-react-sdk/pull/6366)
Fixes #17945
* Exclude state events from widgets reading room events
[\#6378](https://github.com/matrix-org/matrix-react-sdk/pull/6378)
* Cache feature_spaces\* flags to improve performance
[\#6381](https://github.com/matrix-org/matrix-react-sdk/pull/6381)
Changes in [1.7.33](https://github.com/vector-im/element-web/releases/tag/v1.7.33) (2021-07-19)
===============================================================================================
[Full Changelog](https://github.com/vector-im/element-web/compare/v1.7.33-rc.1...v1.7.33)
* No changes from rc.1
Changes in [1.7.33-rc.1](https://github.com/vector-im/element-web/releases/tag/v1.7.33-rc.1) (2021-07-14)
=========================================================================================================
[Full Changelog](https://github.com/vector-im/element-web/compare/v1.7.32...v1.7.33-rc.1)
* Translations update from Weblate
[\#17991](https://github.com/vector-im/element-web/pull/17991)
* Revert "Don't run nginx as root in docker"
[\#17990](https://github.com/vector-im/element-web/pull/17990)
* Don't run nginx as root in docker
[\#17927](https://github.com/vector-im/element-web/pull/17927)
* Add VS Code to gitignore
[\#17982](https://github.com/vector-im/element-web/pull/17982)
* Remove canvas native dependencies from Dockerfile
[\#17973](https://github.com/vector-im/element-web/pull/17973)
* Remove node-canvas devDependency
[\#17967](https://github.com/vector-im/element-web/pull/17967)
* Add `reskindex` to development steps
[\#17926](https://github.com/vector-im/element-web/pull/17926)
* Update Modernizr and stop it from polluting classes on the html tag
[\#17921](https://github.com/vector-im/element-web/pull/17921)
* Convert a few files to TS
[\#17895](https://github.com/vector-im/element-web/pull/17895)
* Do not generate a lockfile when running in CI
[\#17902](https://github.com/vector-im/element-web/pull/17902)
* Fix lockfile to match listed dependencies
[\#17888](https://github.com/vector-im/element-web/pull/17888)
* Remove PostCSS calc() processing
[\#17856](https://github.com/vector-im/element-web/pull/17856)
* Make issue template styling more consistent and improve PR template
[\#17691](https://github.com/vector-im/element-web/pull/17691)
* Update jsrsasign to ^10.2.0 (Includes fix for CVE-2021-30246)
[\#17170](https://github.com/vector-im/element-web/pull/17170)
* Migrate to `eslint-plugin-matrix-org`
[\#17847](https://github.com/vector-im/element-web/pull/17847)
* Remove spurious overflow: auto on #matrixchat element
[\#17647](https://github.com/vector-im/element-web/pull/17647)
* Enhance security by disallowing CSP object-src rule
[\#17818](https://github.com/vector-im/element-web/pull/17818)
Changes in [1.7.32](https://github.com/vector-im/element-web/releases/tag/v1.7.32) (2021-07-05)
===============================================================================================
[Full Changelog](https://github.com/vector-im/element-web/compare/v1.7.32-rc.1...v1.7.32)
* No changes from rc.1
Changes in [1.7.32-rc.1](https://github.com/vector-im/element-web/releases/tag/v1.7.32-rc.1) (2021-06-29)
=========================================================================================================
[Full Changelog](https://github.com/vector-im/element-web/compare/v1.7.31...v1.7.32-rc.1)
* Update to react-sdk v3.25.0-rc.1 and js-sdk v12.0.1-rc.1
* Translations update from Weblate
[\#17832](https://github.com/vector-im/element-web/pull/17832)
* Fix canvas-filter-polyfill mock path
[\#17785](https://github.com/vector-im/element-web/pull/17785)
* Mock context-filter-polyfill for app-tests
[\#17774](https://github.com/vector-im/element-web/pull/17774)
* Add libera.chat to default room directory
[\#17772](https://github.com/vector-im/element-web/pull/17772)
* Improve typing of Event Index Manager / Seshat
[\#17704](https://github.com/vector-im/element-web/pull/17704)
* Bump dns-packet from 1.3.1 to 1.3.4
[\#17478](https://github.com/vector-im/element-web/pull/17478)
* Update matrix-widget-api to fix build issues
[\#17747](https://github.com/vector-im/element-web/pull/17747)
* Fix whitespace in Dockerfile
[\#17742](https://github.com/vector-im/element-web/pull/17742)
* Upgrade @types/react and @types/react-dom
[\#17723](https://github.com/vector-im/element-web/pull/17723)
* Spaces keyboard shortcuts first cut
[\#17457](https://github.com/vector-im/element-web/pull/17457)
* Labs: feature_report_to_moderators
[\#17694](https://github.com/vector-im/element-web/pull/17694)
Changes in [1.7.31](https://github.com/vector-im/element-web/releases/tag/v1.7.31) (2021-06-21)
===============================================================================================
[Full Changelog](https://github.com/vector-im/element-web/compare/v1.7.31-rc.1...v1.7.31)

View File

@@ -9,7 +9,10 @@ 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

View File

@@ -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]:
@@ -127,10 +127,10 @@ guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it alread
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
@@ -267,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 currently an opt-in development feature, and if you want to have
it working properly on your environment, create a `.env` file in this repository
with proper environmental, see `.env.example` for documentation and example.
Setting up a dev environment
============================
@@ -308,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.
@@ -328,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
@@ -404,14 +392,14 @@ Triaging issues
We strive to completely cover all applicable issues with these core labels:
1. __Type__ — Every issue is assigned a type:
* __[T-Defect](https://github.com/vector-im/element-web/labels/T-Defect):__
- __[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):__
- __[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):__
- __[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):__
- __[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:
@@ -426,26 +414,19 @@ We strive to completely cover all applicable issues with these core labels:
* __[S-Tolerable](https://github.com/vector-im/element-web/labels/S-Tolerable):__
Purely cosmetic or low / no impact to users
3. __Prevalence__ — All issues labeled `T-Defect` are also assigned a prevalence:
* __[P-High](https://github.com/vector-im/element-web/labels/P-High):__ Affects most users regularly or impacts most users' first experience (e.g. registration)
* __[P-Medium](https://github.com/vector-im/element-web/labels/P-Medium):__ Affects some users regularly or most users rarely
* __[P-Low](https://github.com/vector-im/element-web/labels/P-Low):__ Most users are unlikely to come across this or it is a corner case
This label may also be used for other types of issues.
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.
The Priority label is now deprecated. Defects will now be classed based on their severity and prevalence:
| Labels | Equivalent priority | What it means |
| ----------- | ----------- | ----------- |
| SCritical and PHigh<br />SCritical and PMedium<br />SMajor and PHigh | P1 | These issues should be worked on in this sprint or next sprint. If the backlog of issues is too long, we should reevaluate why the bugs are not caught earlier. |
| SCritical and PLow<br />SMajor and PMedium<br />SMinor and PHigh | P2 | When all the highest priority bugs are done, this is the next set to tackle. Ideally we should be fixing a few issues from this group every week. |
| SMajor and PLow<br />SMinor and PMedium<br />STolerable and PHigh | P3 | These issues are wishful thinking for now. We hope to get to them one day, but they are low priority. There are likely to be some good new contributor issues in here. |
| SMinor and PLow<br />STolerable&nbsp;and&nbsp;PMedium<br />SMinor and PLow | P4 and P5 | These issues are unlikely to be actively looked at by the webapp team, but may be picked up by community. |
### Other common labels
We have a handful of other labels which are added on an as-needed basis, and not expected to be exhaustive:

View File

@@ -136,9 +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
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

View File

@@ -125,11 +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)

View File

@@ -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

View File

@@ -1,6 +1,6 @@
{
"name": "element-web",
"version": "1.8.1",
"version": "1.7.31",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"repository": {
@@ -46,10 +46,9 @@
"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 --progress --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"
@@ -61,13 +60,15 @@
"highlight.js": "^10.5.0",
"jsrsasign": "^10.2.0",
"katex": "^0.12.0",
"matrix-js-sdk": "12.3.1",
"matrix-react-sdk": "3.28.1",
"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.15",
"prop-types": "^15.7.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": {
@@ -97,18 +98,17 @@
"@types/sanitize-html": "^2.3.1",
"@typescript-eslint/eslint-plugin": "^4.17.0",
"@typescript-eslint/parser": "^4.17.0",
"allchange": "^1.0.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-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#2306b3d4da4eba908b256014b979f1d3d43d2945",
"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",
@@ -126,9 +126,10 @@
"mini-css-extract-plugin": "^0.12.0",
"minimist": "^1.2.5",
"mkdirp": "^1.0.4",
"modernizr": "^3.11.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",
@@ -143,23 +144,17 @@
"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.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"
"webpack-dev-server": "^3.11.2"
},
"jest": {
"testEnvironment": "jest-environment-jsdom-sixteen",
"testMatch": [
"<rootDir>/test/**/*-test.[tj]s"
"<rootDir>/test/**/*-test.js"
],
"setupFilesAfterEnv": [
"<rootDir>/node_modules/matrix-react-sdk/test/setupTests.js"
@@ -176,10 +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",
"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).+$",

View File

@@ -1,4 +1 @@
signing_id: releases@riot.im
subprojects:
matrix-react-sdk:
includeByDefault: true

View File

@@ -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>

View File

@@ -76,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
@@ -90,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

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>
);

View File

@@ -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!"
}

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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",

View File

@@ -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!"
}

View File

@@ -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"
}

View File

@@ -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 %(brand)s rakendust nutiseadmes",
"Switch to space by number": "Vaata kogukonnakeskust tema numbri alusel"
"Use %(brand)s on mobile": "Kasuta %(brand)s rakendust nutiseadmes"
}

View File

@@ -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 روی گوشی"
}

View File

@@ -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"
}

View File

@@ -1,36 +0,0 @@
{
"Sign In": "Ynskriuwe",
"Failed to start": "Iepenjen 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 út sjen.",
"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> ynstallearre foar de beste ûnderfining.",
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s brûkt avansearre browser funksjes dy net stipe wurde troch de browser dy jo no brûke.",
"Powered by Matrix": "Fersoarge 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.": "Ûnferwachte flater by it klearmeitsjen fan de applikaasje. Sjoch yn'e konsole 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 &amp; collaboration powered by [matrix]": "Desintralisearre, fersifere chat &amp; gearwurking fersoarge troch [matrix]",
"You need to be using HTTPS to place a screen-sharing call.": "Jo moatte HTTPS brûke om te skiljen en jo skermynhâld te dielen.",
"%(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 ôf te rûnen",
"Download Completed": "Klear mei Delheljen",
"Unable to load config file: please refresh the page to try again.": "Kin konfiguraasje bestân net lade: ferfarskje de side en probearje it noch ris.",
"Open user settings": "Brûkersynstellingen iepenje",
"Dismiss": "Negearre",
"Explore rooms": "Keamers ûntdekke",
"Create Account": "Account Meitsje",
"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": "Ûnbekend apparaat",
"Open": "Iepenje",
"Invalid JSON": "Ûnjildiche JSON",
"Your Element is misconfigured": "Jo Element is net goed konfigurearre",
"Invalid configuration: no default server specified.": "Ûnjildiche konfiguraasje: gjin standert tsjinner selektearre.",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Ûnjildige konfiguraasje: kin allinnich kieze út default_server_config, default_server_name, as default_hs_url."
}

View File

@@ -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"
}

View File

@@ -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 &amp; collaboration powered by [matrix]": א'ט וכלי שיתוף פעולה מבוזר ומוצפן &amp; מופעל באמצעות [matrix]",
"Decentralised, encrypted chat &amp; collaboration powered by [matrix]": "צ'ט מוצפן &amp; ושת\"פ נעשה ע\"י ה [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": "כניסה",
"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,7 +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": "עבור אל 'Space' על פי מספרו"
"The message from the parser is: %(message)s": "ההודעה מהניתוח היא: %(message)s",
"Missing indexeddb worker script!": "סקריפט indexeddb worker חסר!"
}

View File

@@ -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"
}

View File

@@ -7,32 +7,5 @@
"Decentralised, encrypted chat &amp; collaboration powered by [matrix]": "Obrolan terenkripsi, terdesentralisasi &amp; 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!",
"Explore rooms": "Jelajahi ruang",
"Create Account": "Buat Akun",
"Switch to space by number": "Beralih ke ruang dengan nomor",
"Go to your browser to complete Sign In": "Buka browser Anda untuk menyelesaikan Masuk",
"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 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 bisa menjalankan %(brand)s",
"Unsupported browser": "Browser tidak didukung",
"Use %(brand)s on mobile": "Gunakan %(brand)s di ponsel",
"Powered by Matrix": "Didukung 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 sebelum/berikutnya",
"Open user settings": "Buka pengaturan pengguna",
"Open": "Buka",
"Download Completed": "Unduh 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 bisa muat file konfigurasi: mohon segarkan halaman 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": "Element Anda salah dikonfigurasi",
"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."
"Missing indexeddb worker script!": "Tidak ada script worker indexeddb!"
}

View File

@@ -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"
}

View File

@@ -1,38 +1,36 @@
{
"Dismiss": "Aizvērt/atcelt",
"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 &amp; collaboration powered by [matrix]": "Decentralizēta, šifrēta tērziņu &amp; 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 &amp; collaboration powered by [matrix]": "Decentralizēta, šifrēta čata &amp; kopdarbošanās sistēma uz [matrix] bāzes",
"Sign In": "Pierakstīties",
"Create Account": "Izveidot kontu",
"Explore rooms": "Pārlūkot telpas",
"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",
"Previous/next recently visited room or community": "Iepriekšējā/nākošā nesen apmeklētā telpa 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ā.",
"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 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)"
}

View File

@@ -6,8 +6,8 @@
"Welcome to Element": "Welkom bij Element",
"Decentralised, encrypted chat &amp; collaboration powered by [matrix]": "Gedecentraliseerd en versleuteld chatten &amp; samenwerken dankzij [matrix]",
"Sign In": "Inloggen",
"Create Account": "Registreren",
"Explore rooms": "Kamers ontdekken",
"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 per nummer"
"Use %(brand)s on mobile": "Gebruik %(brand)s op uw mobiel"
}

View File

@@ -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"
}

View File

@@ -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."
}

View File

@@ -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 на мобильном телефоне"
}

View File

@@ -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": "පිවිසෙන්න"
}

View File

@@ -33,6 +33,5 @@
"Your browser can't run %(brand)s": "Shfletuesi juaj smund 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 si 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"
}

View File

@@ -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"
}

View File

@@ -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"
}

View File

@@ -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 на мобільному"
}

View File

@@ -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_configdefault_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_configdefault_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"
}

View File

@@ -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"
}

View File

@@ -25,13 +25,21 @@ window.React = 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 { _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";
@@ -73,19 +81,189 @@ function onNewScreen(screen: string, replaceLast = false) {
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
@@ -135,7 +313,112 @@ function onTokenLoginCompleted() {
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();

279
src/vector/dendrite-sw.js Normal file
View 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

Binary file not shown.

View File

@@ -1,46 +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 will be autoremoved on production builds.
* The purpose of this code is that the webpack's `string-replace-loader`
* pretty much search for this string in this specific file and replaces it
* like a macro before any previous compilations, which allows us to inject
* some css requires statements that are specific to the themes we have turned
* on by ourselves. Without that very specific workaround, webpack would just
* import all the CSSes, which would make the whole thing useless, as on my
* machine with i9 the recompilation for all themes turned ou would take way
* over 30s, which is definitely too high for nice css reloads speed.
*
* 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);
}

View File

@@ -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,7 +58,12 @@
} %>
</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>

View File

@@ -25,14 +25,6 @@ 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 incredibly 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');
// 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';

View File

@@ -14,8 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { IndexedDBStoreWorker } from 'matrix-js-sdk/src/indexeddb-worker';
import { IndexedDBStoreWorker } from 'matrix-js-sdk/src/indexeddb-worker.js';
const remoteWorker = new IndexedDBStoreWorker(postMessage as InstanceType<typeof Worker>["postMessage"]);
const remoteWorker = new IndexedDBStoreWorker(postMessage);
global.onmessage = remoteWorker.onMessage;

View File

@@ -17,6 +17,7 @@ limitations under the License.
// We have to trick webpack into loading our CSS for us.
require("./index.scss");
import * as qs from 'querystring';
import { KJUR } from 'jsrsasign';
import {
IOpenIDCredentials,
@@ -51,16 +52,15 @@ let meetApi: any; // JitsiMeetExternalAPI
(async function() {
try {
// The widget's options are encoded into the fragment to avoid leaking info to the server.
const widgetQuery = new URLSearchParams(window.location.hash.substring(1));
// The widget spec on the other hand requires the widgetId and parentUrl to show up in the regular query string.
const realQuery = new URLSearchParams(window.location.search.substring(1));
// The widget's options are encoded into the fragment to avoid leaking info to the server. The widget
// spec on the other hand requires the widgetId and parentUrl to show up in the regular query string.
const widgetQuery = qs.parse(window.location.hash.substring(1));
const query = Object.assign({}, qs.parse(window.location.search.substring(1)), widgetQuery);
const qsParam = (name: string, optional = false): string => {
const vals = widgetQuery.has(name) ? widgetQuery.getAll(name) : realQuery.getAll(name);
if (!optional && vals.length !== 1) {
if (!optional && (!query[name] || typeof (query[name]) !== 'string')) {
throw new Error(`Expected singular ${name} in query string`);
}
return <string>vals[0];
return <string>query[name];
};
// If we have these params, expect a widget API to be available (ie. to be in an iframe

View File

@@ -326,7 +326,7 @@ body {
<a class="mx_Button" id="configure_element_button" href="#">Configure</a>
<p class="mx_Subtext mx_SubtextTop">Tap the button above, or manually enable <em>Use custom server</em> and enter:</p>
<p class="mx_Subtext">Homeserver: <em id="hs_url"></em></p>
<p class="mx_Subtext" id="custom_is">Identity server: <em id="is_url"></em></p>
<p class="mx_Subtext" id="custom_is">Identity Server: <em id="is_url"></em></p>
</div>
</div>
</div>

View File

@@ -1,21 +1,19 @@
import { getVectorConfig } from '../getconfig';
function onBackToElementClick(): void {
function onBackToElementClick() {
// Cookie should expire in 4 hours
document.cookie = 'element_mobile_redirect_to_guide=false;path=/;max-age=14400';
window.location.href = '../';
}
// NEVER pass user-controlled content to this function! Hardcoded strings only please.
function renderConfigError(message: string): void {
function renderConfigError(message) {
const contactMsg = "If this is unexpected, please contact your system administrator " +
"or technical support representative.";
message = `<h2>Error loading Element</h2><p>${message}</p><p>${contactMsg}</p>`;
const toHide = document.getElementsByClassName("mx_HomePage_container");
const errorContainers = document.getElementsByClassName(
"mx_HomePage_errorContainer",
) as HTMLCollectionOf<HTMLDialogElement>;
const errorContainers = document.getElementsByClassName("mx_HomePage_errorContainer");
for (const e of toHide) {
// We have to clear the content because .style.display='none'; doesn't work
@@ -28,7 +26,7 @@ function renderConfigError(message: string): void {
}
}
async function initPage(): Promise<void> {
async function initPage() {
document.getElementById('back_to_element_button').onclick = onBackToElementClick;
const config = await getVectorConfig('..');
@@ -94,7 +92,7 @@ async function initPage(): Promise<void> {
if (isUrl && !isUrl.endsWith('/')) isUrl += '/';
if (hsUrl !== 'https://matrix.org/') {
(document.getElementById('configure_element_button') as HTMLAnchorElement).href =
document.getElementById('configure_element_button').href =
"https://mobile.element.io?hs_url=" + encodeURIComponent(hsUrl) +
"&is_url=" + encodeURIComponent(isUrl);
document.getElementById('step1_heading').innerHTML= '1: Install the app';

File diff suppressed because one or more lines are too long

View File

@@ -22,7 +22,10 @@ import BaseEventIndexManager, {
ICrawlerCheckpoint,
IEventAndProfile,
IIndexStats,
IMatrixEvent,
IMatrixProfile,
ISearchArgs,
ISearchResult,
} from 'matrix-react-sdk/src/indexing/BaseEventIndexManager';
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
import { _t, _td } from 'matrix-react-sdk/src/languageHandler';
@@ -51,7 +54,6 @@ import { CheckUpdatesPayload } from "matrix-react-sdk/src/dispatcher/payloads/Ch
import ToastStore from "matrix-react-sdk/src/stores/ToastStore";
import GenericExpiringToast from "matrix-react-sdk/src/components/views/toasts/GenericExpiringToast";
import SettingsStore from 'matrix-react-sdk/src/settings/SettingsStore';
import { IMatrixProfile, IEventWithRoomId as IMatrixEvent, IResultRoomEvents } from "matrix-js-sdk/src/@types/search";
import VectorBasePlatform from './VectorBasePlatform';
@@ -110,10 +112,10 @@ class SeshatIndexManager extends BaseEventIndexManager {
constructor() {
super();
electron.on('seshatReply', this.onIpcReply);
electron.on('seshatReply', this._onIpcReply);
}
private async ipcCall(name: string, ...args: any[]): Promise<any> {
async _ipcCall(name: string, ...args: any[]): Promise<any> {
// TODO this should be moved into the preload.js file.
const ipcCallId = ++this.nextIpcCallId;
return new Promise((resolve, reject) => {
@@ -122,7 +124,7 @@ class SeshatIndexManager extends BaseEventIndexManager {
});
}
private onIpcReply = (ev: {}, payload: IPCPayload) => {
_onIpcReply = (ev: {}, payload: IPCPayload) => {
if (payload.id === undefined) {
console.warn("Ignoring IPC reply with no ID");
return;
@@ -143,35 +145,35 @@ class SeshatIndexManager extends BaseEventIndexManager {
};
async supportsEventIndexing(): Promise<boolean> {
return this.ipcCall('supportsEventIndexing');
return this._ipcCall('supportsEventIndexing');
}
async initEventIndex(userId: string, deviceId: string): Promise<void> {
return this.ipcCall('initEventIndex', userId, deviceId);
return this._ipcCall('initEventIndex', userId, deviceId);
}
async addEventToIndex(ev: IMatrixEvent, profile: IMatrixProfile): Promise<void> {
return this.ipcCall('addEventToIndex', ev, profile);
return this._ipcCall('addEventToIndex', ev, profile);
}
async deleteEvent(eventId: string): Promise<boolean> {
return this.ipcCall('deleteEvent', eventId);
return this._ipcCall('deleteEvent', eventId);
}
async isEventIndexEmpty(): Promise<boolean> {
return this.ipcCall('isEventIndexEmpty');
return this._ipcCall('isEventIndexEmpty');
}
async isRoomIndexed(roomId: string): Promise<boolean> {
return this.ipcCall('isRoomIndexed', roomId);
return this._ipcCall('isRoomIndexed', roomId);
}
async commitLiveEvents(): Promise<void> {
return this.ipcCall('commitLiveEvents');
return this._ipcCall('commitLiveEvents');
}
async searchEventIndex(searchConfig: ISearchArgs): Promise<IResultRoomEvents> {
return this.ipcCall('searchEventIndex', searchConfig);
async searchEventIndex(searchConfig: ISearchArgs): Promise<ISearchResult> {
return this._ipcCall('searchEventIndex', searchConfig);
}
async addHistoricEvents(
@@ -179,43 +181,43 @@ class SeshatIndexManager extends BaseEventIndexManager {
checkpoint: ICrawlerCheckpoint | null,
oldCheckpoint: ICrawlerCheckpoint | null,
): Promise<boolean> {
return this.ipcCall('addHistoricEvents', events, checkpoint, oldCheckpoint);
return this._ipcCall('addHistoricEvents', events, checkpoint, oldCheckpoint);
}
async addCrawlerCheckpoint(checkpoint: ICrawlerCheckpoint): Promise<void> {
return this.ipcCall('addCrawlerCheckpoint', checkpoint);
return this._ipcCall('addCrawlerCheckpoint', checkpoint);
}
async removeCrawlerCheckpoint(checkpoint: ICrawlerCheckpoint): Promise<void> {
return this.ipcCall('removeCrawlerCheckpoint', checkpoint);
return this._ipcCall('removeCrawlerCheckpoint', checkpoint);
}
async loadFileEvents(args): Promise<IEventAndProfile[]> {
return this.ipcCall('loadFileEvents', args);
return this._ipcCall('loadFileEvents', args);
}
async loadCheckpoints(): Promise<ICrawlerCheckpoint[]> {
return this.ipcCall('loadCheckpoints');
return this._ipcCall('loadCheckpoints');
}
async closeEventIndex(): Promise<void> {
return this.ipcCall('closeEventIndex');
return this._ipcCall('closeEventIndex');
}
async getStats(): Promise<IIndexStats> {
return this.ipcCall('getStats');
return this._ipcCall('getStats');
}
async getUserVersion(): Promise<number> {
return this.ipcCall('getUserVersion');
return this._ipcCall('getUserVersion');
}
async setUserVersion(version: number): Promise<void> {
return this.ipcCall('setUserVersion', version);
return this._ipcCall('setUserVersion', version);
}
async deleteEventIndex(): Promise<void> {
return this.ipcCall('deleteEventIndex');
return this._ipcCall('deleteEventIndex');
}
}
@@ -249,7 +251,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
rageshake.flush();
});
electron.on('ipcReply', this.onIpcReply);
electron.on('ipcReply', this._onIpcReply);
electron.on('update-downloaded', this.onUpdateDownloaded);
electron.on('preferences', () => {
@@ -257,15 +259,12 @@ export default class ElectronPlatform extends VectorBasePlatform {
});
electron.on('userDownloadCompleted', (ev, { path, name }) => {
const key = `DOWNLOAD_TOAST_${path}`;
const onAccept = () => {
electron.send('userDownloadOpen', { path });
ToastStore.sharedInstance().dismissToast(key);
};
ToastStore.sharedInstance().addOrReplaceToast({
key,
key: `DOWNLOAD_TOAST_${path}`,
title: _t("Download Completed"),
props: {
description: name,
@@ -320,11 +319,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
});
}
this.ipcCall("startSSOFlow", this.ssoID);
this._ipcCall("startSSOFlow", this.ssoID);
}
async getConfig(): Promise<{}> {
return this.ipcCall('getConfig');
return this._ipcCall('getConfig');
}
onUpdateDownloaded = async (ev, { releaseNotes, releaseName }) => {
@@ -391,7 +390,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
room_id: room.roomId,
});
window.focus();
this.ipcCall('focusWindow');
this._ipcCall('focusWindow');
};
return notification;
@@ -402,7 +401,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
async getAppVersion(): Promise<string> {
return this.ipcCall('getAppVersion');
return this._ipcCall('getAppVersion');
}
supportsAutoLaunch(): boolean {
@@ -410,11 +409,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
async getAutoLaunchEnabled(): Promise<boolean> {
return this.ipcCall('getAutoLaunchEnabled');
return this._ipcCall('getAutoLaunchEnabled');
}
async setAutoLaunchEnabled(enabled: boolean): Promise<void> {
return this.ipcCall('setAutoLaunchEnabled', enabled);
return this._ipcCall('setAutoLaunchEnabled', enabled);
}
supportsWarnBeforeExit(): boolean {
@@ -422,11 +421,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
async shouldWarnBeforeExit(): Promise<boolean> {
return this.ipcCall('shouldWarnBeforeExit');
return this._ipcCall('shouldWarnBeforeExit');
}
async setWarnBeforeExit(enabled: boolean): Promise<void> {
return this.ipcCall('setWarnBeforeExit', enabled);
return this._ipcCall('setWarnBeforeExit', enabled);
}
supportsAutoHideMenuBar(): boolean {
@@ -435,11 +434,11 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
async getAutoHideMenuBarEnabled(): Promise<boolean> {
return this.ipcCall('getAutoHideMenuBarEnabled');
return this._ipcCall('getAutoHideMenuBarEnabled');
}
async setAutoHideMenuBarEnabled(enabled: boolean): Promise<void> {
return this.ipcCall('setAutoHideMenuBarEnabled', enabled);
return this._ipcCall('setAutoHideMenuBarEnabled', enabled);
}
supportsMinimizeToTray(): boolean {
@@ -448,15 +447,15 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
async getMinimizeToTrayEnabled(): Promise<boolean> {
return this.ipcCall('getMinimizeToTrayEnabled');
return this._ipcCall('getMinimizeToTrayEnabled');
}
async setMinimizeToTrayEnabled(enabled: boolean): Promise<void> {
return this.ipcCall('setMinimizeToTrayEnabled', enabled);
return this._ipcCall('setMinimizeToTrayEnabled', enabled);
}
async canSelfUpdate(): Promise<boolean> {
const feedUrl = await this.ipcCall('getUpdateFeedUrl');
const feedUrl = await this._ipcCall('getUpdateFeedUrl');
return Boolean(feedUrl);
}
@@ -495,7 +494,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
window.location.reload(false);
}
private async ipcCall(name: string, ...args: any[]): Promise<any> {
async _ipcCall(name: string, ...args: any[]): Promise<any> {
const ipcCallId = ++this.nextIpcCallId;
return new Promise((resolve, reject) => {
this.pendingIpcCalls[ipcCallId] = { resolve, reject };
@@ -504,7 +503,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
});
}
private onIpcReply = (ev, payload) => {
_onIpcReply = (ev, payload) => {
if (payload.id === undefined) {
console.warn("Ignoring IPC reply with no ID");
return;
@@ -529,22 +528,22 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
async setLanguage(preferredLangs: string[]) {
return this.ipcCall('setLanguage', preferredLangs);
return this._ipcCall('setLanguage', preferredLangs);
}
setSpellCheckLanguages(preferredLangs: string[]) {
this.ipcCall('setSpellCheckLanguages', preferredLangs).catch(error => {
this._ipcCall('setSpellCheckLanguages', preferredLangs).catch(error => {
console.log("Failed to send setSpellCheckLanguages IPC to Electron");
console.error(error);
});
}
async getSpellCheckLanguages(): Promise<string[]> {
return this.ipcCall('getSpellCheckLanguages');
return this._ipcCall('getSpellCheckLanguages');
}
async getAvailableSpellCheckLanguages(): Promise<string[]> {
return this.ipcCall('getAvailableSpellCheckLanguages');
return this._ipcCall('getAvailableSpellCheckLanguages');
}
getSSOCallbackUrl(fragmentAfterLogin: string): URL {
@@ -564,7 +563,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
}
private navigateForwardBack(back: boolean) {
this.ipcCall(back ? "navigateBack" : "navigateForward");
this._ipcCall(back ? "navigateBack" : "navigateForward");
}
private navigateToSpace(num: number) {
dis.dispatch<SwitchSpacePayload>({
@@ -592,18 +591,22 @@ export default class ElectronPlatform extends VectorBasePlatform {
handled = true;
}
break;
}
if (!handled &&
// ideally we would use SpaceStore.spacesEnabled here but importing SpaceStore in this platform
// breaks skinning as the platform is instantiated prior to the skin being loaded
SettingsStore.getValue("feature_spaces") &&
ev.code.startsWith("Digit") &&
isOnlyCtrlOrCmdKeyEvent(ev)
) {
const spaceNumber = ev.code.slice(5); // Cut off the first 5 characters - "Digit"
this.navigateToSpace(parseInt(spaceNumber, 10));
handled = true;
case "1":
case "2":
case "3":
case "4":
case "5":
case "6":
case "7":
case "8":
case "9":
case "0":
if (SettingsStore.getValue("feature_spaces") && isOnlyCtrlOrCmdKeyEvent(ev)) {
this.navigateToSpace(parseInt(ev.key, 10));
handled = true;
}
break;
}
return handled;
@@ -611,7 +614,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
async getPickleKey(userId: string, deviceId: string): Promise<string | null> {
try {
return await this.ipcCall('getPickleKey', userId, deviceId);
return await this._ipcCall('getPickleKey', userId, deviceId);
} catch (e) {
// if we can't connect to the password storage, assume there's no
// pickle key
@@ -621,7 +624,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
async createPickleKey(userId: string, deviceId: string): Promise<string | null> {
try {
return await this.ipcCall('createPickleKey', userId, deviceId);
return await this._ipcCall('createPickleKey', userId, deviceId);
} catch (e) {
// if we can't connect to the password storage, assume there's no
// pickle key
@@ -631,7 +634,7 @@ export default class ElectronPlatform extends VectorBasePlatform {
async destroyPickleKey(userId: string, deviceId: string): Promise<void> {
try {
await this.ipcCall('destroyPickleKey', userId, deviceId);
await this._ipcCall('destroyPickleKey', userId, deviceId);
} catch (e) {}
}
}

View File

@@ -49,7 +49,7 @@ export default abstract class VectorBasePlatform extends BasePlatform {
return this._favicon = new Favicon();
}
private updateFavicon() {
_updateFavicon() {
let bgColor = "#d00";
let notif: string | number = this.notificationCount;
@@ -64,13 +64,13 @@ export default abstract class VectorBasePlatform extends BasePlatform {
setNotificationCount(count: number) {
if (this.notificationCount === count) return;
super.setNotificationCount(count);
this.updateFavicon();
this._updateFavicon();
}
setErrorStatus(errorDidOccur: boolean) {
if (this.errorDidOccur === errorDidOccur) return;
super.setErrorStatus(errorDidOccur);
this.updateFavicon();
this._updateFavicon();
}
/**

View File

@@ -37,7 +37,7 @@ export default class WebPlatform extends VectorBasePlatform {
super();
// Register service worker if available on this platform
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('sw.js');
// navigator.serviceWorker.register('sw.js');
}
}
@@ -100,7 +100,7 @@ export default class WebPlatform extends VectorBasePlatform {
return notification;
}
private getVersion(): Promise<string> {
_getVersion(): Promise<string> {
// We add a cachebuster to the request to make sure that we know about
// the most recent version on the origin server. That might not
// actually be the version we'd get on a reload (particularly in the
@@ -132,7 +132,7 @@ export default class WebPlatform extends VectorBasePlatform {
if (this.runningVersion !== null) {
return Promise.resolve(this.runningVersion);
}
return this.getVersion();
return this._getVersion();
}
startUpdater() {
@@ -145,7 +145,7 @@ export default class WebPlatform extends VectorBasePlatform {
}
pollForUpdate = () => {
return this.getVersion().then((ver) => {
return this._getVersion().then((ver) => {
if (this.runningVersion === null) {
this.runningVersion = ver;
} else if (this.runningVersion !== ver) {

22
src/vector/sqlitejs.js Normal file
View File

@@ -0,0 +1,22 @@
// Copyright 2020 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.
import initSqlJs from 'sql.js'
export function init(config) {
return initSqlJs(config).then(SQL => {
global._go_sqlite = SQL;
console.log("Loaded sqlite")
})
}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { QueryDict, decodeParams } from "matrix-js-sdk/src/utils";
import * as qs from 'querystring';
// We want to support some name / value pairs in the fragment
// so we're re-using query string like format
@@ -32,15 +32,15 @@ export function parseQsFromFragment(location: Location) {
const result = {
location: decodeURIComponent(hashparts[0]),
params: <QueryDict>{},
params: <qs.ParsedUrlQuery>{},
};
if (hashparts.length > 1) {
result.params = decodeParams(hashparts[1]);
result.params = qs.parse(hashparts[1]);
}
return result;
}
export function parseQs(location: Location): QueryDict {
return decodeParams(location.search.substring(1));
export function parseQs(location: Location) {
return qs.parse(location.search.substring(1));
}

626
src/vector/wasm_exec.js Normal file
View File

@@ -0,0 +1,626 @@
// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
(() => {
// Map multiple JavaScript environments to a single common API,
// preferring web standards over Node.js API.
//
// Environments considered:
// - Browsers
// - Node.js
// - Electron
// - Parcel
// - Webpack
if (typeof global !== "undefined") {
// global already exists
} else if (typeof window !== "undefined") {
window.global = window;
} else if (typeof self !== "undefined") {
self.global = self;
} else {
throw new Error("cannot export Go (neither global, window nor self is defined)");
}
if (!global.require && typeof require !== "undefined") {
global.require = require;
}
if (!global.fs && global.require) {
const fs = require("fs");
if (typeof fs === "object" && fs !== null && Object.keys(fs).length !== 0) {
global.fs = fs;
}
}
const enosys = () => {
const err = new Error("not implemented");
err.code = "ENOSYS";
return err;
};
if (!global.fs) {
let outputBuf = "";
global.fs = {
constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1 }, // unused
writeSync(fd, buf) {
outputBuf += decoder.decode(buf);
const nl = outputBuf.lastIndexOf("\n");
if (nl != -1) {
console.log(outputBuf.substr(0, nl));
outputBuf = outputBuf.substr(nl + 1);
}
return buf.length;
},
write(fd, buf, offset, length, position, callback) {
if (offset !== 0 || length !== buf.length || position !== null) {
callback(enosys());
return;
}
const n = this.writeSync(fd, buf);
callback(null, n);
},
chmod(path, mode, callback) { callback(enosys()); },
chown(path, uid, gid, callback) { callback(enosys()); },
close(fd, callback) { callback(enosys()); },
fchmod(fd, mode, callback) { callback(enosys()); },
fchown(fd, uid, gid, callback) { callback(enosys()); },
fstat(fd, callback) { callback(enosys()); },
fsync(fd, callback) { callback(null); },
ftruncate(fd, length, callback) { callback(enosys()); },
lchown(path, uid, gid, callback) { callback(enosys()); },
link(path, link, callback) { callback(enosys()); },
lstat(path, callback) { callback(enosys()); },
mkdir(path, perm, callback) { callback(enosys()); },
open(path, flags, mode, callback) { callback(enosys()); },
read(fd, buffer, offset, length, position, callback) { callback(enosys()); },
readdir(path, callback) { callback(enosys()); },
readlink(path, callback) { callback(enosys()); },
rename(from, to, callback) { callback(enosys()); },
rmdir(path, callback) { callback(enosys()); },
stat(path, callback) { callback(enosys()); },
symlink(path, link, callback) { callback(enosys()); },
truncate(path, length, callback) { callback(enosys()); },
unlink(path, callback) { callback(enosys()); },
utimes(path, atime, mtime, callback) { callback(enosys()); },
};
}
if (!global.process) {
global.process = {
getuid() { return -1; },
getgid() { return -1; },
geteuid() { return -1; },
getegid() { return -1; },
getgroups() { throw enosys(); },
pid: -1,
ppid: -1,
umask() { throw enosys(); },
cwd() { throw enosys(); },
chdir() { throw enosys(); },
}
}
if (!global.crypto && global.require) {
const nodeCrypto = require("crypto");
global.crypto = {
getRandomValues(b) {
nodeCrypto.randomFillSync(b);
},
};
}
if (!global.crypto) {
throw new Error("global.crypto is not available, polyfill required (getRandomValues only)");
}
if (!global.performance) {
global.performance = {
now() {
const [sec, nsec] = process.hrtime();
return sec * 1000 + nsec / 1000000;
},
};
}
if (!global.TextEncoder && global.require) {
global.TextEncoder = require("util").TextEncoder;
}
if (!global.TextEncoder) {
throw new Error("global.TextEncoder is not available, polyfill required");
}
if (!global.TextDecoder && global.require) {
global.TextDecoder = require("util").TextDecoder;
}
if (!global.TextDecoder) {
throw new Error("global.TextDecoder is not available, polyfill required");
}
// End of polyfills for common API.
const encoder = new TextEncoder("utf-8");
const decoder = new TextDecoder("utf-8");
global.Go = class {
constructor() {
this.argv = ["js"];
this.env = {};
this.exit = (code) => {
if (code !== 0) {
console.warn("exit code:", code);
}
};
this._exitPromise = new Promise((resolve) => {
this._resolveExitPromise = resolve;
});
this._pendingEvent = null;
this._scheduledTimeouts = new Map();
this._nextCallbackTimeoutID = 1;
const setInt64 = (addr, v) => {
this.mem.setUint32(addr + 0, v, true);
this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true);
}
const getInt64 = (addr) => {
const low = this.mem.getUint32(addr + 0, true);
const high = this.mem.getInt32(addr + 4, true);
return low + high * 4294967296;
}
const loadValue = (addr) => {
const f = this.mem.getFloat64(addr, true);
if (f === 0) {
return undefined;
}
if (!isNaN(f)) {
return f;
}
const id = this.mem.getUint32(addr, true);
return this._values[id];
}
const storeValue = (addr, v) => {
const nanHead = 0x7FF80000;
if (typeof v === "number" && v !== 0) {
if (isNaN(v)) {
this.mem.setUint32(addr + 4, nanHead, true);
this.mem.setUint32(addr, 0, true);
return;
}
this.mem.setFloat64(addr, v, true);
return;
}
if (v === undefined) {
this.mem.setFloat64(addr, 0, true);
return;
}
let id = this._ids.get(v);
if (id === undefined) {
id = this._idPool.pop();
if (id === undefined) {
id = this._values.length;
}
this._values[id] = v;
this._goRefCounts[id] = 0;
this._ids.set(v, id);
}
this._goRefCounts[id]++;
let typeFlag = 0;
switch (typeof v) {
case "object":
if (v !== null) {
typeFlag = 1;
}
break;
case "string":
typeFlag = 2;
break;
case "symbol":
typeFlag = 3;
break;
case "function":
typeFlag = 4;
break;
}
this.mem.setUint32(addr + 4, nanHead | typeFlag, true);
this.mem.setUint32(addr, id, true);
}
const loadSlice = (addr) => {
const array = getInt64(addr + 0);
const len = getInt64(addr + 8);
return new Uint8Array(this._inst.exports.mem.buffer, array, len);
}
const loadSliceOfValues = (addr) => {
const array = getInt64(addr + 0);
const len = getInt64(addr + 8);
const a = new Array(len);
for (let i = 0; i < len; i++) {
a[i] = loadValue(array + i * 8);
}
return a;
}
const loadString = (addr) => {
const saddr = getInt64(addr + 0);
const len = getInt64(addr + 8);
return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len));
}
const timeOrigin = Date.now() - performance.now();
this.importObject = {
go: {
// Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters)
// may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported
// function. A goroutine can switch to a new stack if the current stack is too small (see morestack function).
// This changes the SP, thus we have to update the SP used by the imported function.
// func wasmExit(code int32)
"runtime.wasmExit": (sp) => {
sp >>>= 0;
const code = this.mem.getInt32(sp + 8, true);
this.exited = true;
delete this._inst;
delete this._values;
delete this._goRefCounts;
delete this._ids;
delete this._idPool;
this.exit(code);
},
// func wasmWrite(fd uintptr, p unsafe.Pointer, n int32)
"runtime.wasmWrite": (sp) => {
sp >>>= 0;
const fd = getInt64(sp + 8);
const p = getInt64(sp + 16);
const n = this.mem.getInt32(sp + 24, true);
fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n));
},
// func resetMemoryDataView()
"runtime.resetMemoryDataView": (sp) => {
sp >>>= 0;
this.mem = new DataView(this._inst.exports.mem.buffer);
},
// func nanotime1() int64
"runtime.nanotime1": (sp) => {
sp >>>= 0;
setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000);
},
// func walltime1() (sec int64, nsec int32)
"runtime.walltime1": (sp) => {
sp >>>= 0;
const msec = (new Date).getTime();
setInt64(sp + 8, msec / 1000);
this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true);
},
// func scheduleTimeoutEvent(delay int64) int32
"runtime.scheduleTimeoutEvent": (sp) => {
sp >>>= 0;
const id = this._nextCallbackTimeoutID;
this._nextCallbackTimeoutID++;
this._scheduledTimeouts.set(id, setTimeout(
() => {
this._resume();
while (this._scheduledTimeouts.has(id)) {
// for some reason Go failed to register the timeout event, log and try again
// (temporary workaround for https://github.com/golang/go/issues/28975)
console.warn("scheduleTimeoutEvent: missed timeout event");
this._resume();
}
},
getInt64(sp + 8) + 1, // setTimeout has been seen to fire up to 1 millisecond early
));
this.mem.setInt32(sp + 16, id, true);
},
// func clearTimeoutEvent(id int32)
"runtime.clearTimeoutEvent": (sp) => {
sp >>>= 0;
const id = this.mem.getInt32(sp + 8, true);
clearTimeout(this._scheduledTimeouts.get(id));
this._scheduledTimeouts.delete(id);
},
// func getRandomData(r []byte)
"runtime.getRandomData": (sp) => {
sp >>>= 0;
crypto.getRandomValues(loadSlice(sp + 8));
},
// func finalizeRef(v ref)
"syscall/js.finalizeRef": (sp) => {
sp >>>= 0;
const id = this.mem.getUint32(sp + 8, true);
this._goRefCounts[id]--;
if (this._goRefCounts[id] === 0) {
const v = this._values[id];
this._values[id] = null;
this._ids.delete(v);
this._idPool.push(id);
}
},
// func stringVal(value string) ref
"syscall/js.stringVal": (sp) => {
sp >>>= 0;
storeValue(sp + 24, loadString(sp + 8));
},
// func valueGet(v ref, p string) ref
"syscall/js.valueGet": (sp) => {
sp >>>= 0;
const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16));
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 32, result);
},
// func valueSet(v ref, p string, x ref)
"syscall/js.valueSet": (sp) => {
sp >>>= 0;
Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32));
},
// func valueDelete(v ref, p string)
"syscall/js.valueDelete": (sp) => {
sp >>>= 0;
Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16));
},
// func valueIndex(v ref, i int) ref
"syscall/js.valueIndex": (sp) => {
sp >>>= 0;
storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16)));
},
// valueSetIndex(v ref, i int, x ref)
"syscall/js.valueSetIndex": (sp) => {
sp >>>= 0;
Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24));
},
// func valueCall(v ref, m string, args []ref) (ref, bool)
"syscall/js.valueCall": (sp) => {
sp >>>= 0;
try {
const v = loadValue(sp + 8);
const m = Reflect.get(v, loadString(sp + 16));
const args = loadSliceOfValues(sp + 32);
const result = Reflect.apply(m, v, args);
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 56, result);
this.mem.setUint8(sp + 64, 1);
} catch (err) {
storeValue(sp + 56, err);
this.mem.setUint8(sp + 64, 0);
}
},
// func valueInvoke(v ref, args []ref) (ref, bool)
"syscall/js.valueInvoke": (sp) => {
sp >>>= 0;
try {
const v = loadValue(sp + 8);
const args = loadSliceOfValues(sp + 16);
const result = Reflect.apply(v, undefined, args);
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 40, result);
this.mem.setUint8(sp + 48, 1);
} catch (err) {
storeValue(sp + 40, err);
this.mem.setUint8(sp + 48, 0);
}
},
// func valueNew(v ref, args []ref) (ref, bool)
"syscall/js.valueNew": (sp) => {
sp >>>= 0;
try {
const v = loadValue(sp + 8);
const args = loadSliceOfValues(sp + 16);
const result = Reflect.construct(v, args);
sp = this._inst.exports.getsp() >>> 0; // see comment above
storeValue(sp + 40, result);
this.mem.setUint8(sp + 48, 1);
} catch (err) {
storeValue(sp + 40, err);
this.mem.setUint8(sp + 48, 0);
}
},
// func valueLength(v ref) int
"syscall/js.valueLength": (sp) => {
sp >>>= 0;
setInt64(sp + 16, parseInt(loadValue(sp + 8).length));
},
// valuePrepareString(v ref) (ref, int)
"syscall/js.valuePrepareString": (sp) => {
sp >>>= 0;
const str = encoder.encode(String(loadValue(sp + 8)));
storeValue(sp + 16, str);
setInt64(sp + 24, str.length);
},
// valueLoadString(v ref, b []byte)
"syscall/js.valueLoadString": (sp) => {
sp >>>= 0;
const str = loadValue(sp + 8);
loadSlice(sp + 16).set(str);
},
// func valueInstanceOf(v ref, t ref) bool
"syscall/js.valueInstanceOf": (sp) => {
sp >>>= 0;
this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0);
},
// func copyBytesToGo(dst []byte, src ref) (int, bool)
"syscall/js.copyBytesToGo": (sp) => {
sp >>>= 0;
const dst = loadSlice(sp + 8);
const src = loadValue(sp + 32);
if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) {
this.mem.setUint8(sp + 48, 0);
return;
}
const toCopy = src.subarray(0, dst.length);
dst.set(toCopy);
setInt64(sp + 40, toCopy.length);
this.mem.setUint8(sp + 48, 1);
},
// func copyBytesToJS(dst ref, src []byte) (int, bool)
"syscall/js.copyBytesToJS": (sp) => {
sp >>>= 0;
const dst = loadValue(sp + 8);
const src = loadSlice(sp + 16);
if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) {
this.mem.setUint8(sp + 48, 0);
return;
}
const toCopy = src.subarray(0, dst.length);
dst.set(toCopy);
setInt64(sp + 40, toCopy.length);
this.mem.setUint8(sp + 48, 1);
},
"debug": (value) => {
console.log(value);
},
}
};
}
async run(instance) {
if (!(instance instanceof WebAssembly.Instance)) {
throw new Error("Go.run: WebAssembly.Instance expected");
}
this._inst = instance;
this.mem = new DataView(this._inst.exports.mem.buffer);
this._values = [ // JS values that Go currently has references to, indexed by reference id
NaN,
0,
null,
true,
false,
global,
this,
];
this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id
this._ids = new Map([ // mapping from JS values to reference ids
[0, 1],
[null, 2],
[true, 3],
[false, 4],
[global, 5],
[this, 6],
]);
this._idPool = []; // unused ids that have been garbage collected
this.exited = false; // whether the Go program has exited
// Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory.
let offset = 4096;
const strPtr = (str) => {
const ptr = offset;
const bytes = encoder.encode(str + "\0");
new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes);
offset += bytes.length;
if (offset % 8 !== 0) {
offset += 8 - (offset % 8);
}
return ptr;
};
const argc = this.argv.length;
const argvPtrs = [];
this.argv.forEach((arg) => {
argvPtrs.push(strPtr(arg));
});
argvPtrs.push(0);
const keys = Object.keys(this.env).sort();
keys.forEach((key) => {
argvPtrs.push(strPtr(`${key}=${this.env[key]}`));
});
argvPtrs.push(0);
const argv = offset;
argvPtrs.forEach((ptr) => {
this.mem.setUint32(offset, ptr, true);
this.mem.setUint32(offset + 4, 0, true);
offset += 8;
});
this._inst.exports.run(argc, argv);
if (this.exited) {
this._resolveExitPromise();
}
await this._exitPromise;
}
_resume() {
if (this.exited) {
throw new Error("Go program has already exited");
}
this._inst.exports.resume();
if (this.exited) {
this._resolveExitPromise();
}
}
_makeFuncWrapper(id) {
const go = this;
return function () {
const event = { id: id, this: this, args: arguments };
go._pendingEvent = event;
go._resume();
return event.result;
};
}
}
if (
typeof module !== "undefined" &&
global.require &&
global.require.main === module &&
global.process &&
global.process.versions &&
!global.process.versions.electron
) {
if (process.argv.length < 3) {
console.error("usage: go_js_wasm_exec [wasm binary] [arguments]");
process.exit(1);
}
const go = new Go();
go.argv = process.argv.slice(2);
go.env = Object.assign({ TMPDIR: require("os").tmpdir() }, process.env);
go.exit = process.exit;
WebAssembly.instantiate(fs.readFileSync(process.argv[2]), go.importObject).then((result) => {
process.on("exit", (code) => { // Node.js exits if no event handler is pending
if (code === 0 && !go.exited) {
// deadlock, make Go print error and stack traces
go._pendingEvent = { id: 0 };
go._resume();
}
});
return go.run(result.instance);
}).catch((err) => {
console.error(err);
process.exit(1);
});
}
})();

View File

@@ -1,50 +0,0 @@
/*
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.
*/
import { parseQsFromFragment, parseQs } from "../../src/vector/url_utils";
describe("url_utils.ts", function() {
// @ts-ignore
const location: Location = {
hash: "",
search: "",
};
it("parseQsFromFragment", function() {
location.hash = "/home?foo=bar";
expect(parseQsFromFragment(location)).toEqual({
location: "home",
params: {
"foo": "bar",
},
});
});
describe("parseQs", function() {
location.search = "?foo=bar";
expect(parseQs(location)).toEqual({
"foo": "bar",
});
});
describe("parseQs with arrays", function() {
location.search = "?via=s1&via=s2&via=s2&foo=bar";
expect(parseQs(location)).toEqual({
"via": ["s1", "s2", "s2"],
"foo": "bar",
});
});
});

View File

@@ -12,6 +12,11 @@
"outDir": "./lib",
"declaration": true,
"jsx": "react",
"types": [
"node",
"react",
"flux"
],
"lib": [
"es2019",
"dom",

View File

@@ -1,34 +1,18 @@
/* eslint-disable quote-props */
const dotenv = require('dotenv');
const path = require('path');
const webpack = require('webpack');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const TerserPlugin = require('terser-webpack-plugin');
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
const HtmlWebpackInjectPreload = require('@principalstudio/html-webpack-inject-preload');
dotenv.config();
let ogImageUrl = process.env.RIOT_OG_IMAGE_URL;
if (!ogImageUrl) ogImageUrl = 'https://app.element.io/themes/element/img/logos/opengraph.png';
const cssThemes = {
// CSS themes
"theme-legacy": "./node_modules/matrix-react-sdk/res/themes/legacy-light/css/legacy-light.scss",
"theme-legacy-dark": "./node_modules/matrix-react-sdk/res/themes/legacy-dark/css/legacy-dark.scss",
"theme-light": "./node_modules/matrix-react-sdk/res/themes/light/css/light.scss",
"theme-dark": "./node_modules/matrix-react-sdk/res/themes/dark/css/dark.scss",
"theme-light-custom": "./node_modules/matrix-react-sdk/res/themes/light-custom/css/light-custom.scss",
"theme-dark-custom": "./node_modules/matrix-react-sdk/res/themes/dark-custom/css/dark-custom.scss",
};
function getActiveThemes() {
// We want to use `light` theme by default if it's not defined.
const theme = process.env.MATRIX_THEMES ?? 'dark';
const themes = theme.split(',').filter(x => x).map(x => x.trim()).filter(x => x);
return themes;
}
const additionalPlugins = [
// This is where you can put your customisation replacements.
];
module.exports = (env, argv) => {
let nodeEnv = argv.mode;
@@ -45,8 +29,6 @@ module.exports = (env, argv) => {
// application to productions standards
nodeEnv = "production";
}
const devMode = nodeEnv !== 'production';
const useCssHotReload = process.env.CSS_HOT_RELOAD === '1' && devMode;
const development = {};
if (argv.mode === "production") {
@@ -63,33 +45,38 @@ module.exports = (env, argv) => {
const reactSdkSrcDir = path.resolve(require.resolve("matrix-react-sdk/package.json"), '..', 'src');
const jsSdkSrcDir = path.resolve(require.resolve("matrix-js-sdk/package.json"), '..', 'src');
const ACTIVE_THEMES = getActiveThemes();
function getThemesImports() {
const imports = ACTIVE_THEMES.map((t, index) => {
const themeImportPath = cssThemes[`theme-${ t }`].replace('./node_modules/', '');
return themeImportPath;
});
const s = JSON.stringify(ACTIVE_THEMES);
return `
window.MX_insertedThemeStylesCounter = 0;
window.MX_DEV_ACTIVE_THEMES = (${ s });
${ imports.map(i => `import("${ i }")`).join('\n') };
`;
}
return {
...development,
node: {
// Mock out the NodeFS module: The opus decoder imports this wrongly.
// Also needed by sql.js in P2P mode.
fs: 'empty',
},
entry: {
"bundle": "./src/vector/index.ts",
"mobileguide": "./src/vector/mobile_guide/index.ts",
"indexeddb-worker": "./src/vector/indexeddb-worker.js",
"mobileguide": "./src/vector/mobile_guide/index.js",
"jitsi": "./src/vector/jitsi/index.ts",
"usercontent": "./node_modules/matrix-react-sdk/src/usercontent/index.js",
...(useCssHotReload ? {} : cssThemes),
"recorder-worklet": "./node_modules/matrix-react-sdk/src/voice/RecorderWorklet.ts",
// P2P
"dendrite_sw": "./src/vector/dendrite-sw.js",
"sqlitejs": "./src/vector/sqlitejs.js",
"localforage": "./node_modules/localforage/dist/localforage.min.js",
"sql_wasm": "./node_modules/sql.js/dist/sql-wasm.wasm",
"dendrite_wasm": "./src/vector/dendrite.wasm",
"wasm_exec": "./src/vector/wasm_exec.js",
// CSS themes
"theme-legacy": "./node_modules/matrix-react-sdk/res/themes/legacy-light/css/legacy-light.scss",
"theme-legacy-dark": "./node_modules/matrix-react-sdk/res/themes/legacy-dark/css/legacy-dark.scss",
"theme-light": "./node_modules/matrix-react-sdk/res/themes/light/css/light.scss",
"theme-dark": "./node_modules/matrix-react-sdk/res/themes/dark/css/dark.scss",
"theme-light-custom": "./node_modules/matrix-react-sdk/res/themes/light-custom/css/light-custom.scss",
"theme-dark-custom": "./node_modules/matrix-react-sdk/res/themes/dark-custom/css/dark-custom.scss",
},
optimization: {
@@ -173,18 +160,6 @@ module.exports = (env, argv) => {
/olm[\\/](javascript[\\/])?olm\.js$/,
],
rules: [
useCssHotReload && {
test: /devcss\.ts$/,
loader: 'string-replace-loader',
options: {
search: '"use theming";',
replace: getThemesImports(),
},
},
{
test: /\.worker\.ts$/,
loader: "worker-loader",
},
{
test: /\.(ts|js)x?$/,
include: (f) => {
@@ -250,7 +225,7 @@ module.exports = (env, argv) => {
// It's important that this plugin is last otherwise we end
// up with broken CSS.
require('postcss-preset-env')({ stage: 3, browsers: 'last 2 versions' }),
require('postcss-preset-env')({stage: 3, browsers: 'last 2 versions'}),
],
parser: "postcss-scss",
"local-plugins": true,
@@ -261,40 +236,7 @@ module.exports = (env, argv) => {
{
test: /\.scss$/,
use: [
/**
* This code is hopeful that no .scss outside of our themes will be directly imported in any
* of the JS/TS files.
* Should be MUCH better with webpack 5, but we're stuck to this solution for now.
*/
useCssHotReload ? {
loader: 'style-loader',
/**
* If we refactor the `theme.js` in `matrix-react-sdk` a little bit,
* we could try using `lazyStyleTag` here to add and remove styles on demand,
* that would nicely resolve issues of race conditions for themes,
* at least for development purposes.
*/
options: {
insert: function insertBeforeAt(element) {
const parent = document.querySelector('head');
// We're in iframe
if (!window.MX_DEV_ACTIVE_THEMES) {
parent.appendChild(element);
return;
}
// Properly disable all other instances of themes
element.disabled = true;
element.onload = () => {
element.disabled = true;
};
const theme = window.MX_DEV_ACTIVE_THEMES[window.MX_insertedThemeStylesCounter];
element.setAttribute('data-mx-theme', theme);
window.MX_insertedThemeStylesCounter++;
parent.appendChild(element);
},
},
} : MiniCssExtractPlugin.loader,
MiniCssExtractPlugin.loader,
{
loader: 'css-loader',
options: {
@@ -318,10 +260,11 @@ module.exports = (env, argv) => {
require("postcss-easings")(),
require("postcss-strip-inline-comments")(),
require("postcss-hexrgba")(),
require("postcss-calc")(),
// It's important that this plugin is last otherwise we end
// up with broken CSS.
require('postcss-preset-env')({ stage: 3, browsers: 'last 2 versions' }),
require('postcss-preset-env')({stage: 3, browsers: 'last 2 versions'}),
],
parser: "postcss-scss",
"local-plugins": true,
@@ -334,7 +277,9 @@ module.exports = (env, argv) => {
loader: "file-loader",
type: "javascript/auto", // https://github.com/webpack/webpack/issues/6725
options: {
name: '[name].[hash:7].[ext]',
// fixme: reintroduce [hash] once we can figure out how to pass it into the
// dendrite service worker nicely
name: '[name].[ext]',
outputPath: '.',
},
},
@@ -350,26 +295,6 @@ module.exports = (env, argv) => {
outputPath: '.',
},
},
{
// Special case the recorder worklet as it can't end up HMR'd, but the worker-loader
// isn't good enough for us. Note that the worklet-loader is listed as "do not use",
// however it seems to work fine for our purposes.
test: /RecorderWorklet\.ts$/,
type: "javascript/auto",
use: [ // executed last -> first, for some reason.
{
loader: "worklet-loader",
options: {
// Override name so we know what it is in the output.
name: 'recorder-worklet.[hash:7].js',
},
},
{
// TS -> JS because the worklet-loader won't do this for us.
loader: "babel-loader",
},
],
},
{
// This is from the same place as the encoderWorker above, but only needed
// for Safari support.
@@ -454,19 +379,13 @@ module.exports = (env, argv) => {
},
],
},
].filter(Boolean),
],
},
plugins: [
new webpack.EnvironmentPlugin({
NODE_ENV: 'development', // use 'development' unless process.env.NODE_ENV is defined
DEBUG: false,
}),
// This exports our CSS using the splitChunks and loaders above.
new MiniCssExtractPlugin({
filename: useCssHotReload ? "bundles/[name].css" : "bundles/[hash]/[name].css",
chunkFilename: useCssHotReload ? "bundles/[name].css" : "bundles/[hash]/[name].css",
filename: 'bundles/[hash]/[name].css',
ignoreOrder: false, // Enable to remove warnings about conflicting order
}),
@@ -527,6 +446,7 @@ module.exports = (env, argv) => {
files: [{ match: /.*Inter.*\.woff2$/ }],
}),
...additionalPlugins,
],
output: {
@@ -541,22 +461,29 @@ module.exports = (env, argv) => {
// chunks even after the app is redeployed.
filename: "bundles/[hash]/[name].js",
chunkFilename: "bundles/[hash]/[name].js",
libraryTarget: "var",
library: "[name]",
},
// configuration for the webpack-dev-server
devServer: {
// serve unwebpacked assets from webapp.
contentBase: [
'./webapp',
],
contentBase: './webapp',
// Only output errors, warnings, or new compilations.
// This hides the massive list of modules.
stats: 'minimal',
// hot: false,
// injectHot: false,
hotOnly: true,
inline: true,
headers: {
"Service-Worker-Allowed": "/",
},
// hot module replacement doesn't work (I think we'd need react-hot-reload?)
// so webpack-dev-server reloads the page on every update which is quite
// tedious in Riot since that can take a while.
hot: false,
inline: false,
writeToDisk: true,
},
};
};

4613
yarn.lock

File diff suppressed because it is too large Load Diff