Compare commits

..

1 Commits

Author SHA1 Message Date
Michael Telatynski
a52d4aed9f Specify node-version for setup-node action 2022-10-13 08:52:52 +01:00
45 changed files with 1180 additions and 1153 deletions

View File

@@ -14,15 +14,11 @@ module.exports = {
},
settings: {
react: {
version: 'detect',
},
version: 'detect'
}
},
overrides: [{
files: [
"src/**/*.{ts,tsx}",
"test/**/*.{ts,tsx}",
"module_system/**/*.{ts,tsx}",
],
files: ["src/**/*.{ts,tsx}", "module_system/**/*.{ts,tsx}"],
extends: [
"plugin:matrix-org/typescript",
"plugin:matrix-org/react",

View File

@@ -5,7 +5,7 @@ body:
- type: markdown
attributes:
value: |
Thank you for taking the time to propose an enhancement to an existing feature. If you would like to propose a new feature or a major cross-platform change, please [start a discussion here](https://github.com/vector-im/element-meta/discussions/new?category=ideas).
Thank you for taking the time to propose a new feature or make a suggestion.
- type: textarea
id: usecase
attributes:

View File

@@ -18,6 +18,7 @@ jobs:
- uses: actions/setup-node@v3
with:
cache: 'yarn'
node-version: 16
- name: Install Dependencies
run: "./scripts/layered.sh"

View File

@@ -22,6 +22,7 @@ jobs:
- uses: actions/setup-node@v3
with:
cache: 'yarn'
node-version: 16
- name: Install Dependencies
run: "./scripts/layered.sh"

View File

@@ -19,6 +19,7 @@ jobs:
- uses: actions/setup-node@v3
with:
cache: 'yarn'
node-version: 16
- name: Install Dependencies
run: "./scripts/layered.sh"
@@ -39,6 +40,7 @@ jobs:
- uses: actions/setup-node@v3
with:
cache: 'yarn'
node-version: 16
# Does not need branch matching as only analyses this layer
- name: Install Deps
@@ -56,6 +58,7 @@ jobs:
- uses: actions/setup-node@v3
with:
cache: 'yarn'
node-version: 16
# Needs branch matching as it inherits .stylelintrc.js from matrix-react-sdk
- name: Install Dependencies
@@ -73,6 +76,7 @@ jobs:
- uses: actions/setup-node@v3
with:
cache: 'yarn'
node-version: 16
- name: Install Deps
run: "scripts/layered.sh"

View File

@@ -21,6 +21,7 @@ jobs:
uses: actions/setup-node@v3
with:
cache: 'yarn'
node-version: 16
- name: Install Dependencies
run: "./scripts/layered.sh"

View File

@@ -17,8 +17,7 @@ jobs:
contains(github.event.issue.labels.*.name, 'A-E2EE-Dehydration') ||
contains(github.event.issue.labels.*.name, 'A-Tags') ||
contains(github.event.issue.labels.*.name, 'A-Video-Rooms') ||
contains(github.event.issue.labels.*.name, 'A-Message-Starring') ||
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor')
contains(github.event.issue.labels.*.name, 'A-Message-Starring')
steps:
- uses: actions/github-script@v5
with:
@@ -30,23 +29,6 @@ jobs:
labels: ['Z-Labs']
})
apply_Help-Wanted_label:
name: Add "Help Wanted" label to all "good first issue" and Hacktoberfest
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'good first issue') ||
contains(github.event.issue.labels.*.name, 'Hacktoberfest')
steps:
- uses: actions/github-script@v5
with:
script: |
github.rest.issues.addLabels({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
labels: ['Help Wanted']
})
move_needs_info_issues:
name: X-Needs-Info issues to Need info column on triage board
runs-on: ubuntu-latest
@@ -62,13 +44,7 @@ jobs:
name: P1 X-Needs-Design to Design project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'X-Needs-Design') &&
(contains(github.event.issue.labels.*.name, 'S-Critical') &&
(contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'O-Occasional')) ||
contains(github.event.issue.labels.*.name, 'S-Major') &&
contains(github.event.issue.labels.*.name, 'O-Frequent') ||
contains(github.event.issue.labels.*.name, 'A11y'))
contains(github.event.issue.labels.*.name, 'X-Needs-Design')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
@@ -185,7 +161,6 @@ jobs:
env:
PROJECT_ID: "PN_kwDOAM0swc2KCw"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
move_message_bubbles_issues:
name: A-Message-Bubbles to Message bubbles board
runs-on: ubuntu-latest
@@ -254,105 +229,3 @@ jobs:
env:
PROJECT_ID: "PN_kwDOAM0swc4AArk0"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features1:
name: Add labelled issues to PS features team 1
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Polls') ||
contains(github.event.issue.labels.*.name, 'A-Location-Sharing') ||
(contains(github.event.issue.labels.*.name, 'A-Voice-Messages') &&
!contains(github.event.issue.labels.*.name, 'A-Broadcast')) ||
(contains(github.event.issue.labels.*.name, 'A-Session-Mgmt') &&
contains(github.event.issue.labels.*.name, 'A-User-Settings'))
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4AHJKF"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features2:
name: Add labelled issues to PS features team 2
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-DM-Start') ||
contains(github.event.issue.labels.*.name, 'A-Broadcast')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4AHJKd"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
ps_features3:
name: Add labelled issues to PS features team 3
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'A-Rich-Text-Editor')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4AHJKW"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
voip:
name: Add labelled issues to VoIP project board
runs-on: ubuntu-latest
if: >
contains(github.event.issue.labels.*.name, 'Team: VoIP')
steps:
- uses: octokit/graphql-action@v2.x
id: add_to_project
with:
headers: '{"GraphQL-Features": "projects_next_graphql"}'
query: |
mutation add_to_project($projectid:ID!,$contentid:ID!) {
addProjectV2ItemById(input: {projectId: $projectid contentId: $contentid}) {
item {
id
}
}
}
projectid: ${{ env.PROJECT_ID }}
contentid: ${{ github.event.issue.node_id }}
env:
PROJECT_ID: "PVT_kwDOAM0swc4ABMIk"
GITHUB_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

View File

@@ -1,109 +1,3 @@
Changes in [1.11.14](https://github.com/vector-im/element-web/releases/tag/v1.11.14) (2022-11-08)
=================================================================================================
## ✨ Features
* Loading threads with server-side assistance ([\#9356](https://github.com/matrix-org/matrix-react-sdk/pull/9356)). Fixes #21807, #21799, #21911, #22141, #22157, #22641, #22501 #22438 and #21678. Contributed by @justjanne.
* Make thread replies trigger a room list re-ordering ([\#9510](https://github.com/matrix-org/matrix-react-sdk/pull/9510)). Fixes #21700.
* Device manager - add extra details to device security and renaming ([\#9501](https://github.com/matrix-org/matrix-react-sdk/pull/9501)). Contributed by @kerryarchibald.
* Add plain text mode to the wysiwyg composer ([\#9503](https://github.com/matrix-org/matrix-react-sdk/pull/9503)). Contributed by @florianduros.
* Sliding Sync: improve sort order, show subspace rooms, better tombstoned room handling ([\#9484](https://github.com/matrix-org/matrix-react-sdk/pull/9484)).
* Device manager - add learn more popups to filtered sessions section ([\#9497](https://github.com/matrix-org/matrix-react-sdk/pull/9497)). Contributed by @kerryarchibald.
* Show thread notification if thread timeline is closed ([\#9495](https://github.com/matrix-org/matrix-react-sdk/pull/9495)). Fixes #23589.
* Add message editing to wysiwyg composer ([\#9488](https://github.com/matrix-org/matrix-react-sdk/pull/9488)). Contributed by @florianduros.
* Device manager - confirm sign out of other sessions ([\#9487](https://github.com/matrix-org/matrix-react-sdk/pull/9487)). Contributed by @kerryarchibald.
* Automatically request logs from other users in a call when submitting logs ([\#9492](https://github.com/matrix-org/matrix-react-sdk/pull/9492)).
* Add thread notification with server assistance (MSC3773) ([\#9400](https://github.com/matrix-org/matrix-react-sdk/pull/9400)). Fixes #21114, #21413, #21416, #21433, #21481, #21798, #21823 #23192 and #21765.
* Support for login + E2EE set up with QR ([\#9403](https://github.com/matrix-org/matrix-react-sdk/pull/9403)). Contributed by @hughns.
* Allow pressing Enter to send messages in new composer ([\#9451](https://github.com/matrix-org/matrix-react-sdk/pull/9451)). Contributed by @andybalaam.
## 🐛 Bug Fixes
* Fix regressions around media uploads failing and causing soft crashes ([\#9549](https://github.com/matrix-org/matrix-react-sdk/pull/9549)). Fixes matrix-org/element-web-rageshakes#16831, matrix-org/element-web-rageshakes#16824 matrix-org/element-web-rageshakes#16810 and vector-im/element-web#23641.
* Fix /myroomavatar slash command ([\#9536](https://github.com/matrix-org/matrix-react-sdk/pull/9536)). Fixes matrix-org/synapse#14321.
* Fix config.json failing to load for Jitsi wrapper in non-root deployment ([\#23577](https://github.com/vector-im/element-web/pull/23577)).
* Fix NotificationBadge unsent color ([\#9522](https://github.com/matrix-org/matrix-react-sdk/pull/9522)). Fixes #23646.
* Fix room list sorted by recent on app startup ([\#9515](https://github.com/matrix-org/matrix-react-sdk/pull/9515)). Fixes #23635.
* Reset custom power selector when blurred on empty ([\#9508](https://github.com/matrix-org/matrix-react-sdk/pull/9508)). Fixes #23481.
* Reinstate timeline/redaction callbacks when updating notification state ([\#9494](https://github.com/matrix-org/matrix-react-sdk/pull/9494)). Fixes #23554.
* Only render NotificationBadge when needed ([\#9493](https://github.com/matrix-org/matrix-react-sdk/pull/9493)). Fixes #23584.
* Fix embedded Element Call screen sharing ([\#9485](https://github.com/matrix-org/matrix-react-sdk/pull/9485)). Fixes #23571.
* Send Content-Type: application/json header for integration manager /register API ([\#9490](https://github.com/matrix-org/matrix-react-sdk/pull/9490)). Fixes #23580.
* Fix joining calls without audio or video inputs ([\#9486](https://github.com/matrix-org/matrix-react-sdk/pull/9486)). Fixes #23511.
* Ensure spaces in the spotlight dialog have rounded square avatars ([\#9480](https://github.com/matrix-org/matrix-react-sdk/pull/9480)). Fixes #23515.
* Only show mini avatar uploader in room intro when no avatar yet exists ([\#9479](https://github.com/matrix-org/matrix-react-sdk/pull/9479)). Fixes #23552.
* Fix threads fallback incorrectly targets root event ([\#9229](https://github.com/matrix-org/matrix-react-sdk/pull/9229)). Fixes #23147.
* Align video call icon with banner text ([\#9460](https://github.com/matrix-org/matrix-react-sdk/pull/9460)).
* Set relations helper when creating event tile context menu ([\#9253](https://github.com/matrix-org/matrix-react-sdk/pull/9253)). Fixes #22018.
* Device manager - put client/browser device metadata in correct section ([\#9447](https://github.com/matrix-org/matrix-react-sdk/pull/9447)). Contributed by @kerryarchibald.
* Update the room unread notification counter when the server changes the value without any related read receipt ([\#9438](https://github.com/matrix-org/matrix-react-sdk/pull/9438)).
Changes in [1.11.13](https://github.com/vector-im/element-web/releases/tag/v1.11.13) (2022-11-01)
=================================================================================================
## 🐛 Bug Fixes
* Fix default behavior of Room.getBlacklistUnverifiedDevices ([\#2830](https://github.com/matrix-org/matrix-js-sdk/pull/2830)). Contributed by @duxovni.
* Catch server versions API call exception when starting the client ([\#2828](https://github.com/matrix-org/matrix-js-sdk/pull/2828)). Fixes vector-im/element-web#23634.
* Fix authedRequest including `Authorization: Bearer undefined` for password resets ([\#2822](https://github.com/matrix-org/matrix-js-sdk/pull/2822)). Fixes vector-im/element-web#23655.
Changes in [1.11.12](https://github.com/vector-im/element-web/releases/tag/v1.11.12) (2022-10-26)
=================================================================================================
## 🐛 Bug Fixes
* Fix config.json failing to load for Jitsi wrapper in non-root deployment ([\#23577](https://github.com/vector-im/element-web/pull/23577)).
Changes in [1.11.11](https://github.com/vector-im/element-web/releases/tag/v1.11.11) (2022-10-25)
=================================================================================================
## ✨ Features
* Device manager - tweak string formatting of default device name ([\#23457](https://github.com/vector-im/element-web/pull/23457)).
* Add Element Call participant limit ([\#23431](https://github.com/vector-im/element-web/pull/23431)).
* Add Element Call `brand` ([\#23443](https://github.com/vector-im/element-web/pull/23443)).
* Include a file-safe room name and ISO date in chat exports ([\#9440](https://github.com/matrix-org/matrix-react-sdk/pull/9440)). Fixes #21812 and #19724.
* Room call banner ([\#9378](https://github.com/matrix-org/matrix-react-sdk/pull/9378)). Fixes #23453. Contributed by @toger5.
* Device manager - spinners while devices are signing out ([\#9433](https://github.com/matrix-org/matrix-react-sdk/pull/9433)). Fixes #15865.
* Device manager - silence call ringers when local notifications are silenced ([\#9420](https://github.com/matrix-org/matrix-react-sdk/pull/9420)).
* Pass the current language to Element Call ([\#9427](https://github.com/matrix-org/matrix-react-sdk/pull/9427)).
* Hide screen-sharing button in Element Call on desktop ([\#9423](https://github.com/matrix-org/matrix-react-sdk/pull/9423)).
* Add reply support to WysiwygComposer ([\#9422](https://github.com/matrix-org/matrix-react-sdk/pull/9422)). Contributed by @florianduros.
* Disconnect other connected devices (of the same user) when joining an Element call ([\#9379](https://github.com/matrix-org/matrix-react-sdk/pull/9379)).
* Device manager - device tile main click target ([\#9409](https://github.com/matrix-org/matrix-react-sdk/pull/9409)).
* Add formatting buttons to the rich text editor ([\#9410](https://github.com/matrix-org/matrix-react-sdk/pull/9410)). Contributed by @florianduros.
* Device manager - current session context menu ([\#9386](https://github.com/matrix-org/matrix-react-sdk/pull/9386)).
* Remove piwik config fallback for privacy policy URL ([\#9390](https://github.com/matrix-org/matrix-react-sdk/pull/9390)).
* Add the first step to integrate the matrix wysiwyg composer ([\#9374](https://github.com/matrix-org/matrix-react-sdk/pull/9374)). Contributed by @florianduros.
* Device manager - UA parsing tweaks ([\#9382](https://github.com/matrix-org/matrix-react-sdk/pull/9382)).
* Device manager - remove client information events when disabling setting ([\#9384](https://github.com/matrix-org/matrix-react-sdk/pull/9384)).
* Add Element Call participant limit ([\#9358](https://github.com/matrix-org/matrix-react-sdk/pull/9358)).
* Add Element Call room settings ([\#9347](https://github.com/matrix-org/matrix-react-sdk/pull/9347)).
* Device manager - render extended device information ([\#9360](https://github.com/matrix-org/matrix-react-sdk/pull/9360)).
* New group call experience: Room header and PiP designs ([\#9351](https://github.com/matrix-org/matrix-react-sdk/pull/9351)).
* Pass language to Jitsi Widget ([\#9346](https://github.com/matrix-org/matrix-react-sdk/pull/9346)). Contributed by @Fox32.
* Add notifications and toasts for Element Call calls ([\#9337](https://github.com/matrix-org/matrix-react-sdk/pull/9337)).
* Device manager - device type icon ([\#9355](https://github.com/matrix-org/matrix-react-sdk/pull/9355)).
* Delete the remainder of groups ([\#9357](https://github.com/matrix-org/matrix-react-sdk/pull/9357)). Fixes #22770.
* Device manager - display client information in device details ([\#9315](https://github.com/matrix-org/matrix-react-sdk/pull/9315)).
## 🐛 Bug Fixes
* Send Content-Type: application/json header for integration manager /register API ([\#9490](https://github.com/matrix-org/matrix-react-sdk/pull/9490)). Fixes #23580.
* Make ErrorView & CompatibilityView scrollable ([\#23468](https://github.com/vector-im/element-web/pull/23468)). Fixes #23376.
* Device manager - put client/browser device metadata in correct section ([\#9447](https://github.com/matrix-org/matrix-react-sdk/pull/9447)).
* update the room unread notification counter when the server changes the value without any related read receipt ([\#9438](https://github.com/matrix-org/matrix-react-sdk/pull/9438)).
* Don't show call banners in video rooms ([\#9441](https://github.com/matrix-org/matrix-react-sdk/pull/9441)).
* Prevent useContextMenu isOpen from being true if the button ref goes away ([\#9418](https://github.com/matrix-org/matrix-react-sdk/pull/9418)). Fixes matrix-org/element-web-rageshakes#15637.
* Automatically focus the WYSIWYG composer when you enter a room ([\#9412](https://github.com/matrix-org/matrix-react-sdk/pull/9412)).
* Improve the tooltips on the call lobby join button ([\#9428](https://github.com/matrix-org/matrix-react-sdk/pull/9428)).
* Pass the homeserver's base URL to Element Call ([\#9429](https://github.com/matrix-org/matrix-react-sdk/pull/9429)). Fixes #23301.
* Better accommodate long room names in call toasts ([\#9426](https://github.com/matrix-org/matrix-react-sdk/pull/9426)).
* Hide virtual widgets from the room info panel ([\#9424](https://github.com/matrix-org/matrix-react-sdk/pull/9424)). Fixes #23494.
* Inhibit clicking on sender avatar in threads list ([\#9417](https://github.com/matrix-org/matrix-react-sdk/pull/9417)). Fixes #23482.
* Correct the dir parameter of MSC3715 ([\#9391](https://github.com/matrix-org/matrix-react-sdk/pull/9391)). Contributed by @dhenneke.
* Use a more correct subset of users in `/remakeolm` developer command ([\#9402](https://github.com/matrix-org/matrix-react-sdk/pull/9402)).
* use correct default for notification silencing ([\#9388](https://github.com/matrix-org/matrix-react-sdk/pull/9388)). Fixes #23456.
* Device manager - eagerly create `m.local_notification_settings` events ([\#9353](https://github.com/matrix-org/matrix-react-sdk/pull/9353)).
* Close incoming Element call toast when viewing the call lobby ([\#9375](https://github.com/matrix-org/matrix-react-sdk/pull/9375)).
* Always allow enabling sending read receipts ([\#9367](https://github.com/matrix-org/matrix-react-sdk/pull/9367)). Fixes #23433.
* Fixes (vector-im/element-web/issues/22609) where the white theme is not applied when `white -> dark -> white` sequence is done. ([\#9320](https://github.com/matrix-org/matrix-react-sdk/pull/9320)). Contributed by @florianduros.
* Fix applying programmatically set height for "top" room layout ([\#9339](https://github.com/matrix-org/matrix-react-sdk/pull/9339)). Contributed by @Fox32.
Changes in [1.11.10](https://github.com/vector-im/element-web/releases/tag/v1.11.10) (2022-10-11)
=================================================================================================

View File

@@ -1,5 +1,5 @@
# Builder
FROM --platform=$BUILDPLATFORM node:16-buster as builder
FROM node:14-buster as builder
# Support custom branches of the react-sdk and js-sdk. This also helps us build
# images of element-web develop.

View File

@@ -360,7 +360,8 @@ For example:
## Integration managers
Integration managers are embedded applications within Element to help the user configure bots, bridges, and widgets. An integration manager
is a separate piece of software not typically available with your homeserver. To disable integrations, set the options defined here to `null`.
is a separate piece of software not typically available with your homeserver. To disable integrations, leave the options defined here out of
your config.
1. `integrations_ui_url`: The UI URL for the integration manager.
2. `integrations_rest_url`: The REST interface URL for the integration manager.
@@ -550,4 +551,3 @@ The following are undocumented or intended for developer use only.
2. `sync_timeline_limit`
3. `dangerously_allow_unsafe_and_insecure_passwords`
4. `latex_maths_delims`: An optional setting to override the default delimiters used for maths parsing. See https://github.com/matrix-org/matrix-react-sdk/pull/5939 for details. Only used when `feature_latex_maths` is enabled.
5. `voice_broadcast.chunk_length`: Target chunk length in seconds for the Voice Broadcast feature currently under development.

View File

@@ -1,6 +1,6 @@
{
"name": "element-web",
"version": "1.11.14",
"version": "1.11.10",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"repository": {
@@ -46,8 +46,8 @@
"start:res": "yarn build:jitsi && node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --host=0.0.0.0 --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --mode development --disable-host-check --hot",
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
"lint:js": "eslint --max-warnings 0 src module_system test",
"lint:js-fix": "eslint --fix src module_system test",
"lint:js": "eslint --max-warnings 0 src module_system",
"lint:js-fix": "eslint --fix src module_system",
"lint:types": "tsc --noEmit --jsx react && tsc --noEmit --project ./tsconfig.module_system.json",
"lint:style": "stylelint \"res/css/**/*.pcss\"",
"test": "jest",
@@ -57,11 +57,12 @@
"dependencies": {
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.12.tgz",
"@matrix-org/react-sdk-module-api": "^0.0.3",
"browser-request": "^0.3.3",
"gfm.css": "^1.1.2",
"jsrsasign": "^10.5.25",
"katex": "^0.16.0",
"matrix-js-sdk": "21.1.0",
"matrix-react-sdk": "3.60.0",
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop",
"matrix-widget-api": "^1.1.1",
"prop-types": "^15.7.2",
"react": "17.0.2",
@@ -92,7 +93,6 @@
"@testing-library/react": "^12.1.5",
"@types/flux": "^3.1.9",
"@types/jest": "^29.0.0",
"@types/jsrsasign": "^10.5.4",
"@types/modernizr": "^3.5.3",
"@types/node": "^14.18.28",
"@types/react": "^17.0.49",
@@ -132,6 +132,7 @@
"json-loader": "^0.5.7",
"loader-utils": "^1.4.0",
"matrix-mock-request": "^2.5.0",
"matrix-react-test-utils": "^0.2.3",
"matrix-web-i18n": "^1.3.0",
"mini-css-extract-plugin": "^1",
"minimist": "^1.2.6",

View File

@@ -28,7 +28,5 @@
"%(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 на мобилен телефон",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Децентрализиран, криптиран чат & сътрудничество, захранено от $matrixlogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s под %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Децентрализиран, криптиран чат & сътрудничество, захранено от $matrixlogo"
}

View File

@@ -28,7 +28,5 @@
"Powered by Matrix": "Běží na Matrixu",
"%(brand)s Desktop (%(platformName)s)": "%(brand)s pro desktopový počítač (%(platformName)s)",
"Use %(brand)s on mobile": "Používání %(brand)s v mobilních zařízeních",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Decentralizovaný, šifrovaný chat a spolupráce na platformě $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s na %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Decentralizovaný, šifrovaný chat a spolupráce na platformě $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"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",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Dezentralisierter, verschlüsselter Chat & Zusammenarbeit unterstützt von $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s auf %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Dezentralisierter, verschlüsselter Chat & Zusammenarbeit unterstützt von $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"%(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",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Conversaciones y colaboración descentralizadas y cifradas gracias a $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s en %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s de escritorio: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Conversaciones y colaboración descentralizadas y cifradas gracias a $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s kasutab mitmeid uusi brauseri-põhiseid tehnoloogiaid, mis ei ole veel sinu veebibrauseris toetatud.",
"Powered by Matrix": "Põhineb Matrix'il",
"Use %(brand)s on mobile": "Kasuta rakendust %(brand)s nutiseadmes",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Hajutatud ja krüpteeritud suhtlus- ning ühistöörakendus, mille aluseks on $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s operatsioonisüsteemis %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Hajutatud ja krüpteeritud suhtlus- ning ühistöörakendus, mille aluseks on $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"Failed to start": "خطا در شروع",
"Powered by Matrix": "راه اندازی شده با استفاده از ماتریکس",
"Use %(brand)s on mobile": "از %(brand)s گوشی استفاده کنید",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "همکاری چت غیرمتمرکز و رمزگذاری شده & توسعه یافته با استفاده از $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s: روی %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s دسکتاپ: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "همکاری چت غیرمتمرکز و رمزگذاری شده & توسعه یافته با استفاده از $matrixLogo"
}

View File

@@ -27,8 +27,5 @@
"Powered by Matrix": "Moottorina Matrix",
"Your browser can't run %(brand)s": "%(brand)s ei toimi selaimessasi",
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s käyttää edistyneitä selaimen ominaisuuksia, joita nykyinen selaimesi ei tue.",
"Use %(brand)s on mobile": "Käytä %(brand)sia mobiilisti",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Hajautettu, salattu keskustelu & yhteistyö, taustavoimana $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s käyttöjärjestelmällä %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)sin työpöytäversio: %(platformName)s"
"Use %(brand)s on mobile": "Käytä %(brand)sia mobiilisti"
}

View File

@@ -28,7 +28,5 @@
"%(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",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Messagerie décentralisée, chiffrée & une collaboration alimentée par $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s : %(browserName)s pour %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s pour bureau : %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Messagerie décentralisée, chiffrée & une collaboration alimentée par $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "A(z) %(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álja ezt: %(brand)s",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Elosztott, titkosított csevegés és együttműködés ezzel: $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: (%(browserName)s itt: %(osName)s)",
"%(brand)s Desktop: %(platformName)s": "Asztali %(brand)s: (%(platformName)s)"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Elosztott, titkosított csevegés és együttműködés ezzel: $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"The message from the parser is: %(message)s": "Pesan dari pengurai adalah: %(message)s",
"Your Element is misconfigured": "Anda salah mengatur Element",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Konfigurasi tidak absah: hanya bisa menentukan satu dari default_server_config, default_server_name, atau default_hs_url.",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Obrolan & kolaborasi terdesentralisasi dan terenkripsi diberdayakan oleh $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s di %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Obrolan & kolaborasi terdesentralisasi dan terenkripsi diberdayakan oleh $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"%(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",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Chat e collaborazioni criptate e decentralizzate offerte da $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s su %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s"
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "Chat e collaborazioni criptate e decentralizzate offerte da $matrixLogo"
}

View File

@@ -27,8 +27,5 @@
"Open": "열기",
"Download Completed": "다운로드 완료",
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "당신의 Element 설정은 유효하지 않은 JSON을 포함합니다. 이 문제를 해결하고 페이지를 새로고침해주세요.",
"Your Element is misconfigured": "당신의 Element가 잘못 설정되었습니다",
"Decentralised, encrypted chat & collaboration powered by $matrixLogo": "$matrixLogo 에서 제공하는 탈중앙화되고 암호화된 협업",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(osName)s 의 %(browserName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s 데스크탑: %(platformName)s"
"Your Element is misconfigured": "당신의 Element가 잘못 설정되었습니다"
}

View File

@@ -1 +0,0 @@
{}

View File

@@ -10,25 +10,23 @@
"Invalid configuration: no default server specified.": "Configuratie ongeldig: geen standaardserver opgegeven.",
"The message from the parser is: %(message)s": "De ontleder meldt: %(message)s",
"Invalid JSON": "Ongeldige JSON",
"Go to your browser to complete Sign In": "Ga naar je browser om de aanmelding te voltooien",
"Unable to load config file: please refresh the page to try again.": "Kan het configuratiebestand niet laden. Herlaad de pagina.",
"Go to your browser to complete Sign In": "Ga naar uw browser om de aanmelding te voltooien",
"Unable to load config file: please refresh the page to try again.": "Kan het configuratiebestand niet laden. Herlaad de pagina alstublieft.",
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)",
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
"Unsupported browser": "Niet-ondersteunde browser",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Installeer <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, of <safariLink>Safari</safariLink> voor de beste gebruikservaring.",
"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.": "Je kan je huidige browser blijven gebruiken, maar sommige of alle functies zouden niet kunnen werken en de weergave van het programma kan verkeerd zijn.",
"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.": "U kunt uw huidige browser blijven gebruiken, maar sommige of alle functies zouden niet kunnen werken en de weergave van het programma kan verkeerd zijn.",
"I understand the risks and wish to continue": "Ik begrijp de risico's en wil verder gaan",
"Go to element.io": "Ga naar element.io",
"Failed to start": "Opstarten mislukt",
"Open": "Openen",
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Jouw Element configuratie bevat ongeldige JSON. Corrigeer het probleem en herlaad de pagina.",
"Your Element configuration contains invalid JSON. Please correct the problem and reload the page.": "Uw Element configuratie bevat ongeldige JSON. Gelieve het probleem te corrigeren daarna de pagina te herladen.",
"Download Completed": "Download voltooid",
"Your Element is misconfigured": "Jouw Element is verkeerd geconfigureerd",
"Your browser can't run %(brand)s": "Jouw 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 je huidige browser.",
"Your Element is misconfigured": "Uw Element is verkeerd geconfigureerd",
"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 je mobiel",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Gedecentraliseerde, versleutelde chat &amp; samenwerking mogelijk gemaakt door $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s op %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s"
"Use %(brand)s on mobile": "Gebruik %(brand)s op uw mobiel",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Gedecentraliseerde, versleutelde chat &amp; samenwerking mogelijk gemaakt door $matrixLogo"
}

View File

@@ -1,34 +1,31 @@
{
"Unknown device": "Dispozitiv necunoscut",
"Unknown device": "Device necunoscut",
"Dismiss": "Închide",
"Welcome to Element": "Bine ai venit pe Element",
"Sign In": "Autentifică-te",
"Create Account": "Creează-ți Cont",
"Welcome to Element": "Bun venit pe Element",
"Sign In": "Autentificare",
"Create Account": "Crează un cont",
"Explore rooms": "Explorează camerele",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configurație invalidă: se poate specifica doar una dintre default_server_config, default_server_name, sau default_hs_url.",
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuratie invalida: se poate specifica doar una dintre default_server_config, default_server_name, or default_hs_url.",
"Invalid JSON": "JSON invalid",
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Desktop (%(platformName)s)",
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
"Unsupported browser": "Acest browser nu este suportat",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Instalați vă rog <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, sau <safariLink>Safari</safariLink> pentru cea mai bună experiență.",
"I understand the risks and wish to continue": "Ințeleg riscurile și doresc să continui",
"Go to element.io": "Accesează element.io",
"Failed to start": "Inițializare eșuată",
"Please install <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> for the best experience.": "Instalati va rog <chromeLink>Chrome</chromeLink>, <firefoxLink>Firefox</firefoxLink>, or <safariLink>Safari</safariLink> pentru o experienta mai buna.",
"I understand the risks and wish to continue": "Inteleg riscul si doresc sa continui",
"Go to element.io": "Acceseaza element.io",
"Failed to start": "Nu reuseste sa porneasca",
"Your Element is misconfigured": "Element-ul tău este configurat necorespunzător",
"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.": "Poți continua să folosești browser-ul curent, însă unele sau toate funcționalitățile pot să nu meargă, iar aspectul și experiența în aplicație pot fi incorecte.",
"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.": "Poți continua să folosești browser-ul curent, însă aspectul și experiența câtorva sau tuturor funcțiilor poate fi incorectă.",
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s folosește funcții avansate de browser ce nu sunt suportate de browser-ul dumneavoastră.",
"Your browser can't run %(brand)s": "Browser-ul tău nu poate rula %(brand)s",
"Your browser can't run %(brand)s": "Browserul tău nu poate rula %(brand)s",
"Use %(brand)s on mobile": "Folosește %(brand)s pe mobil",
"Powered by Matrix": "Cu ajutorul Matrix",
"Go to your browser to complete Sign In": "Deschide în browser pentru a finaliza Autentificarea",
"Powered by Matrix": "Bazat pe Matrix",
"Go to your browser to complete Sign In": "Du-te la browser pentru a finaliza Autentificarea",
"Open": "Deschide",
"Download Completed": "Descărcare Completă",
"Unexpected error preparing the app. See console for details.": "Eroare neașteptată în aplicație. Vezi consola pentru detalii.",
"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 să reîncărcați pagina și să încercați din nou.",
"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 să corectați problema și să reîncărcați pagina.",
"Invalid configuration: no default server specified.": "Configurație invalidă: niciun server implicit nu este specificat.",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s pe %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Desktop: %(platformName)s",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Chat &amp; colaborare descentralizate și criptate cu ajutorul $matrixLogo"
"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."
}

View File

@@ -28,7 +28,5 @@
"%(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 на мобильном телефоне",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Децентрализованное, зашифрованное общение и сотрудничество на основе $matrixLogo",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Рабочий стол: %(platformName)s",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s на %(osName)s"
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Децентрализованное, зашифрованное общение и сотрудничество на основе $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"%(brand)s uses advanced browser features which aren't supported by your current browser.": "%(brand)s používa pokročilé funkcie prehliadača, ktoré nie sú podporované vaším aktuálnym prehliadačom.",
"Powered by Matrix": "používa protokol Matrix",
"Use %(brand)s on mobile": "Používať %(brand)s pri mobilných zariadeniach",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Decentralizované, šifrované konverzácie a spolupráca na platforme $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s na %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Stolný počítač: %(platformName)s"
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Decentralizované, šifrované konverzácie a spolupráca na platforme $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"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",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Decentraliserad krypterad chatt &amp; samarbete som drivs av $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s på %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s Skrivbord: %(platformName)s"
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Decentraliserad krypterad chatt &amp; samarbete som drivs av $matrixLogo"
}

View File

@@ -24,7 +24,7 @@
"Go to element.io": "element.io adresine git",
"Failed to start": "Başlatılamadı",
"Powered by Matrix": "Gücünü Matrix'ten alır",
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName)s (%(browserName)s, %(osName)s)",
"%(appName)s (%(browserName)s, %(osName)s)": "%(appName) (%(browserName), %(osName))",
"%(brand)s Desktop (%(platformName)s)": "%(brand)s Masaüstü (%(platformName)s)",
"Open": "Aç",
"Use %(brand)s on mobile": "Mobilde %(brand)s kullan",

View File

@@ -28,7 +28,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 використовує передові властивості, які ваш браузер не підтримує.",
"Use %(brand)s on mobile": "Користуйтеся %(brand)s на мобільному",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Децентралізована, зашифрована бесіда та співпраця на основі $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s: %(browserName)s на %(osName)s",
"%(brand)s Desktop: %(platformName)s": "%(brand)s для комп'ютера: %(platformName)s"
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "Децентралізована, зашифрована бесіда та співпраця на основі $matrixLogo"
}

View File

@@ -28,7 +28,5 @@
"%(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",
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "去中心化、加密的聊天與協作,威力本源 $matrixLogo",
"%(appName)s: %(browserName)s on %(osName)s": "%(appName)s%(browserName)s 在 %(osName)s 上",
"%(brand)s Desktop: %(platformName)s": "%(brand)s 桌面版:%(platformName)s"
"Decentralised, encrypted chat &amp; collaboration powered by $matrixLogo": "去中心化、加密的聊天與協作,威力本源 $matrixLogo"
}

View File

@@ -65,7 +65,7 @@ const setupCompleted = (async () => {
try {
// Queue a config.json lookup asap, so we can use it later on. We want this to be concurrent with
// other setup work and therefore do not block.
const configPromise = getVectorConfig();
const configPromise = getVectorConfig('..');
// 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));

View File

@@ -137,8 +137,7 @@ export default class WebPlatform extends VectorBasePlatform {
return true;
}
// Exported for tests
public pollForUpdate = (
private pollForUpdate = (
showUpdate: (currentVersion: string, mostRecentVersion: string) => void,
showNoUpdate?: () => void,
): Promise<UpdateStatus> => {

5
test/.eslintrc.js Normal file
View File

@@ -0,0 +1,5 @@
module.exports = {
env: {
mocha: true,
},
}

View File

@@ -17,26 +17,34 @@ limitations under the License.
/* loading.js: test the myriad paths we have for loading the application */
import "fake-indexeddb/auto";
import React from 'react';
import { render, screen, fireEvent, waitFor, RenderResult, waitForElementToBeRemoved } from "@testing-library/react";
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
import { MatrixClientPeg } from 'matrix-react-sdk/src/MatrixClientPeg';
import MatrixChat from 'matrix-react-sdk/src/components/structures/MatrixChat';
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
import MockHttpBackend from 'matrix-mock-request';
import { makeType } from "matrix-react-sdk/src/utils/TypeUtils";
import { ValidatedServerConfig } from 'matrix-react-sdk/src/utils/ValidatedServerConfig';
import { IndexedDBCryptoStore } from "matrix-js-sdk/src/crypto/store/indexeddb-crypto-store";
import { sleep } from "matrix-js-sdk/src/utils";
import "../jest-mocks";
import WebPlatform from '../../src/vector/platform/WebPlatform';
import { parseQs, parseQsFromFragment } from '../../src/vector/url_utils';
import { cleanLocalstorage, deleteIndexedDB } from "../test-utils";
import "../jest-mocks";
import React from 'react';
import ReactDOM from 'react-dom';
import ReactTestUtils from 'react-dom/test-utils';
import MatrixReactTestUtils from 'matrix-react-test-utils';
import * as jssdk from 'matrix-js-sdk/src/matrix';
import {MatrixClientPeg} from 'matrix-react-sdk/src/MatrixClientPeg';
import MatrixChat, {Views} from 'matrix-react-sdk/src/components/structures/MatrixChat';
import dis from 'matrix-react-sdk/src/dispatcher/dispatcher';
import * as test_utils from '../test-utils';
import MockHttpBackend from 'matrix-mock-request';
import {parseQs, parseQsFromFragment} from '../../src/vector/url_utils';
import {makeType} from "matrix-react-sdk/src/utils/TypeUtils";
import { ValidatedServerConfig } from 'matrix-react-sdk/src/utils/ValidatedServerConfig';
import {sleep} from "../test-utils";
import "fake-indexeddb/auto";
import {cleanLocalstorage} from "../test-utils";
import {IndexedDBCryptoStore} from "matrix-js-sdk/src/crypto/store/indexeddb-crypto-store";
import { RoomView as RoomViewClass } from 'matrix-react-sdk/src/components/structures/RoomView';
import LoginComponent from 'matrix-react-sdk/src/components/structures/auth/Login';
import WelcomeComponent from "matrix-react-sdk/src/components/views/auth/Welcome";
import EmbeddedPage from "matrix-react-sdk/src/components/structures/EmbeddedPage";
import { AutoDiscovery } from 'matrix-js-sdk/src/matrix';
const DEFAULT_HS_URL = 'http://my_server';
const DEFAULT_IS_URL = 'http://my_is';
const DEFAULT_HS_URL='http://my_server';
const DEFAULT_IS_URL='http://my_is';
describe('loading:', function() {
let parentDiv;
@@ -46,7 +54,7 @@ describe('loading:', function() {
let windowLocation;
// the mounted MatrixChat
let matrixChat: RenderResult;
let matrixChat;
// a promise which resolves when the MatrixChat calls onTokenLoginCompleted
let tokenLoginCompletePromise;
@@ -66,16 +74,25 @@ describe('loading:', function() {
afterEach(async function() {
console.log(`${Date.now()}: loading: afterEach`);
matrixChat?.unmount();
// unmounting should have cleared the MatrixClientPeg
expect(MatrixClientPeg.get()).toBe(null);
try {
if (matrixChat) {
ReactDOM.unmountComponentAtNode(parentDiv);
parentDiv.remove();
parentDiv = null;
}
// clear the indexeddbs so we can start from a clean slate next time.
await Promise.all([
deleteIndexedDB('matrix-js-sdk:crypto'),
deleteIndexedDB('matrix-js-sdk:riot-web-sync'),
]);
cleanLocalstorage();
// unmounting should have cleared the MatrixClientPeg
expect(MatrixClientPeg.get()).toBe(null);
// clear the indexeddbs so we can start from a clean slate next time.
await Promise.all([
test_utils.deleteIndexedDB('matrix-js-sdk:crypto'),
test_utils.deleteIndexedDB('matrix-js-sdk:riot-web-sync'),
]);
cleanLocalstorage();
} catch (e) {
console.error(e);
}
console.log(`${Date.now()}: loading: afterEach complete`);
});
@@ -132,8 +149,8 @@ describe('loading:', function() {
const params = parseQs(windowLocation);
tokenLoginCompletePromise = new Promise<void>(resolve => {
matrixChat = render(
tokenLoginCompletePromise = new Promise(resolve => {
matrixChat = ReactDOM.render(
<MatrixChat
onNewScreen={onNewScreen}
config={config}
@@ -159,14 +176,13 @@ describe('loading:', function() {
.respond(200, {
"versions": ["r0.3.0"],
"unstable_features": {
"m.lazy_load_members": true,
},
"m.lazy_load_members": true
}
});
const isGuest = opts && opts.isGuest;
if (!isGuest) {
// the call to create the LL filter
httpBackend.when('POST', '/filter').respond(200, { filter_id: 'llfid' });
httpBackend.when('GET', '/pushrules').respond(200, {});
}
httpBackend.when('GET', '/sync')
.check((r) => {syncRequest = r;})
@@ -186,10 +202,10 @@ describe('loading:', function() {
it('gives a welcome page by default', function() {
loadApp();
return sleep(1).then(async () => {
return sleep(1).then(() => {
// at this point, we're trying to do a guest registration;
// we expect a spinner
await assertAtLoadingSpinner();
assertAtLoadingSpinner(matrixChat);
httpBackend.when('POST', '/register').check(function(req) {
expect(req.queryParams.kind).toEqual('guest');
@@ -200,7 +216,7 @@ describe('loading:', function() {
// Wait for another trip around the event loop for the UI to update
return awaitWelcomeComponent(matrixChat);
}).then(() => {
return waitFor(() => expect(windowLocation.hash).toEqual("#/welcome"));
expect(windowLocation.hash).toEqual("#/welcome");
});
});
@@ -210,13 +226,13 @@ describe('loading:', function() {
});
// Pass the liveliness checks
httpBackend.when("GET", "/versions").respond(200, { versions: ["r0.4.0"] });
httpBackend.when("GET", "/versions").respond(200, {versions: ["r0.4.0"]});
httpBackend.when("GET", "/api/v1").respond(200, {});
return sleep(1).then(async () => {
return sleep(1).then(() => {
// at this point, we're trying to do a guest registration;
// we expect a spinner
await assertAtLoadingSpinner();
assertAtLoadingSpinner(matrixChat);
httpBackend.when('POST', '/register').check(function(req) {
expect(req.queryParams.kind).toEqual('guest');
@@ -245,20 +261,19 @@ describe('loading:', function() {
});
});
it.skip('should not register as a guest when using a #/login link', function() {
it('should not register as a guest when using a #/login link', function() {
loadApp({
uriFragment: "#/login",
});
// Pass the liveliness checks
httpBackend.when("GET", "/versions").respond(200, { versions: ["r0.4.0"] });
httpBackend.when("GET", "/versions").respond(200, {versions: ["r0.4.0"]});
httpBackend.when("GET", "/api/v1").respond(200, {});
return awaitLoginComponent(matrixChat).then(async () => {
await waitForElementToBeRemoved(() => screen.queryAllByLabelText("Loading..."));
return awaitLoginComponent(matrixChat).then(() => {
// we expect a single <Login> component
await screen.findByRole("main");
screen.getAllByText("Sign in");
ReactTestUtils.findRenderedComponentWithType(
matrixChat, LoginComponent);
// the only outstanding request should be a GET /login
// (in particular there should be no /register request for
@@ -277,7 +292,9 @@ describe('loading:', function() {
}
return completeLogin(matrixChat);
}).then(() => {
expect(matrixChat.container.querySelector(".mx_HomePage")).toBeTruthy();
// once the sync completes, we should have a room view
ReactTestUtils.findRenderedComponentWithType(
matrixChat, EmbeddedPage);
expect(windowLocation.hash).toEqual("#/home");
});
});
@@ -285,8 +302,8 @@ describe('loading:', function() {
describe("MatrixClient rehydrated from stored credentials:", function() {
beforeEach(async function() {
localStorage.setItem("mx_hs_url", "http://localhost");
localStorage.setItem("mx_is_url", "http://localhost");
localStorage.setItem("mx_hs_url", "http://localhost" );
localStorage.setItem("mx_is_url", "http://localhost" );
localStorage.setItem("mx_access_token", "access_token");
localStorage.setItem("mx_user_id", "@me:localhost");
localStorage.setItem("mx_last_room_id", "!last_room:id");
@@ -300,6 +317,8 @@ describe('loading:', function() {
});
it('shows the last known room by default', function() {
httpBackend.when('GET', '/pushrules').respond(200, {});
loadApp();
return awaitLoggedIn(matrixChat).then(() => {
@@ -317,6 +336,8 @@ describe('loading:', function() {
it('shows a home page by default if we have no joined rooms', function() {
localStorage.removeItem("mx_last_room_id");
httpBackend.when('GET', '/pushrules').respond(200, {});
loadApp();
return awaitLoggedIn(matrixChat).then(() => {
@@ -325,12 +346,15 @@ describe('loading:', function() {
}).then(() => {
// once the sync completes, we should have a home page
httpBackend.verifyNoOutstandingExpectation();
expect(matrixChat.container.querySelector(".mx_HomePage")).toBeTruthy();
ReactTestUtils.findRenderedComponentWithType(
matrixChat, EmbeddedPage);
expect(windowLocation.hash).toEqual("#/home");
});
});
it('shows a room view if we followed a room link', function() {
httpBackend.when('GET', '/pushrules').respond(200, {});
loadApp({
uriFragment: "#/room/!room:id",
});
@@ -354,14 +378,48 @@ describe('loading:', function() {
});
// give the UI a chance to display
return expectAndAwaitSync();
return awaitLoginComponent(matrixChat);
});
it('does not show a login view', async function() {
await awaitRoomView(matrixChat);
it('shows a login view', function() {
// Pass the liveliness checks
httpBackend.when("GET", "/versions").respond(200, {versions: ["r0.4.0"]});
httpBackend.when("GET", "/api/v1").respond(200, {});
await screen.findByLabelText("Spaces");
expect(screen.queryAllByText("Sign in")).toHaveLength(0);
// we expect a single <Login> component
ReactTestUtils.findRenderedComponentWithType(
matrixChat, LoginComponent,
);
// the only outstanding request should be a GET /login
// (in particular there should be no /register request for
// guest registration, nor /sync, etc).
const allowedRequests = [
"/_matrix/client/r0/login",
"/versions",
"/api/v1",
];
for (const req of httpBackend.requests) {
if (req.method === 'GET' && allowedRequests.find(p => req.path.endsWith(p))) {
continue;
}
throw new Error(`Unexpected HTTP request to ${req}`);
}
});
it('shows the homepage after login', function() {
// Pass the liveliness checks
httpBackend.when("GET", "/versions").respond(200, {versions: ["r0.4.0"]});
httpBackend.when("GET", "/api/v1").respond(200, {});
return completeLogin(matrixChat).then(() => {
// we should see a home page, even though we previously had
// a stored mx_last_room_id
ReactTestUtils.findRenderedComponentWithType(
matrixChat, EmbeddedPage);
expect(windowLocation.hash).toEqual("#/home");
});
});
});
});
@@ -370,10 +428,10 @@ describe('loading:', function() {
it('shows a welcome page by default', function() {
loadApp();
return sleep(1).then(async () => {
return sleep(1).then(() => {
// at this point, we're trying to do a guest registration;
// we expect a spinner
await assertAtLoadingSpinner();
assertAtLoadingSpinner(matrixChat);
httpBackend.when('POST', '/register').check(function(req) {
expect(req.queryParams.kind).toEqual('guest');
@@ -387,22 +445,24 @@ describe('loading:', function() {
return awaitLoggedIn(matrixChat);
}).then(() => {
// we are logged in - let the sync complete
return expectAndAwaitSync({ isGuest: true });
return expectAndAwaitSync({isGuest: true});
}).then(() => {
// once the sync completes, we should have a welcome page
httpBackend.verifyNoOutstandingExpectation();
expect(matrixChat.container.querySelector(".mx_Welcome")).toBeTruthy();
ReactTestUtils.findRenderedComponentWithType(
matrixChat, WelcomeComponent);
expect(windowLocation.hash).toEqual("#/welcome");
});
});
it('uses the default homeserver to register with', function() {
loadApp();
return sleep(1).then(async () => {
return sleep(1).then(() => {
// at this point, we're trying to do a guest registration;
// we expect a spinner
await assertAtLoadingSpinner();
assertAtLoadingSpinner(matrixChat);
httpBackend.when('POST', '/register').check(function(req) {
expect(req.path.startsWith(DEFAULT_HS_URL)).toBe(true);
@@ -416,13 +476,14 @@ describe('loading:', function() {
}).then(() => {
return awaitLoggedIn(matrixChat);
}).then(() => {
return expectAndAwaitSync({ isGuest: true });
return expectAndAwaitSync({isGuest: true});
}).then((req) => {
expect(req.path.startsWith(DEFAULT_HS_URL)).toBe(true);
// once the sync completes, we should have a welcome page
httpBackend.verifyNoOutstandingExpectation();
expect(matrixChat.container.querySelector(".mx_Welcome")).toBeTruthy();
ReactTestUtils.findRenderedComponentWithType(
matrixChat, WelcomeComponent);
expect(windowLocation.hash).toEqual("#/welcome");
expect(MatrixClientPeg.get().baseUrl).toEqual(DEFAULT_HS_URL);
expect(MatrixClientPeg.get().idBaseUrl).toEqual(DEFAULT_IS_URL);
@@ -430,13 +491,14 @@ describe('loading:', function() {
});
it('shows a room view if we followed a room link', function() {
loadApp({
uriFragment: "#/room/!room:id",
});
return sleep(1).then(async () => {
return sleep(1).then(() => {
// at this point, we're trying to do a guest registration;
// we expect a spinner
await assertAtLoadingSpinner();
assertAtLoadingSpinner(matrixChat);
httpBackend.when('POST', '/register').check(function(req) {
expect(req.queryParams.kind).toEqual('guest');
@@ -449,7 +511,7 @@ describe('loading:', function() {
}).then(() => {
return awaitLoggedIn(matrixChat);
}).then(() => {
return expectAndAwaitSync({ isGuest: true });
return expectAndAwaitSync({isGuest: true});
}).then(() => {
// once the sync completes, we should have a room view
return awaitRoomView(matrixChat);
@@ -461,6 +523,7 @@ describe('loading:', function() {
describe('Login as user', function() {
beforeEach(function() {
// first we have to load the homepage
loadApp();
@@ -476,9 +539,10 @@ describe('loading:', function() {
}).then(() => {
// we got a sync spinner - let the sync complete
return expectAndAwaitSync();
}).then(async () => {
}).then(() => {
// once the sync completes, we should have a home page
await waitFor(() => matrixChat.container.querySelector(".mx_HomePage"));
ReactTestUtils.findRenderedComponentWithType(
matrixChat, EmbeddedPage);
// we simulate a click on the 'login' button by firing off
// the relevant dispatch.
@@ -495,13 +559,40 @@ describe('loading:', function() {
});
});
it('should give us a login page', async function() {
// we expect a single <Login> component
await screen.findByRole("main");
screen.getAllByText("Sign in");
it('should give us a login page', function() {
expect(windowLocation.hash).toEqual("#/login");
// we expect a single <Login> component
ReactTestUtils.findRenderedComponentWithType(
matrixChat, LoginComponent,
);
});
/*
// ILAG renders this obsolete. I think.
it('should allow us to return to the app', function() {
const login = ReactTestUtils.findRenderedComponentWithType(
matrixChat, LoginComponent
);
const linkText = 'Return to app';
const returnToApp = ReactTestUtils.scryRenderedDOMComponentsWithTag(
login, 'a').find((e) => e.innerText === linkText);
if (!returnToApp) {
throw new Error(`Couldn't find '${linkText}' link`);
}
ReactTestUtils.Simulate.click(returnToApp);
return sleep(1).then(() => {
// we should be straight back into the home page
ReactTestUtils.findRenderedComponentWithType(
matrixChat, EmbeddedPage);
});
});
*/
});
});
@@ -513,9 +604,9 @@ describe('loading:', function() {
queryString: "?loginToken=secretToken",
});
return sleep(1).then(async () => {
return sleep(1).then(() => {
// we expect a spinner while we're logging in
await assertAtLoadingSpinner();
assertAtLoadingSpinner(matrixChat);
httpBackend.when('POST', '/login').check(function(req) {
expect(req.path).toMatch(new RegExp("^https://homeserver/"));
@@ -548,11 +639,15 @@ describe('loading:', function() {
// check that we have a Login component, send a 'user:pass' login,
// and await the HTTP requests.
async function completeLogin(matrixChat: RenderResult) {
async function completeLogin(matrixChat) {
// we expect a single <Login> component
const login = ReactTestUtils.findRenderedComponentWithType(
matrixChat, LoginComponent);
// When we switch to the login component, it'll hit the login endpoint
// for proof of life and to get flows. We'll only give it one option.
httpBackend.when('GET', '/login')
.respond(200, { flows: [{ type: "m.login.password" }] });
.respond(200, {"flows": [{"type": "m.login.password"}]});
httpBackend.flush(); // We already would have tried the GET /login request
// Give the component some time to finish processing the login flows before
@@ -569,14 +664,13 @@ describe('loading:', function() {
device_id: 'DEVICE_ID',
access_token: 'access_token',
});
fireEvent.change(matrixChat.container.querySelector("#mx_LoginForm_username"), { target: { value: "user" } });
fireEvent.change(matrixChat.container.querySelector("#mx_LoginForm_password"), { target: { value: "pass" } });
fireEvent.click(screen.getByText("Sign in", { selector: ".mx_Login_submit" }));
login.onPasswordLogin("user", undefined, undefined, "pass");
return httpBackend.flush().then(() => {
// Wait for another trip around the event loop for the UI to update
return sleep(1);
}).then(() => {
httpBackend.when('GET', '/pushrules').respond(200, {});
return expectAndAwaitSync().catch((e) => {
throw new Error("Never got /sync after login: did the client start?");
});
@@ -587,13 +681,18 @@ describe('loading:', function() {
});
// assert that we are on the loading page
async function assertAtLoadingSpinner() {
await screen.findByRole("progressbar");
function assertAtLoadingSpinner(matrixChat) {
const domComponent = ReactDOM.findDOMNode(matrixChat) as Element;
expect(domComponent.className).toEqual("mx_MatrixChat_splash");
// just the spinner
expect(domComponent.children.length).toEqual(1);
}
async function awaitLoggedIn(matrixChat: RenderResult) {
if (matrixChat.container.querySelector(".mx_MatrixChat_wrapper")) return; // already logged in
function awaitLoggedIn(matrixChat) {
if (matrixChat.state.view === Views.LOGGED_IN) {
return Promise.resolve();
}
return new Promise(resolve => {
const onAction = ({ action }) => {
if (action !== "on_logged_in") {
@@ -601,26 +700,55 @@ async function awaitLoggedIn(matrixChat: RenderResult) {
}
console.log(Date.now() + ": Received on_logged_in action");
dis.unregister(dispatcherRef);
resolve(sleep(1));
resolve(undefined);
};
const dispatcherRef = dis.register(onAction);
console.log(Date.now() + ": Waiting for on_logged_in action");
});
}
async function awaitRoomView(matrixChat: RenderResult) {
await waitFor(() => matrixChat.container.querySelector(".mx_RoomView"));
function awaitRoomView(matrixChat, retryLimit?, retryCount?) {
if (retryLimit === undefined) {
retryLimit = 5;
}
if (retryCount === undefined) {
retryCount = 0;
}
if (matrixChat.state.view !== Views.LOGGED_IN || !matrixChat.state.ready) {
console.log(Date.now() + " Awaiting room view: not ready yet.");
if (retryCount >= retryLimit) {
throw new Error("MatrixChat still not ready after " +
retryCount + " tries");
}
return sleep(0).then(() => {
return awaitRoomView(matrixChat, retryLimit, retryCount + 1);
});
}
console.log(Date.now() + " Awaiting room view: now ready.");
// state looks good, check the rendered output
ReactTestUtils.findRenderedComponentWithType(
matrixChat, RoomViewClass);
return Promise.resolve();
}
async function awaitLoginComponent(matrixChat: RenderResult) {
await waitFor(() => matrixChat.container.querySelector(".mx_AuthPage"));
function awaitLoginComponent(matrixChat, attempts?) {
return MatrixReactTestUtils.waitForRenderedComponentWithType(
matrixChat, LoginComponent, attempts,
);
}
async function awaitWelcomeComponent(matrixChat: RenderResult) {
await waitFor(() => matrixChat.container.querySelector(".mx_Welcome"));
function awaitWelcomeComponent(matrixChat, attempts?) {
return MatrixReactTestUtils.waitForRenderedComponentWithType(
matrixChat, WelcomeComponent, attempts,
);
}
function moveFromWelcomeToLogin(matrixChat: RenderResult) {
function moveFromWelcomeToLogin(matrixChat) {
ReactTestUtils.findRenderedComponentWithType(
matrixChat, WelcomeComponent);
dis.dispatch({ action: 'start_login' });
return awaitLoginComponent(matrixChat);
}

View File

@@ -1,19 +1,3 @@
/*
Copyright 2020-2022 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.
*/
// https://jestjs.io/docs/en/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
Object.defineProperty(window, 'matchMedia', {
writable: true,

View File

@@ -1,25 +1,9 @@
/*
Copyright 2016-2022 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.
*/
export function cleanLocalstorage(): void {
export function cleanLocalstorage() {
window.localStorage.clear();
}
export function deleteIndexedDB(dbName: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
export function deleteIndexedDB(dbName) {
return new Promise((resolve, reject) => {
if (!window.indexedDB) {
resolve();
return;
@@ -35,7 +19,7 @@ export function deleteIndexedDB(dbName: string): Promise<void> {
req.onerror = (ev) => {
reject(new Error(
`${Date.now()}: unable to delete indexeddb ${dbName}: ${req.error}`,
`${Date.now()}: unable to delete indexeddb ${dbName}: ${ev.target.error}`,
));
};
@@ -49,3 +33,7 @@ export function deleteIndexedDB(dbName: string): Promise<void> {
throw e;
});
}
export function sleep(ms) {
return new Promise((resolve) => { setTimeout(resolve, ms); });
}

View File

@@ -26,10 +26,10 @@ describe('getVectorConfig()', () => {
const now = 1234567890;
const specificConfig = {
brand: 'specific',
};
}
const generalConfig = {
brand: 'general',
};
}
beforeEach(() => {
document.domain = elementDomain;

View File

@@ -14,25 +14,28 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import request from 'browser-request';
import EventEmitter from 'events';
import { logger } from 'matrix-js-sdk/src/logger';
import { MatrixEvent, Room } from 'matrix-js-sdk/src/matrix';
import { MatrixClient, MatrixEvent, Room } from 'matrix-js-sdk/src/matrix';
import { UpdateCheckStatus } from 'matrix-react-sdk/src/BasePlatform';
import { Action } from 'matrix-react-sdk/src/dispatcher/actions';
import dispatcher from 'matrix-react-sdk/src/dispatcher/dispatcher';
import { MatrixClientPeg } from 'matrix-react-sdk/src/MatrixClientPeg';
import * as rageshake from 'matrix-react-sdk/src/rageshake/rageshake';
import ElectronPlatform from '../../../../src/vector/platform/ElectronPlatform';
jest.mock('matrix-react-sdk/src/rageshake/rageshake', () => ({
flush: jest.fn(),
}));
flush: jest.fn()
}))
describe('ElectronPlatform', () => {
const defaultUserAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 ' +
'(KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36';
const defaultUserAgent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36';
const mockElectron = {
on: jest.fn(),
send: jest.fn(),
send: jest.fn()
};
const dispatchSpy = jest.spyOn(dispatcher, 'dispatch');
@@ -55,25 +58,25 @@ describe('ElectronPlatform', () => {
it('flushes rageshake before quitting', () => {
new ElectronPlatform();
const [event, handler] = getElectronEventHandlerCall('before-quit');
// correct event bound
expect(event).toBeTruthy();
const [event, handler] = getElectronEventHandlerCall('before-quit');
// correct event bound
expect(event).toBeTruthy();
handler();
handler();
expect(logSpy).toHaveBeenCalled();
expect(rageshake.flush).toHaveBeenCalled();
expect(logSpy).toHaveBeenCalled();
expect(rageshake.flush).toHaveBeenCalled();
});
it('dispatches view settings action on preferences event', () => {
new ElectronPlatform();
const [event, handler] = getElectronEventHandlerCall('preferences');
// correct event bound
expect(event).toBeTruthy();
const [event, handler] = getElectronEventHandlerCall('preferences');
// correct event bound
expect(event).toBeTruthy();
handler();
handler();
expect(dispatchFireSpy).toHaveBeenCalledWith(Action.ViewUserSettings);
expect(dispatchFireSpy).toHaveBeenCalledWith(Action.ViewUserSettings);
});
describe('updates', () => {
@@ -82,38 +85,39 @@ describe('ElectronPlatform', () => {
const [event, handler] = getElectronEventHandlerCall('check_updates');
// correct event bound
expect(event).toBeTruthy();
handler({}, true);
expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.CheckUpdates,
status: UpdateCheckStatus.Downloading,
});
status: UpdateCheckStatus.Downloading
})
});
it('dispatches on check updates action when update not available', () => {
new ElectronPlatform();
const [, handler] = getElectronEventHandlerCall('check_updates');
handler({}, false);
expect(dispatchSpy).toHaveBeenCalledWith({
action: Action.CheckUpdates,
status: UpdateCheckStatus.NotAvailable,
});
status: UpdateCheckStatus.NotAvailable
})
});
it('starts update check', () => {
const platform = new ElectronPlatform();
platform.startUpdateCheck();
expect(mockElectron.send).toHaveBeenCalledWith('check_updates');
expect(mockElectron.send).toHaveBeenCalledWith('check_updates')
});
it('installs update', () => {
const platform = new ElectronPlatform();
platform.installUpdate();
expect(mockElectron.send).toHaveBeenCalledWith('install_update');
expect(mockElectron.send).toHaveBeenCalledWith('install_update')
});
});
it('returns human readable name', () => {
const platform = new ElectronPlatform();
expect(platform.getHumanReadableName()).toEqual('Electron Platform');
@@ -121,13 +125,11 @@ describe('ElectronPlatform', () => {
describe("getDefaultDeviceDisplayName", () => {
it.each([[
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 " +
"(KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"Element Desktop: macOS",
],
[
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) " +
"electron/1.0.0 Chrome/53.0.2785.113 Electron/1.4.3 Safari/537.36",
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) electron/1.0.0 Chrome/53.0.2785.113 Electron/1.4.3 Safari/537.36",
"Element Desktop: Windows",
],
[
@@ -149,7 +151,9 @@ describe('ElectronPlatform', () => {
[
"custom user agent",
"Element Desktop: Unknown",
]])("%s = %s", (userAgent, result) => {
],
])("%s = %s", (userAgent, result) => {
delete window.navigator;
window.navigator = { userAgent } as unknown as Navigator;
const platform = new ElectronPlatform();
@@ -228,7 +232,7 @@ describe('ElectronPlatform', () => {
const [channel, { name }] = mockElectron.send.mock.calls[0];
expect(channel).toEqual("ipcCall");
expect(name).toEqual('getAvailableSpellCheckLanguages');
expect(name).toEqual('getAvailableSpellCheckLanguages')
});
});
@@ -239,8 +243,8 @@ describe('ElectronPlatform', () => {
platform.getPickleKey(userId, deviceId);
const [, { name, args }] = mockElectron.send.mock.calls[0];
expect(name).toEqual('getPickleKey');
expect(args).toEqual([userId, deviceId]);
expect(name).toEqual('getPickleKey')
expect(args).toEqual([userId, deviceId])
});
it('makes correct ipc call to create pickle key', () => {
@@ -249,8 +253,8 @@ describe('ElectronPlatform', () => {
platform.createPickleKey(userId, deviceId);
const [, { name, args }] = mockElectron.send.mock.calls[0];
expect(name).toEqual('createPickleKey');
expect(args).toEqual([userId, deviceId]);
expect(name).toEqual('createPickleKey')
expect(args).toEqual([userId, deviceId])
});
it('makes correct ipc call to destroy pickle key', () => {
@@ -259,8 +263,8 @@ describe('ElectronPlatform', () => {
platform.destroyPickleKey(userId, deviceId);
const [, { name, args }] = mockElectron.send.mock.calls[0];
expect(name).toEqual('destroyPickleKey');
expect(args).toEqual([userId, deviceId]);
expect(name).toEqual('destroyPickleKey')
expect(args).toEqual([userId, deviceId])
});
});

View File

@@ -33,7 +33,6 @@ describe('WebPlatform', () => {
});
it('registers service worker', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore - mocking readonly object
navigator.serviceWorker = { register: jest.fn() };
new WebPlatform();
@@ -67,8 +66,7 @@ describe('WebPlatform', () => {
describe("getDefaultDeviceDisplayName", () => {
it.each([[
"https://develop.element.io/#/room/!foo:bar",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) " +
"Chrome/105.0.0.0 Safari/537.36",
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36",
"develop.element.io: Chrome on macOS",
]])("%s & %s = %s", (url, userAgent, result) => {
delete window.navigator;
@@ -84,16 +82,14 @@ describe('WebPlatform', () => {
const mockNotification = {
requestPermission: jest.fn(),
permission: 'notGranted',
};
}
beforeEach(() => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
window.Notification = mockNotification;
mockNotification.permission = 'notGranted';
});
it('supportsNotifications returns false when platform does not support notifications', () => {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
window.Notification = undefined;
expect(new WebPlatform().supportsNotifications()).toBe(false);
@@ -108,7 +104,7 @@ describe('WebPlatform', () => {
});
it('maySendNotifications returns true when notification permissions are granted', () => {
mockNotification.permission = 'granted';
mockNotification.permission = 'granted'
expect(new WebPlatform().maySendNotifications()).toBe(true);
});
@@ -119,6 +115,7 @@ describe('WebPlatform', () => {
const result = await platform.requestNotificationPermission();
expect(result).toEqual('test');
});
});
describe('app version', () => {
@@ -127,7 +124,7 @@ describe('WebPlatform', () => {
beforeEach(() => {
jest.spyOn(MatrixClientPeg, 'userRegisteredWithinLastHours').mockReturnValue(false);
});
})
afterAll(() => {
process.env.VERSION = envVersion;
@@ -157,8 +154,7 @@ describe('WebPlatform', () => {
});
describe('pollForUpdate()', () => {
it('should return not available and call showNoUpdate when current version ' +
'matches most recent version', async () => {
it('should return not available and call showNoUpdate when current version matches most recent version', async () => {
process.env.VERSION = prodVersion;
fetchMock.getOnce("/version", prodVersion);
const platform = new WebPlatform();
@@ -187,8 +183,7 @@ describe('WebPlatform', () => {
expect(showNoUpdate).toHaveBeenCalled();
});
it('should return ready and call showUpdate when current version ' +
'differs from most recent version', async () => {
it('should return ready and call showUpdate when current version differs from most recent version', async () => {
process.env.VERSION = '0.0.0'; // old version
fetchMock.getOnce("/version", prodVersion);
const platform = new WebPlatform();

View File

@@ -17,7 +17,6 @@ limitations under the License.
import { parseQsFromFragment, parseQs } from "../../../src/vector/url_utils";
describe("url_utils.ts", function() {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
const location: Location = {
hash: "",

View File

@@ -21,8 +21,6 @@
},
"include": [
"./src/**/*.ts",
"./src/**/*.tsx",
"./test/**/*.ts",
"./test/**/*.tsx"
"./src/**/*.tsx"
]
}

View File

@@ -123,7 +123,6 @@ module.exports = (env, argv) => {
fs: 'empty',
net: 'empty',
tls: 'empty',
crypto: 'empty',
},
entry: {
@@ -369,14 +368,9 @@ module.exports = (env, argv) => {
],
},
{
// the olm library wants to load its own wasm, rather than have webpack do it.
// We therefore use the `file-loader` to tell webpack to dump the contents to
// a separate file and return the name, and override the default `type` for `.wasm` files
// (which is `webassembly/experimental` under webpack 4) to stop webpack trying to interpret
// the filename as webassembly. (see also https://github.com/webpack/webpack/issues/6725)
test: /olm\.wasm$/,
test: /\.wasm$/,
loader: "file-loader",
type: "javascript/auto",
type: "javascript/auto", // https://github.com/webpack/webpack/issues/6725
options: {
name: '[name].[hash:7].[ext]',
outputPath: '.',
@@ -387,7 +381,7 @@ module.exports = (env, argv) => {
// We more or less just want it to be clear it's for opus and not something else.
test: /encoderWorker\.min\.js$/,
loader: "file-loader",
type: "javascript/auto",
type: "javascript/auto", // https://github.com/webpack/webpack/issues/6725
options: {
// We deliberately override the name so it makes sense in debugging
name: 'opus-encoderWorker.min.[hash:7].[ext]',
@@ -427,11 +421,11 @@ module.exports = (env, argv) => {
},
},
{
// Same deal as olm.wasm: the decoderWorker wants to load the wasm artifact
// itself.
// This is from the same place as the encoderWorker above, but only needed
// for Safari support.
test: /decoderWorker\.min\.wasm$/,
loader: "file-loader",
type: "javascript/auto",
type: "javascript/auto", // https://github.com/webpack/webpack/issues/6725
options: {
// We deliberately don't change the name because the decoderWorker has this
// hardcoded. This is here to avoid the default wasm rule from adding a hash.
@@ -657,7 +651,6 @@ module.exports = (env, argv) => {
// chunks even after the app is redeployed.
filename: "bundles/[hash]/[name].js",
chunkFilename: "bundles/[hash]/[name].js",
webassemblyModuleFilename: "bundles/[hash]/[modulehash].wasm",
},
// configuration for the webpack-dev-server

1441
yarn.lock

File diff suppressed because it is too large Load Diff