Compare commits
267 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a5d5e2800c | ||
|
|
b225367e0d | ||
|
|
38cd6a0d0c | ||
|
|
9b5655c1fa | ||
|
|
e482d69034 | ||
|
|
585d40f4c1 | ||
|
|
a26bd6ef94 | ||
|
|
aa95dcc0cb | ||
|
|
08c149ed66 | ||
|
|
9dd89dff6a | ||
|
|
49ece1cbf9 | ||
|
|
35204416bf | ||
|
|
036348cd60 | ||
|
|
51f2afb7b7 | ||
|
|
2c0968e40e | ||
|
|
3eb5eb1d21 | ||
|
|
4a1b9d8ea4 | ||
|
|
1a84836fd0 | ||
|
|
2e2d90f335 | ||
|
|
b3fb496212 | ||
|
|
a24959319d | ||
|
|
e923f935ea | ||
|
|
54f7347da5 | ||
|
|
95f749ccd9 | ||
|
|
eb62972aed | ||
|
|
3a5a904afb | ||
|
|
7d68c2c465 | ||
|
|
074a3cfaaf | ||
|
|
2b5e028cbe | ||
|
|
ec20e1ece2 | ||
|
|
b107da09fa | ||
|
|
9534a25270 | ||
|
|
f7e5613f30 | ||
|
|
7d49078f22 | ||
|
|
3abe61e13b | ||
|
|
032efafe2e | ||
|
|
087bcf0ae6 | ||
|
|
cdc1202bbe | ||
|
|
bceca49cdc | ||
|
|
c3e6a30789 | ||
|
|
87913e6c98 | ||
|
|
00fa5aad85 | ||
|
|
2818de4d4a | ||
|
|
e9f8700d6b | ||
|
|
d8b059452c | ||
|
|
98b8ba2650 | ||
|
|
37d924731d | ||
|
|
4affaaf309 | ||
|
|
d3d6e4ae77 | ||
|
|
daf6aaaf30 | ||
|
|
d50b52cdc5 | ||
|
|
cff4ad9e82 | ||
|
|
e3e7a47aea | ||
|
|
c30f901716 | ||
|
|
0ad0cbeb35 | ||
|
|
8ca6c2c433 | ||
|
|
9782599c69 | ||
|
|
768cabe4bb | ||
|
|
5d01384af2 | ||
|
|
15a77e8826 | ||
|
|
dd26d43173 | ||
|
|
59d3bd2746 | ||
|
|
1bbb104600 | ||
|
|
9c258f9da9 | ||
|
|
4c4f885f25 | ||
|
|
fb32d41b3e | ||
|
|
2445f19431 | ||
|
|
7aff020d4d | ||
|
|
192f2b8892 | ||
|
|
3d804665da | ||
|
|
c0558f3527 | ||
|
|
d6a5d701fe | ||
|
|
a34507f6e1 | ||
|
|
8b08ba05c2 | ||
|
|
9ee7febd9b | ||
|
|
47d88d6b79 | ||
|
|
d7e47841e5 | ||
|
|
b6963d0e5c | ||
|
|
1b8ea4b6d7 | ||
|
|
51a97571a0 | ||
|
|
1d53fc41ea | ||
|
|
0798945109 | ||
|
|
8d769dafca | ||
|
|
5d95a3ef7e | ||
|
|
0f24950466 | ||
|
|
902252ad93 | ||
|
|
43c35a760b | ||
|
|
cd3fafb2b0 | ||
|
|
eb5e14661d | ||
|
|
fe15d3b7c1 | ||
|
|
ebd3f0e4e1 | ||
|
|
5673d51cec | ||
|
|
323762ffa7 | ||
|
|
8913eba60d | ||
|
|
a90e56a22b | ||
|
|
d4e46108c4 | ||
|
|
8c103b50af | ||
|
|
c197c2f4fd | ||
|
|
2e2e09ed2b | ||
|
|
3036bab1c6 | ||
|
|
e1e3bba290 | ||
|
|
e556bb242f | ||
|
|
18bdbe13b4 | ||
|
|
6835f6054b | ||
|
|
99e1ff9477 | ||
|
|
932c221548 | ||
|
|
3e324f6544 | ||
|
|
5b575d5627 | ||
|
|
be64e86cc3 | ||
|
|
42743c3ead | ||
|
|
5d8d5d70d0 | ||
|
|
024297c200 | ||
|
|
db030d9733 | ||
|
|
4c699d8001 | ||
|
|
922ed597d6 | ||
|
|
c3a5e2e5d3 | ||
|
|
ad8bd62ae6 | ||
|
|
119802d00f | ||
|
|
674adfb81e | ||
|
|
342d717ff6 | ||
|
|
cdd25ea45f | ||
|
|
4191c51b42 | ||
|
|
a2e256b4c9 | ||
|
|
e3b4f189b4 | ||
|
|
8c6d6b1d09 | ||
|
|
63f8a22b34 | ||
|
|
b965188a5f | ||
|
|
4ca41f4971 | ||
|
|
276d14dd5d | ||
|
|
9a084a6801 | ||
|
|
fb9503199d | ||
|
|
bb931e25d8 | ||
|
|
69d49f9881 | ||
|
|
6ce50435e3 | ||
|
|
0efd7edf0c | ||
|
|
4e37f8aa88 | ||
|
|
fb77bcf762 | ||
|
|
2652060e38 | ||
|
|
3fb6b1ed63 | ||
|
|
5cd54e9f6d | ||
|
|
9ab40af430 | ||
|
|
bcda501864 | ||
|
|
c70d21a92e | ||
|
|
5c915f3d02 | ||
|
|
f0dbc85ca5 | ||
|
|
84439cff86 | ||
|
|
e37da08730 | ||
|
|
3c9c0ec447 | ||
|
|
161a1342b2 | ||
|
|
ae010ef649 | ||
|
|
909fddb732 | ||
|
|
044720b7e5 | ||
|
|
599b263e22 | ||
|
|
625c21a8af | ||
|
|
d515bad46f | ||
|
|
f2da98b136 | ||
|
|
ab758d2377 | ||
|
|
1a3e5a3c70 | ||
|
|
a978a6734f | ||
|
|
3b688aaeb8 | ||
|
|
f73d2bae1f | ||
|
|
6ce5377747 | ||
|
|
619cd57bc6 | ||
|
|
d426847f4f | ||
|
|
2574841bf4 | ||
|
|
fd6b6dc597 | ||
|
|
54a88a94b7 | ||
|
|
057f78fadc | ||
|
|
b4f210d68f | ||
|
|
2471b803e8 | ||
|
|
9e8358dc24 | ||
|
|
12267159f2 | ||
|
|
0e65d2ecfa | ||
|
|
1b1a8594c0 | ||
|
|
2fdaf65244 | ||
|
|
1cb0e39dcc | ||
|
|
a41484cb35 | ||
|
|
455b7ae347 | ||
|
|
d877187d5e | ||
|
|
9bf1c65971 | ||
|
|
a91bab29ff | ||
|
|
929096b3f9 | ||
|
|
5445f97998 | ||
|
|
a6015d46f4 | ||
|
|
110b63b816 | ||
|
|
ec66069e96 | ||
|
|
4482cac9b4 | ||
|
|
1cd9c4ff11 | ||
|
|
203c9c8a7d | ||
|
|
37a83d469c | ||
|
|
e19d86e822 | ||
|
|
f7637a0df7 | ||
|
|
275b0555bd | ||
|
|
5d636baae3 | ||
|
|
a1b14751e5 | ||
|
|
15982ae0b0 | ||
|
|
5f1ef6dfb8 | ||
|
|
14620a5763 | ||
|
|
66b40d8c61 | ||
|
|
1de2fe5e27 | ||
|
|
52ca0908e2 | ||
|
|
f7618e3c73 | ||
|
|
8b3df0d793 | ||
|
|
1f1c8d07c3 | ||
|
|
06dc5aa410 | ||
|
|
83e5ebafd7 | ||
|
|
50fe3109c0 | ||
|
|
d7607df1b1 | ||
|
|
23e9c16ced | ||
|
|
024c019c5b | ||
|
|
514e9b754a | ||
|
|
16e384172c | ||
|
|
9b8819eb08 | ||
|
|
b0255683e9 | ||
|
|
7a285ead7e | ||
|
|
e25fee6f99 | ||
|
|
01f14a7211 | ||
|
|
e993eee97c | ||
|
|
7744dcc508 | ||
|
|
f98ac9dda1 | ||
|
|
af76adf866 | ||
|
|
1c0bb1101b | ||
|
|
9beb4e94d7 | ||
|
|
11e304f42f | ||
|
|
3389f7afc9 | ||
|
|
17e332bb48 | ||
|
|
8e754765e2 | ||
|
|
1b41dc3291 | ||
|
|
262b5a56ca | ||
|
|
15bded694b | ||
|
|
c44a6e296e | ||
|
|
443d3812d1 | ||
|
|
6ead268ef0 | ||
|
|
5fbe74e20d | ||
|
|
4479018289 | ||
|
|
7f451d2635 | ||
|
|
ecb386017f | ||
|
|
4be0ff7095 | ||
|
|
6f06716954 | ||
|
|
f6db2ed8dd | ||
|
|
c143b9b2d7 | ||
|
|
b537016bfb | ||
|
|
e5fcbd1b05 | ||
|
|
b23318be8d | ||
|
|
65c8c8b52a | ||
|
|
0930424406 | ||
|
|
4ae5559a59 | ||
|
|
df3517d7bf | ||
|
|
dd9eda8f97 | ||
|
|
eb42793ad5 | ||
|
|
a30ad77d10 | ||
|
|
26eff8d372 | ||
|
|
685c1ba276 | ||
|
|
04402b325a | ||
|
|
bd57ff793f | ||
|
|
33284302b9 | ||
|
|
89d622b8b2 | ||
|
|
b7f6d7b102 | ||
|
|
7776b19339 | ||
|
|
60467ffd02 | ||
|
|
364e79c673 | ||
|
|
c063cec4d7 | ||
|
|
e2b1a86a29 | ||
|
|
1d49544238 | ||
|
|
70d2adb9e2 | ||
|
|
8ad1bd1501 | ||
|
|
f93b7a1675 |
20
.babelrc
20
.babelrc
@@ -1,20 +0,0 @@
|
||||
{
|
||||
"presets": [
|
||||
"react",
|
||||
"es2015",
|
||||
"es2016"
|
||||
],
|
||||
"plugins": [
|
||||
[
|
||||
"transform-builtin-extend",
|
||||
{
|
||||
"globals": ["Error"]
|
||||
}
|
||||
],
|
||||
"transform-class-properties",
|
||||
"transform-object-rest-spread",
|
||||
"transform-runtime",
|
||||
"add-module-exports",
|
||||
"syntax-dynamic-import"
|
||||
]
|
||||
}
|
||||
@@ -1,46 +1,55 @@
|
||||
steps:
|
||||
- label: ":eslint: Lint"
|
||||
- label: ":eslint: JS Lint"
|
||||
command:
|
||||
- "echo '--- Fetching Dependencies'"
|
||||
- "./scripts/fetch-develop.deps.sh --depth 1"
|
||||
- "yarn install"
|
||||
- "yarn lint"
|
||||
- "yarn lint:js"
|
||||
plugins:
|
||||
- docker#v3.0.1:
|
||||
image: "node:10"
|
||||
image: "node:12"
|
||||
|
||||
- label: ":karma: Tests"
|
||||
# This layer doesn't have a TypeScript linter. This comment is to remind TravisR to fix that.
|
||||
# - label: ":eslint: TS Lint"
|
||||
# command:
|
||||
# - "echo '--- Install js-sdk'"
|
||||
# - "./scripts/ci/install-deps.sh"
|
||||
# - "yarn lint:ts"
|
||||
# plugins:
|
||||
# - docker#v3.0.1:
|
||||
# image: "node:12"
|
||||
|
||||
- label: ":eslint: Types Lint"
|
||||
command:
|
||||
- "yarn install"
|
||||
- "yarn lint:types"
|
||||
plugins:
|
||||
- docker#v3.0.1:
|
||||
image: "node:12"
|
||||
|
||||
- label: "🛠 Build"
|
||||
command:
|
||||
- "echo '--- Fetching Dependencies'"
|
||||
- "./scripts/fetch-develop.deps.sh --depth 1"
|
||||
- "yarn install"
|
||||
- "echo '+++ Building Project'"
|
||||
- "yarn build"
|
||||
plugins:
|
||||
- docker#v3.0.1:
|
||||
image: "node:12"
|
||||
|
||||
- label: ":jest: Tests"
|
||||
agents:
|
||||
# We use a medium sized instance instead of the normal small ones because
|
||||
# webpack loves to gorge itself on resources.
|
||||
queue: "medium"
|
||||
command:
|
||||
# Install chrome
|
||||
- "echo '--- Installing Chrome'"
|
||||
- "wget -q -O - https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -"
|
||||
- "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'"
|
||||
- "apt-get update"
|
||||
- "apt-get install -y google-chrome-stable"
|
||||
# Run tests
|
||||
- "echo '--- Fetching Dependencies'"
|
||||
- "./scripts/fetch-develop.deps.sh --depth 1"
|
||||
- "yarn install"
|
||||
- "yarn build:genfiles" # We have to build the app to make sure the autogenned files are present
|
||||
- "echo '+++ Running Tests'"
|
||||
- "yarn test"
|
||||
env:
|
||||
CHROME_BIN: "/usr/bin/google-chrome-stable"
|
||||
plugins:
|
||||
- docker#v3.0.1:
|
||||
image: "node:10"
|
||||
propagate-environment: true
|
||||
|
||||
- label: ":hammer: Package"
|
||||
command:
|
||||
- "echo '--- Fetching Dependencies'"
|
||||
- "./scripts/fetch-develop.deps.sh --depth 1"
|
||||
- "yarn install"
|
||||
- "echo '+++ Packaging'"
|
||||
- "./scripts/ci_package.sh"
|
||||
branches: "develop"
|
||||
artifact_paths: "dist/riot-*.tar.gz"
|
||||
plugins:
|
||||
- docker#v3.0.1:
|
||||
image: "node:10"
|
||||
@@ -54,4 +63,20 @@ steps:
|
||||
- "yarn diff-i18n"
|
||||
plugins:
|
||||
- docker#v3.0.1:
|
||||
image: "node:10"
|
||||
image: "node:10"
|
||||
|
||||
- wait: ~ # this wait is to perform deploy to /develop only if all other steps passed
|
||||
continue_on_failure: false
|
||||
|
||||
- label: ":hammer: Package"
|
||||
command:
|
||||
- "echo '--- Fetching Dependencies'"
|
||||
- "./scripts/fetch-develop.deps.sh --depth 1"
|
||||
- "yarn install"
|
||||
- "echo '+++ Packaging'"
|
||||
- "./scripts/ci_package.sh"
|
||||
branches: "develop"
|
||||
artifact_paths: "dist/riot-*.tar.gz"
|
||||
plugins:
|
||||
- docker#v3.0.1:
|
||||
image: "node:10"
|
||||
|
||||
@@ -10,7 +10,14 @@
|
||||
"test/es5/specification",
|
||||
"test/css/objectfit",
|
||||
"test/storage/localstorage",
|
||||
"test/workers/webworkers",
|
||||
"test/indexeddb"
|
||||
"test/es6/array",
|
||||
"test/es6/collections",
|
||||
"test/es6/promises",
|
||||
"test/svg",
|
||||
"test/svg/asimg",
|
||||
"test/svg/filters",
|
||||
"test/css/animations",
|
||||
"test/css/filters",
|
||||
"test/network/fetch"
|
||||
]
|
||||
}
|
||||
|
||||
26
.stylelintrc.js
Normal file
26
.stylelintrc.js
Normal file
@@ -0,0 +1,26 @@
|
||||
// Copied from react-sdk
|
||||
// TODO: Only keep one copy of this for synchronization purposes
|
||||
module.exports = {
|
||||
"extends": "stylelint-config-standard",
|
||||
"plugins": [
|
||||
"stylelint-scss",
|
||||
],
|
||||
"rules": {
|
||||
"indentation": 4,
|
||||
"comment-empty-line-before": null,
|
||||
"declaration-empty-line-before": null,
|
||||
"length-zero-no-unit": null,
|
||||
"rule-empty-line-before": null,
|
||||
"color-hex-length": null,
|
||||
"max-empty-lines": null,
|
||||
"number-no-trailing-zeros": null,
|
||||
"number-leading-zero": null,
|
||||
"selector-list-comma-newline-after": null,
|
||||
"at-rule-no-unknown": null,
|
||||
"no-descending-specificity": null,
|
||||
"scss/at-rule-no-unknown": [true, {
|
||||
// https://github.com/vector-im/riot-web/issues/10544
|
||||
"ignoreAtRules": ["define-mixin"],
|
||||
}],
|
||||
}
|
||||
};
|
||||
182
CHANGELOG.md
182
CHANGELOG.md
@@ -1,3 +1,185 @@
|
||||
Changes in [1.5.9](https://github.com/vector-im/riot-web/releases/tag/v1.5.9) (2020-02-17)
|
||||
==========================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.9-rc.1...v1.5.9)
|
||||
|
||||
* Automate SDK dep upgrades for release
|
||||
[\#12374](https://github.com/vector-im/riot-web/pull/12374)
|
||||
|
||||
Changes in [1.5.9-rc.1](https://github.com/vector-im/riot-web/releases/tag/v1.5.9-rc.1) (2020-02-13)
|
||||
====================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.8...v1.5.9-rc.1)
|
||||
|
||||
* Upgrade JS SDK to 5.0.0-rc.1 and React SDK 2.1.0-rc.2
|
||||
* Update from Weblate
|
||||
[\#12354](https://github.com/vector-im/riot-web/pull/12354)
|
||||
* Add top left menu shortcut
|
||||
[\#12310](https://github.com/vector-im/riot-web/pull/12310)
|
||||
* Remove modernizr rules for features on which we only soft depend
|
||||
[\#12272](https://github.com/vector-im/riot-web/pull/12272)
|
||||
* Embed CSP meta tag and stop using script-src unsafe-inline
|
||||
[\#12258](https://github.com/vector-im/riot-web/pull/12258)
|
||||
* Add contribute.json
|
||||
[\#12251](https://github.com/vector-im/riot-web/pull/12251)
|
||||
* Improve Browser checks
|
||||
[\#12232](https://github.com/vector-im/riot-web/pull/12232)
|
||||
* Document padlock flag
|
||||
[\#12173](https://github.com/vector-im/riot-web/pull/12173)
|
||||
* Enable cross-signing on /develop
|
||||
[\#12126](https://github.com/vector-im/riot-web/pull/12126)
|
||||
* Switch back to legacy decorators
|
||||
[\#12110](https://github.com/vector-im/riot-web/pull/12110)
|
||||
* Update babel targets
|
||||
[\#12102](https://github.com/vector-im/riot-web/pull/12102)
|
||||
* Install deps for linting
|
||||
[\#12076](https://github.com/vector-im/riot-web/pull/12076)
|
||||
* Update from Weblate
|
||||
[\#12062](https://github.com/vector-im/riot-web/pull/12062)
|
||||
* Change to minimal Webpack output
|
||||
[\#12049](https://github.com/vector-im/riot-web/pull/12049)
|
||||
* Remove docs for new invite dialog labs feature
|
||||
[\#12015](https://github.com/vector-im/riot-web/pull/12015)
|
||||
* ElectronPlatform: Add the indexSize method.
|
||||
[\#11529](https://github.com/vector-im/riot-web/pull/11529)
|
||||
* ElectronPlatform: Add the ability to load file events from the event index
|
||||
[\#11907](https://github.com/vector-im/riot-web/pull/11907)
|
||||
* Fix the remainder of the cookie links
|
||||
[\#12008](https://github.com/vector-im/riot-web/pull/12008)
|
||||
* Use bash in Docker scripts
|
||||
[\#12001](https://github.com/vector-im/riot-web/pull/12001)
|
||||
* Use debian to build the Docker image
|
||||
[\#11999](https://github.com/vector-im/riot-web/pull/11999)
|
||||
* Update cookie policy urls on /app and /develop config.json
|
||||
[\#11998](https://github.com/vector-im/riot-web/pull/11998)
|
||||
* BuildKite: Only deploy to /develop if everything else passed
|
||||
[\#11996](https://github.com/vector-im/riot-web/pull/11996)
|
||||
* Add docs for admin report content message
|
||||
[\#11995](https://github.com/vector-im/riot-web/pull/11995)
|
||||
* Load as little as possible in index.js for the skinner
|
||||
[\#11959](https://github.com/vector-im/riot-web/pull/11959)
|
||||
* Fix webpack config (by stealing Dave's config)
|
||||
[\#11956](https://github.com/vector-im/riot-web/pull/11956)
|
||||
* Force Jest to resolve the js-sdk and react-sdk to src directories
|
||||
[\#11954](https://github.com/vector-im/riot-web/pull/11954)
|
||||
* Fix build to not babel modules inside js/react sdk
|
||||
[\#11949](https://github.com/vector-im/riot-web/pull/11949)
|
||||
* Fix webpack to babel js-sdk & react-sdk but no other deps
|
||||
[\#11944](https://github.com/vector-im/riot-web/pull/11944)
|
||||
|
||||
Changes in [1.5.8](https://github.com/vector-im/riot-web/releases/tag/v1.5.8) (2020-01-27)
|
||||
==========================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.8-rc.2...v1.5.8)
|
||||
|
||||
* Fixes for alias display and copy / paste on composer
|
||||
|
||||
Changes in [1.5.8-rc.2](https://github.com/vector-im/riot-web/releases/tag/v1.5.8-rc.2) (2020-01-22)
|
||||
====================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.8-rc.1...v1.5.8-rc.2)
|
||||
|
||||
* Fix incorrect version of react-sdk
|
||||
|
||||
Changes in [1.5.8-rc.1](https://github.com/vector-im/riot-web/releases/tag/v1.5.8-rc.1) (2020-01-22)
|
||||
====================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.7...v1.5.8-rc.1)
|
||||
|
||||
This version contains an upgrade to the cryptography database
|
||||
version. Once users run this version, their session's indexeddb
|
||||
store will be upgraded and older version of Riot will no longer
|
||||
be able to read it. Users will have to log out and log in if
|
||||
the version of Riot is downgraded back to a previous version.
|
||||
|
||||
* Fix webpack config (by stealing Dave's config)
|
||||
[\#11994](https://github.com/vector-im/riot-web/pull/11994)
|
||||
* Fix webpack to babel js-sdk & react-sdk but no other deps
|
||||
[\#11947](https://github.com/vector-im/riot-web/pull/11947)
|
||||
* Update from Weblate
|
||||
[\#11934](https://github.com/vector-im/riot-web/pull/11934)
|
||||
* Fix rageshake post-sourcemaps
|
||||
[\#11926](https://github.com/vector-im/riot-web/pull/11926)
|
||||
* Fix yarn start concurrent commands
|
||||
[\#11895](https://github.com/vector-im/riot-web/pull/11895)
|
||||
* Run the react-sdk reskindexer for developers
|
||||
[\#11894](https://github.com/vector-im/riot-web/pull/11894)
|
||||
* Update labs documentation for feature_ftue_dms given new scope
|
||||
[\#11893](https://github.com/vector-im/riot-web/pull/11893)
|
||||
* Fix indentation on webpack config and make sourcemapped files legible
|
||||
[\#11892](https://github.com/vector-im/riot-web/pull/11892)
|
||||
* Remove spinner check
|
||||
[\#11891](https://github.com/vector-im/riot-web/pull/11891)
|
||||
* Don't minifiy builds of develop through CI packaging
|
||||
[\#11867](https://github.com/vector-im/riot-web/pull/11867)
|
||||
* Use Jest for tests
|
||||
[\#11869](https://github.com/vector-im/riot-web/pull/11869)
|
||||
* Support application/wasm in Docker image
|
||||
[\#11858](https://github.com/vector-im/riot-web/pull/11858)
|
||||
* Fix sourcemaps by refactoring the build system
|
||||
[\#11843](https://github.com/vector-im/riot-web/pull/11843)
|
||||
* Disable event indexing on develop
|
||||
[\#11850](https://github.com/vector-im/riot-web/pull/11850)
|
||||
* Updated blog url
|
||||
[\#11792](https://github.com/vector-im/riot-web/pull/11792)
|
||||
* Enable and document presence in room list feature flag
|
||||
[\#11829](https://github.com/vector-im/riot-web/pull/11829)
|
||||
* Add stub service worker so users can install on desktop with Chrome
|
||||
[\#11774](https://github.com/vector-im/riot-web/pull/11774)
|
||||
* Update from Weblate
|
||||
[\#11826](https://github.com/vector-im/riot-web/pull/11826)
|
||||
* Sourcemaps: develop -> feature branch
|
||||
[\#11802](https://github.com/vector-im/riot-web/pull/11802)
|
||||
* Update build scripts for new process
|
||||
[\#11801](https://github.com/vector-im/riot-web/pull/11801)
|
||||
* Make the webpack config work for us
|
||||
[\#11712](https://github.com/vector-im/riot-web/pull/11712)
|
||||
* Updates URL for Electron Command Line Switches
|
||||
[\#11810](https://github.com/vector-im/riot-web/pull/11810)
|
||||
* Import from src/ for the react-sdk and js-sdk
|
||||
[\#11714](https://github.com/vector-im/riot-web/pull/11714)
|
||||
* Convert components to ES6 exports
|
||||
[\#11713](https://github.com/vector-im/riot-web/pull/11713)
|
||||
* Remove now-retired package.json property
|
||||
[\#11660](https://github.com/vector-im/riot-web/pull/11660)
|
||||
|
||||
Changes in [1.5.7](https://github.com/vector-im/riot-web/releases/tag/v1.5.7) (2020-01-13)
|
||||
==========================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.7-rc.2...v1.5.7)
|
||||
|
||||
* Enable and document presence in room list feature flag
|
||||
[\#11830](https://github.com/vector-im/riot-web/pull/11830)
|
||||
|
||||
Changes in [1.5.7-rc.2](https://github.com/vector-im/riot-web/releases/tag/v1.5.7-rc.2) (2020-01-08)
|
||||
====================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.7-rc.1...v1.5.7-rc.2)
|
||||
|
||||
* Update to react-sdk rc.2 to fix build
|
||||
|
||||
Changes in [1.5.7-rc.1](https://github.com/vector-im/riot-web/releases/tag/v1.5.7-rc.1) (2020-01-06)
|
||||
====================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.6...v1.5.7-rc.1)
|
||||
|
||||
* Update from Weblate
|
||||
[\#11784](https://github.com/vector-im/riot-web/pull/11784)
|
||||
* Add docs for feature_bridge_state flag
|
||||
[\#11778](https://github.com/vector-im/riot-web/pull/11778)
|
||||
* Add docs for feature_ftue_dms flag
|
||||
[\#11758](https://github.com/vector-im/riot-web/pull/11758)
|
||||
* Fix version file for Docker images
|
||||
[\#11721](https://github.com/vector-im/riot-web/pull/11721)
|
||||
* Add accelerators to context menu options like cut&paste in electron
|
||||
[\#11690](https://github.com/vector-im/riot-web/pull/11690)
|
||||
* electron-main: Provide a better error message if Seshat isn't installed.
|
||||
[\#11691](https://github.com/vector-im/riot-web/pull/11691)
|
||||
* Update from Weblate
|
||||
[\#11672](https://github.com/vector-im/riot-web/pull/11672)
|
||||
* Remove babel-plugin-transform-async-to-bluebird
|
||||
[\#11662](https://github.com/vector-im/riot-web/pull/11662)
|
||||
* Clarify which versions of what we support
|
||||
[\#11658](https://github.com/vector-im/riot-web/pull/11658)
|
||||
* Remove the code that calls the origin migrator
|
||||
[\#11631](https://github.com/vector-im/riot-web/pull/11631)
|
||||
* yarn upgrade
|
||||
[\#11617](https://github.com/vector-im/riot-web/pull/11617)
|
||||
* Remove draft-js dependency
|
||||
[\#11616](https://github.com/vector-im/riot-web/pull/11616)
|
||||
|
||||
Changes in [1.5.6](https://github.com/vector-im/riot-web/releases/tag/v1.5.6) (2019-12-09)
|
||||
==========================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.5.6-rc.1...v1.5.6)
|
||||
|
||||
11
Dockerfile
11
Dockerfile
@@ -1,5 +1,5 @@
|
||||
# Builder
|
||||
FROM node:10-alpine as builder
|
||||
FROM node:10 as builder
|
||||
|
||||
# Support custom branches of the react-sdk and js-sdk. This also helps us build
|
||||
# images of riot-web develop.
|
||||
@@ -9,12 +9,12 @@ ARG REACT_SDK_BRANCH="master"
|
||||
ARG JS_SDK_REPO="https://github.com/matrix-org/matrix-js-sdk.git"
|
||||
ARG JS_SDK_BRANCH="master"
|
||||
|
||||
RUN apk add --no-cache git dos2unix
|
||||
RUN apt-get update && apt-get install -y git dos2unix
|
||||
|
||||
WORKDIR /src
|
||||
|
||||
COPY . /src
|
||||
RUN dos2unix /src/scripts/docker-link-repos.sh && sh /src/scripts/docker-link-repos.sh
|
||||
RUN dos2unix /src/scripts/docker-link-repos.sh && bash /src/scripts/docker-link-repos.sh
|
||||
RUN yarn --network-timeout=100000 install
|
||||
RUN yarn build
|
||||
|
||||
@@ -22,7 +22,7 @@ RUN yarn build
|
||||
RUN cp /src/config.sample.json /src/webapp/config.json
|
||||
|
||||
# Ensure we populate the version file
|
||||
RUN dos2unix /src/scripts/docker-write-version.sh && sh /src/scripts/docker-write-version.sh
|
||||
RUN dos2unix /src/scripts/docker-write-version.sh && bash /src/scripts/docker-write-version.sh
|
||||
|
||||
|
||||
# App
|
||||
@@ -30,5 +30,8 @@ FROM nginx:alpine
|
||||
|
||||
COPY --from=builder /src/webapp /app
|
||||
|
||||
# Insert wasm type into Nginx mime.types file so they load correctly.
|
||||
RUN sed -i '3i\ \ \ \ application/wasm wasm\;' /etc/nginx/mime.types
|
||||
|
||||
RUN rm -rf /usr/share/nginx/html \
|
||||
&& ln -s /app /usr/share/nginx/html
|
||||
|
||||
@@ -3,8 +3,9 @@ Riot
|
||||
|
||||
Riot (formerly known as Vector) is a Matrix web client built using the [Matrix React SDK](https://github.com/matrix-org/matrix-react-sdk).
|
||||
|
||||
Riot is officially supported on the web in modern versions of Chrome, Firefox, and Safari. Other browsers may work, however
|
||||
official support is not provided. For accessing Riot on an Android or iOS device, check out [riot-android](https://github.com/vector-im/riot-android)
|
||||
Riot is officially supported on the web in the last 2 major versions of Chrome, Firefox, and Safari. For Riot on Desktop (electron),
|
||||
only the officially published app is supported. Other browsers and packages may work, however official support is not provided.
|
||||
For accessing Riot on an Android or iOS device, check out [riot-android](https://github.com/vector-im/riot-android)
|
||||
and [riot-ios](https://github.com/vector-im/riot-ios) - riot-web does not support mobile devices.
|
||||
|
||||
Getting Started
|
||||
|
||||
23
babel.config.js
Normal file
23
babel.config.js
Normal file
@@ -0,0 +1,23 @@
|
||||
module.exports = {
|
||||
"sourceMaps": true,
|
||||
"presets": [
|
||||
["@babel/preset-env", {
|
||||
"targets": [
|
||||
"last 2 Chrome versions", "last 2 Firefox versions", "last 2 Safari versions"
|
||||
],
|
||||
}],
|
||||
"@babel/preset-typescript",
|
||||
"@babel/preset-flow",
|
||||
"@babel/preset-react"
|
||||
],
|
||||
"plugins": [
|
||||
["@babel/plugin-proposal-decorators", {legacy: true}],
|
||||
"@babel/plugin-proposal-export-default-from",
|
||||
"@babel/plugin-proposal-numeric-separator",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-object-rest-spread",
|
||||
"@babel/plugin-transform-flow-comments",
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-transform-runtime"
|
||||
]
|
||||
};
|
||||
17
contribute.json
Normal file
17
contribute.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "Riot",
|
||||
"description": "A glossy Matrix collaboration client for the web.",
|
||||
"repository": {
|
||||
"url": "https://github.com/vector-im/riot-web",
|
||||
"license": "Apache License 2.0"
|
||||
},
|
||||
"bugs": {
|
||||
"list": "https://github.com/vector-im/riot-web/issues",
|
||||
"report": "https://github.com/vector-im/riot-web/issues/new/choose"
|
||||
},
|
||||
"keywords": [
|
||||
"chat",
|
||||
"riot",
|
||||
"matrix"
|
||||
]
|
||||
}
|
||||
@@ -37,6 +37,10 @@ For a good example, see https://riot.im/develop/config.json.
|
||||
authentication flows
|
||||
1. `authFooterLinks`: a list of links to show in the authentication page footer:
|
||||
`[{"text": "Link text", "url": "https://link.target"}, {"text": "Other link", ...}]`
|
||||
1. `reportEvent`: Configures the dialog for reporting content to the homeserver
|
||||
admin.
|
||||
1. `adminMessageMD`: An extra message to show on the reporting dialog to
|
||||
mention homeserver-specific policies. Accepts Markdown.
|
||||
1. `integrations_ui_url`: URL to the web interface for the integrations server. The integrations
|
||||
server is not Riot and normally not your homeserver either. The integration server settings
|
||||
may be left blank to disable integrations.
|
||||
|
||||
17
docs/labs.md
17
docs/labs.md
@@ -81,3 +81,20 @@ that downloads, stores, and indexes room messages for E2E encrypted rooms.
|
||||
|
||||
The existing search will transparently work for encrypted rooms just like it
|
||||
does for non-encrypted.
|
||||
|
||||
## Bridge info tab (`feature_bridge_state`)
|
||||
|
||||
Adds a "Bridge Info" tab to the Room Settings dialog, if a compatible bridge is
|
||||
present in the room. The Bridge info tab pulls information from the `m.bridge` state event ([MSC2346](https://github.com/matrix-org/matrix-doc/pull/2346)). Since the feature is based upon a MSC, most
|
||||
bridges are not expected to be compatible, and users should not rely on this
|
||||
tab as the single source of truth just yet.
|
||||
|
||||
## Presence indicator in room list (`feature_presence_in_room_list`)
|
||||
|
||||
This adds a presence indicator in the room list next to DM rooms where the other
|
||||
person is online.
|
||||
|
||||
## Show padlocks on invite only rooms (`feature_invite_only_padlocks`)
|
||||
|
||||
This adds padlocks to room list tiles and room header for invite only rooms.
|
||||
This feature flag (unlike most) is enabled by default.
|
||||
|
||||
@@ -47,7 +47,7 @@ Again from the `electron_app/` directory:
|
||||
|
||||
Recompiling Seshat itself can be done like so:
|
||||
|
||||
yarn run electron-build-env -- --electron 6.1.1 -- neon build matrix-seshat --release`
|
||||
yarn run electron-build-env -- --electron 6.1.1 -- neon build matrix-seshat --release
|
||||
|
||||
Please make sure to include all the `--` as well as the `--release` command line
|
||||
switch at the end. Modify your electron version accordingly depending on the
|
||||
@@ -56,6 +56,5 @@ version that is installed on your system.
|
||||
After this is done the Electron version of Riot can be run from the main folder
|
||||
as usual using:
|
||||
|
||||
yarn build
|
||||
yarn electron
|
||||
|
||||
|
||||
@@ -11,3 +11,4 @@ The modifier is <kbd>Ctrl</kbd> on Windows & Linux and <kbd>⌘</kbd> on Mac.
|
||||
- <kbd>Alt</kbd>+<kbd>↑</kbd>/<kbd>↓</kbd> - resend previous messages when the composer is in focus
|
||||
- <kbd>PageUp</kbd>/<kbd>PageDown</kbd> - scroll timeline up/down
|
||||
- <kbd>Ctrl</kbd>/<kbd>⌘</kbd>+<kbd>Home</kbd>/<kbd>End</kbd> - jump to timeline start/end
|
||||
- <kbd>Ctrl</kbd>/<kbd>⌘</kbd>+<kbd>`</kbd> - toggle the top left menu
|
||||
|
||||
@@ -9,6 +9,9 @@
|
||||
Latest electron-builder does, but it appears to be causing issues:
|
||||
(https://github.com/electron-userland/electron-builder/issues/4390)
|
||||
-->
|
||||
<!-- https://github.com/electron/electron-notarize#prerequisites -->
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<!-- https://github.com/electron-userland/electron-builder/issues/3940 -->
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Link to the binary
|
||||
ln -sf '/opt/${productFilename}/${executable}' '/usr/bin/${executable}'
|
||||
|
||||
# SUID chrome-sandbox for Electron 5+
|
||||
# Remove this entire file (after-install.tpl) and remove the reference in
|
||||
# package.json once this change has been upstreamed so we go back to the copy
|
||||
# from upstream.
|
||||
# https://github.com/electron-userland/electron-builder/pull/4163
|
||||
chmod 4755 '/opt/${productFilename}/chrome-sandbox' || true
|
||||
|
||||
update-mime-database /usr/share/mime || true
|
||||
update-desktop-database /usr/share/applications || true
|
||||
@@ -2,7 +2,7 @@
|
||||
"name": "riot-web",
|
||||
"productName": "Riot",
|
||||
"main": "src/electron-main.js",
|
||||
"version": "1.5.6",
|
||||
"version": "1.5.9",
|
||||
"description": "A feature-rich client for Matrix.org",
|
||||
"author": "New Vector Ltd.",
|
||||
"dependencies": {
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"piwik": {
|
||||
"url": "https://piwik.riot.im/",
|
||||
"siteId": 1,
|
||||
"policyUrl": "https://matrix.org/docs/guides/riot_im_cookie_policy"
|
||||
"policyUrl": "https://matrix.org/legal/riot-im-cookie-policy"
|
||||
},
|
||||
"phasedRollOut": {
|
||||
"feature_lazyloading": {
|
||||
|
||||
@@ -35,7 +35,6 @@ const tray = require('./tray');
|
||||
const vectorMenu = require('./vectormenu');
|
||||
const webContentsHandler = require('./webcontents-handler');
|
||||
const updater = require('./updater');
|
||||
const { migrateFromOldOrigin } = require('./originMigrator');
|
||||
|
||||
const windowStateKeeper = require('electron-window-state');
|
||||
const Store = require('electron-store');
|
||||
@@ -48,7 +47,11 @@ let Seshat = null;
|
||||
try {
|
||||
Seshat = require('matrix-seshat');
|
||||
} catch (e) {
|
||||
console.warn("seshat unavailable", e);
|
||||
if (e.code === "MODULE_NOT_FOUND") {
|
||||
console.log("Seshat isn't installed, event indexing is disabled.");
|
||||
} else {
|
||||
console.warn("Seshat unexpected error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
if (argv["help"]) {
|
||||
@@ -60,15 +63,10 @@ if (argv["help"]) {
|
||||
console.log(" --hidden: Start the application hidden in the system tray.");
|
||||
console.log(" --help: Displays this help message.");
|
||||
console.log("And more such as --proxy, see:" +
|
||||
"https://github.com/electron/electron/blob/master/docs/api/chrome-command-line-switches.md");
|
||||
"https://electronjs.org/docs/api/chrome-command-line-switches#supported-chrome-command-line-switches");
|
||||
app.exit();
|
||||
}
|
||||
|
||||
// boolean flag set whilst we are doing one-time origin migration
|
||||
// We only serve the origin migration script while we're actually
|
||||
// migrating to mitigate any risk of it being used maliciously.
|
||||
let migratingOrigin = false;
|
||||
|
||||
if (argv['profile-dir']) {
|
||||
app.setPath('userData', argv['profile-dir']);
|
||||
} else if (argv['profile']) {
|
||||
@@ -231,11 +229,6 @@ ipcMain.on('ipcCall', async function(ev, payload) {
|
||||
mainWindow.focus();
|
||||
}
|
||||
break;
|
||||
case 'origin_migrate':
|
||||
migratingOrigin = true;
|
||||
await migrateFromOldOrigin();
|
||||
migratingOrigin = false;
|
||||
break;
|
||||
case 'getConfig':
|
||||
ret = vectorConfig;
|
||||
break;
|
||||
@@ -353,6 +346,18 @@ ipcMain.on('seshat', async function(ev, payload) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'getStats':
|
||||
if (eventIndex === null) ret = 0;
|
||||
else {
|
||||
try {
|
||||
ret = await eventIndex.getStats();
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'removeCrawlerCheckpoint':
|
||||
if (eventIndex === null) ret = false;
|
||||
else {
|
||||
@@ -377,6 +382,18 @@ ipcMain.on('seshat', async function(ev, payload) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'loadFileEvents':
|
||||
if (eventIndex === null) ret = [];
|
||||
else {
|
||||
try {
|
||||
ret = await eventIndex.loadFileEvents(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'loadCheckpoints':
|
||||
if (eventIndex === null) ret = [];
|
||||
else {
|
||||
@@ -477,13 +494,7 @@ app.on('ready', () => {
|
||||
|
||||
let baseDir;
|
||||
// first part of the path determines where we serve from
|
||||
if (migratingOrigin && target[1] === 'origin_migrator_dest') {
|
||||
// the origin migrator destination page
|
||||
// (only the destination script needs to come from the
|
||||
// custom protocol: the source part is loaded from a
|
||||
// file:// as that's the origin we're migrating from).
|
||||
baseDir = __dirname + "/../../origin_migrator/dest";
|
||||
} else if (target[1] === 'webapp') {
|
||||
if (target[1] === 'webapp') {
|
||||
baseDir = __dirname + "/../../webapp";
|
||||
} else {
|
||||
callback({error: -6}); // FILE_NOT_FOUND
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 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.
|
||||
*/
|
||||
|
||||
const { BrowserWindow, ipcMain } = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
async function migrateFromOldOrigin() {
|
||||
console.log("Attempting to migrate data between origins");
|
||||
|
||||
// We can use the same preload script: we just need ipcRenderer exposed
|
||||
const preloadScript = path.normalize(`${__dirname}/preload.js`);
|
||||
await new Promise(resolve => {
|
||||
const migrateWindow = new BrowserWindow({
|
||||
show: false,
|
||||
webPreferences: {
|
||||
preload: preloadScript,
|
||||
nodeIntegration: false,
|
||||
sandbox: true,
|
||||
enableRemoteModule: false,
|
||||
webgl: false,
|
||||
},
|
||||
});
|
||||
const onOriginMigrationComplete = (e, success, sentSummary, storedSummary) => {
|
||||
// we use once but we'll only get one of these events,
|
||||
// so remove the listener for the other one
|
||||
ipcMain.removeListener('origin_migration_nodata', onOriginMigrationNoData);
|
||||
|
||||
if (success) {
|
||||
console.log("Origin migration completed successfully!");
|
||||
} else {
|
||||
console.error("Origin migration failed!");
|
||||
}
|
||||
console.error("Data sent", sentSummary);
|
||||
console.error("Data stored", storedSummary);
|
||||
migrateWindow.close();
|
||||
resolve();
|
||||
};
|
||||
const onOriginMigrationNoData = (e, success, sentSummary, storedSummary) => {
|
||||
ipcMain.removeListener('origin_migration_complete', onOriginMigrationComplete);
|
||||
|
||||
console.log("No session to migrate from old origin");
|
||||
migrateWindow.close();
|
||||
resolve();
|
||||
};
|
||||
|
||||
ipcMain.once('origin_migration_complete', onOriginMigrationComplete);
|
||||
ipcMain.once('origin_migration_nodata', onOriginMigrationNoData);
|
||||
|
||||
// Normalise the path because in the distribution, __dirname will be inside the
|
||||
// electron asar.
|
||||
const sourcePagePath = path.normalize(__dirname + '/../../origin_migrator/source.html');
|
||||
console.log("Loading path: " + sourcePagePath);
|
||||
migrateWindow.loadURL('file://' + sourcePagePath);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
migrateFromOldOrigin,
|
||||
};
|
||||
@@ -56,7 +56,7 @@ function onLinkContextMenu(ev, params) {
|
||||
let addSaveAs = false;
|
||||
if (params.mediaType && params.mediaType === 'image' && !url.startsWith('file://')) {
|
||||
popupMenu.append(new MenuItem({
|
||||
label: 'Copy image',
|
||||
label: '&Copy image',
|
||||
click() {
|
||||
if (url.startsWith('data:')) {
|
||||
clipboard.writeImage(nativeImage.createFromDataURL(url));
|
||||
@@ -76,14 +76,14 @@ function onLinkContextMenu(ev, params) {
|
||||
// Special-case e-mail URLs to strip the `mailto:` like modern browsers do
|
||||
if (url.startsWith(MAILTO_PREFIX)) {
|
||||
popupMenu.append(new MenuItem({
|
||||
label: 'Copy email address',
|
||||
label: 'Copy email &address',
|
||||
click() {
|
||||
clipboard.writeText(url.substr(MAILTO_PREFIX.length));
|
||||
},
|
||||
}));
|
||||
} else {
|
||||
popupMenu.append(new MenuItem({
|
||||
label: 'Copy link address',
|
||||
label: 'Copy link &address',
|
||||
click() {
|
||||
clipboard.writeText(url);
|
||||
},
|
||||
@@ -93,7 +93,7 @@ function onLinkContextMenu(ev, params) {
|
||||
|
||||
if (addSaveAs) {
|
||||
popupMenu.append(new MenuItem({
|
||||
label: 'Save image as...',
|
||||
label: 'Sa&ve image as...',
|
||||
click() {
|
||||
const targetFileName = params.titleText || "image.png";
|
||||
const filePath = dialog.showSaveDialog({
|
||||
@@ -128,18 +128,22 @@ function onLinkContextMenu(ev, params) {
|
||||
function _CutCopyPasteSelectContextMenus(params) {
|
||||
return [{
|
||||
role: 'cut',
|
||||
label: 'Cu&t',
|
||||
enabled: params.editFlags.canCut,
|
||||
}, {
|
||||
role: 'copy',
|
||||
label: '&Copy',
|
||||
enabled: params.editFlags.canCopy,
|
||||
}, {
|
||||
role: 'paste',
|
||||
label: '&Paste',
|
||||
enabled: params.editFlags.canPaste,
|
||||
}, {
|
||||
role: 'pasteandmatchstyle',
|
||||
enabled: params.editFlags.canPaste,
|
||||
}, {
|
||||
role: 'selectall',
|
||||
label: "Select &All",
|
||||
enabled: params.editFlags.canSelectAll,
|
||||
}];
|
||||
}
|
||||
|
||||
178
karma.conf.js
178
karma.conf.js
@@ -1,178 +0,0 @@
|
||||
// karma.conf.js - the config file for karma, which runs our tests.
|
||||
|
||||
var path = require('path');
|
||||
var webpack = require('webpack');
|
||||
var webpack_config = require('./webpack.config');
|
||||
|
||||
/*
|
||||
* We use webpack to build our tests. It's a pain to have to wait for webpack
|
||||
* to build everything; however it's the easiest way to load our dependencies
|
||||
* from node_modules.
|
||||
*
|
||||
* If you run karma in multi-run mode (with `yarn test-multi`), it will watch
|
||||
* the tests for changes, and webpack will rebuild using a cache. This is much quicker
|
||||
* than a clean rebuild.
|
||||
*/
|
||||
|
||||
// the name of the test file. By default, a special file which runs all tests.
|
||||
var testFile = process.env.KARMA_TEST_FILE || 'test/all-tests.js';
|
||||
|
||||
process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs';
|
||||
process.env.Q_DEBUG = 1;
|
||||
|
||||
/* the webpack config is based on the real one, to (a) try to simulate the
|
||||
* deployed environment as closely as possible, and (b) to avoid a shedload of
|
||||
* cut-and-paste.
|
||||
*/
|
||||
|
||||
// find out if we're shipping olm, and where it is, if so.
|
||||
const olm_entry = webpack_config.entry['olm'];
|
||||
|
||||
// remove the default entries - karma provides its own (via the 'files' and
|
||||
// 'preprocessors' config below)
|
||||
delete webpack_config['entry'];
|
||||
|
||||
// make sure we're flagged as development to avoid wasting time optimising
|
||||
webpack_config.mode = 'development';
|
||||
|
||||
// add ./test as a search path for js
|
||||
webpack_config.module.rules.unshift({
|
||||
test: /\.js$/, use: "babel-loader",
|
||||
include: [path.resolve('./src'), path.resolve('./test')],
|
||||
});
|
||||
|
||||
// disable parsing for sinon, because it
|
||||
// tries to do voodoo with 'require' which upsets
|
||||
// webpack (https://github.com/webpack/webpack/issues/304)
|
||||
webpack_config.module.noParse.push(/sinon\/pkg\/sinon\.js$/);
|
||||
|
||||
// ?
|
||||
webpack_config.resolve.alias['sinon'] = 'sinon/pkg/sinon.js';
|
||||
|
||||
webpack_config.resolve.modules = [
|
||||
path.resolve('./test'),
|
||||
"node_modules"
|
||||
];
|
||||
|
||||
webpack_config.devtool = 'inline-source-map';
|
||||
|
||||
module.exports = function (config) {
|
||||
const myconfig = {
|
||||
// frameworks to use
|
||||
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
|
||||
frameworks: ['mocha'],
|
||||
|
||||
// list of files / patterns to load in the browser
|
||||
files: [
|
||||
'node_modules/babel-polyfill/browser.js',
|
||||
testFile,
|
||||
|
||||
// make the images available via our httpd. They will be avaliable
|
||||
// below http://localhost:[PORT]/base/. See also `proxies` which
|
||||
// defines alternative URLs for them.
|
||||
//
|
||||
// This isn't required by any of the tests, but it stops karma
|
||||
// logging warnings when it serves a 404 for them.
|
||||
{
|
||||
pattern: 'node_modules/matrix-react-sdk/res/img/*',
|
||||
watched: false, included: false, served: true, nocache: false,
|
||||
},
|
||||
{
|
||||
pattern: 'res/**',
|
||||
watched: false, included: false, served: true, nocache: false,
|
||||
},
|
||||
],
|
||||
|
||||
proxies: {
|
||||
// redirect img links to the karma server. See above.
|
||||
"/img/": "/base/node_modules/matrix-react-sdk/res/img/",
|
||||
"/themes/": "/base/res/themes/",
|
||||
"/welcome.html": "/base/res/welcome.html",
|
||||
"/welcome/": "/base/res/welcome/",
|
||||
},
|
||||
|
||||
// preprocess matching files before serving them to the browser
|
||||
// available preprocessors:
|
||||
// https://npmjs.org/browse/keyword/karma-preprocessor
|
||||
preprocessors: {
|
||||
'{src,test}/**/*.js': ['webpack', 'sourcemap'],
|
||||
},
|
||||
|
||||
// test results reporter to use
|
||||
// available reporters: https://npmjs.org/browse/keyword/karma-reporter
|
||||
reporters: ['logcapture', 'spec', 'summary'],
|
||||
|
||||
specReporter: {
|
||||
suppressErrorSummary: false, // do print error summary
|
||||
suppressFailed: false, // do print information about failed tests
|
||||
suppressPassed: false, // do print information about passed tests
|
||||
showSpecTiming: true, // print the time elapsed for each spec
|
||||
},
|
||||
|
||||
client: {
|
||||
captureLogs: true,
|
||||
},
|
||||
|
||||
// web server port
|
||||
port: 9876,
|
||||
|
||||
// enable / disable colors in the output (reporters and logs)
|
||||
colors: true,
|
||||
|
||||
// level of logging
|
||||
// possible values: config.LOG_DISABLE || config.LOG_ERROR ||
|
||||
// config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
|
||||
logLevel: config.LOG_INFO,
|
||||
|
||||
// enable / disable watching file and executing tests whenever any file
|
||||
// changes
|
||||
autoWatch: true,
|
||||
|
||||
// start these browsers
|
||||
// available browser launchers:
|
||||
// https://npmjs.org/browse/keyword/karma-launcher
|
||||
browsers: [
|
||||
'Chrome',
|
||||
//'PhantomJS',
|
||||
//'ChromeHeadless'
|
||||
],
|
||||
|
||||
customLaunchers: {
|
||||
'VectorChromeHeadless': {
|
||||
base: 'Chrome',
|
||||
flags: [
|
||||
'--no-sandbox',
|
||||
// See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
|
||||
'--headless',
|
||||
'--disable-gpu',
|
||||
// Without a remote debugging port, Google Chrome exits immediately.
|
||||
'--remote-debugging-port=9222',
|
||||
],
|
||||
}
|
||||
},
|
||||
|
||||
// Continuous Integration mode
|
||||
// if true, Karma captures browsers, runs the tests and exits
|
||||
// singleRun: false,
|
||||
|
||||
// Concurrency level
|
||||
// how many browser should be started simultaneous
|
||||
concurrency: Infinity,
|
||||
|
||||
webpack: webpack_config,
|
||||
|
||||
webpackMiddleware: {
|
||||
stats: {
|
||||
// don't fill the console up with a mahoosive list of modules
|
||||
chunks: false,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// include the olm loader if we have it.
|
||||
if (olm_entry) {
|
||||
myconfig.files.unshift(olm_entry);
|
||||
}
|
||||
|
||||
config.set(myconfig);
|
||||
};
|
||||
19
origin_migrator/dest/browser-matrix.min.js
vendored
19
origin_migrator/dest/browser-matrix.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -1,6 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<script src="browser-matrix.min.js"></script>
|
||||
<script src="dest.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 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.
|
||||
*/
|
||||
|
||||
const SOURCE_ORIGIN = 'file://';
|
||||
|
||||
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
|
||||
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
|
||||
|
||||
let accountStored = 0;
|
||||
let sessionsStored = 0;
|
||||
let inboundGroupSessionsStored = 0;
|
||||
let deviceDataStored = 0;
|
||||
let roomsStored = 0;
|
||||
let localStorageKeysStored = 0;
|
||||
|
||||
const promises = [];
|
||||
|
||||
async function onMessage(e) {
|
||||
if (e.origin !== SOURCE_ORIGIN) return;
|
||||
|
||||
const data = e.data.data; // bleh, naming clash
|
||||
switch (e.data.cmd) {
|
||||
case 'init':
|
||||
// start with clean stores before we migrate data in
|
||||
window.localStorage.clear();
|
||||
await cryptoStore.deleteAllData();
|
||||
|
||||
e.source.postMessage({
|
||||
cmd: 'initOK',
|
||||
}, SOURCE_ORIGIN);
|
||||
break;
|
||||
case 'storeAccount':
|
||||
promises.push(cryptoStore.doTxn(
|
||||
'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT],
|
||||
(txn) => {
|
||||
cryptoStore.storeAccount(txn, data);
|
||||
},
|
||||
).then(() => {
|
||||
++accountStored;
|
||||
}));
|
||||
break;
|
||||
case 'storeSessions':
|
||||
promises.push(cryptoStore.doTxn(
|
||||
'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS],
|
||||
(txn) => {
|
||||
for (const sess of data) {
|
||||
cryptoStore.storeEndToEndSession(sess.deviceKey, sess.sessionId, sess, txn);
|
||||
}
|
||||
},
|
||||
).then(() => {
|
||||
sessionsStored += data.length;
|
||||
}));
|
||||
break;
|
||||
case 'storeInboundGroupSessions':
|
||||
promises.push(cryptoStore.doTxn(
|
||||
'readwrite', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
|
||||
(txn) => {
|
||||
for (const sess of data) {
|
||||
cryptoStore.addEndToEndInboundGroupSession(
|
||||
sess.senderKey, sess.sessionId, sess.sessionData, txn,
|
||||
);
|
||||
}
|
||||
},
|
||||
).then(() => {
|
||||
inboundGroupSessionsStored += data.length;
|
||||
}));
|
||||
break;
|
||||
case 'storeDeviceData':
|
||||
promises.push(cryptoStore.doTxn(
|
||||
'readwrite', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
|
||||
(txn) => {
|
||||
cryptoStore.storeEndToEndDeviceData(data, txn);
|
||||
},
|
||||
).then(() => {
|
||||
++deviceDataStored;
|
||||
}));
|
||||
break;
|
||||
case 'storeRooms':
|
||||
promises.push(cryptoStore.doTxn(
|
||||
'readwrite', [IndexedDBCryptoStore.STORE_ROOMS],
|
||||
(txn) => {
|
||||
for (const [roomId, roomInfo] of Object.entries(data)) {
|
||||
cryptoStore.storeEndToEndRoom(roomId, roomInfo, txn);
|
||||
}
|
||||
},
|
||||
).then(() => {
|
||||
++roomsStored;
|
||||
}));
|
||||
break;
|
||||
case 'storeLocalStorage':
|
||||
window.localStorage.setItem(data.key, data.val);
|
||||
++localStorageKeysStored;
|
||||
break;
|
||||
case 'getSummary':
|
||||
await Promise.all(promises);
|
||||
e.source.postMessage({
|
||||
cmd: 'summary',
|
||||
data: {
|
||||
accountStored,
|
||||
sessionsStored,
|
||||
inboundGroupSessionsStored,
|
||||
deviceDataStored,
|
||||
roomsStored,
|
||||
localStorageKeysStored,
|
||||
},
|
||||
}, SOURCE_ORIGIN);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
window.addEventListener('message', onMessage);
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<script src="dest/browser-matrix.min.js"></script>
|
||||
<script src="source.js"></script>
|
||||
<iframe name="dest" src="vector://vector/origin_migrator_dest/dest.html" onload="doMigrate()"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,210 +0,0 @@
|
||||
/*
|
||||
Copyright 2018 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.
|
||||
*/
|
||||
|
||||
const TARGET_ORIGIN = 'vector://vector';
|
||||
const BATCH_SIZE = 500;
|
||||
let destFrame;
|
||||
|
||||
let initResolver = null;
|
||||
let getSummaryResolver = null;
|
||||
|
||||
function onMessage(e) {
|
||||
if (e.origin !== TARGET_ORIGIN) return;
|
||||
|
||||
if (e.data.cmd === 'initOK' && initResolver) {
|
||||
initResolver();
|
||||
initResolver = null;
|
||||
} else if (e.data.cmd === 'summary' && getSummaryResolver) {
|
||||
getSummaryResolver(e.data.data);
|
||||
getSummaryResolver = null;
|
||||
}
|
||||
}
|
||||
|
||||
async function initDestFrame() {
|
||||
return new Promise(resolve => {
|
||||
initResolver = resolve;
|
||||
destFrame.postMessage({
|
||||
cmd: 'init',
|
||||
}, TARGET_ORIGIN);
|
||||
});
|
||||
}
|
||||
|
||||
async function getSummary() {
|
||||
return new Promise(resolve => {
|
||||
getSummaryResolver = resolve;
|
||||
destFrame.postMessage({
|
||||
cmd: 'getSummary',
|
||||
}, TARGET_ORIGIN);
|
||||
});
|
||||
}
|
||||
|
||||
async function doMigrate() {
|
||||
let accountSent = 0;
|
||||
let sessionsSent = 0;
|
||||
let inboundGroupSessionsSent = 0;
|
||||
let deviceDataSent = 0;
|
||||
let roomsSent = 0;
|
||||
let localStorageKeysSent = 0;
|
||||
|
||||
if (!window.ipcRenderer) {
|
||||
console.error("ipcRenderer not found");
|
||||
return;
|
||||
}
|
||||
|
||||
if (window.localStorage.getItem('mx_user_id') === null) {
|
||||
window.ipcRenderer.send("origin_migration_nodata");
|
||||
return;
|
||||
}
|
||||
|
||||
destFrame = window.parent.frames.dest;
|
||||
|
||||
await initDestFrame();
|
||||
|
||||
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
|
||||
|
||||
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
|
||||
|
||||
await cryptoStore.doTxn(
|
||||
'readonly', [IndexedDBCryptoStore.STORE_ACCOUNT],
|
||||
(txn) => {
|
||||
cryptoStore.getAccount(txn, (account) => {
|
||||
destFrame.postMessage({
|
||||
cmd: 'storeAccount',
|
||||
data: account,
|
||||
}, TARGET_ORIGIN);
|
||||
++accountSent;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
await cryptoStore.doTxn(
|
||||
'readonly', [IndexedDBCryptoStore.STORE_SESSIONS],
|
||||
(txn) => {
|
||||
let sessBatch = [];
|
||||
cryptoStore.getAllEndToEndSessions(txn, (sessInfo) => {
|
||||
if (sessInfo) {
|
||||
++sessionsSent;
|
||||
sessBatch.push(sessInfo);
|
||||
}
|
||||
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
|
||||
destFrame.postMessage({
|
||||
cmd: 'storeSessions',
|
||||
data: sessBatch,
|
||||
}, TARGET_ORIGIN);
|
||||
sessBatch = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
await cryptoStore.doTxn(
|
||||
'readonly', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
|
||||
(txn) => {
|
||||
let sessBatch = [];
|
||||
cryptoStore.getAllEndToEndInboundGroupSessions(txn, (sessInfo) => {
|
||||
if (sessInfo) {
|
||||
++inboundGroupSessionsSent;
|
||||
sessBatch.push(sessInfo);
|
||||
}
|
||||
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
|
||||
destFrame.postMessage({
|
||||
cmd: 'storeInboundGroupSessions',
|
||||
data: sessBatch,
|
||||
}, TARGET_ORIGIN);
|
||||
sessBatch = [];
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
await cryptoStore.doTxn(
|
||||
'readonly', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
|
||||
(txn) => {
|
||||
cryptoStore.getEndToEndDeviceData(txn, (deviceData) => {
|
||||
destFrame.postMessage({
|
||||
cmd: 'storeDeviceData',
|
||||
data: deviceData,
|
||||
}, TARGET_ORIGIN);
|
||||
++deviceDataSent;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
await cryptoStore.doTxn(
|
||||
'readonly', [IndexedDBCryptoStore.STORE_ROOMS],
|
||||
(txn) => {
|
||||
cryptoStore.getEndToEndRooms(txn, (rooms) => {
|
||||
destFrame.postMessage({
|
||||
cmd: 'storeRooms',
|
||||
data: rooms,
|
||||
}, TARGET_ORIGIN);
|
||||
++roomsSent;
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
// we don't bother migrating;
|
||||
// * sync data (we can just initialsync again)
|
||||
// * logs
|
||||
// * key requests (worst case they'll just be re-sent)
|
||||
// * sessions needing backup (feature isn't available on Electron)
|
||||
|
||||
for (let i = 0; i < window.localStorage.length; ++i) {
|
||||
const key = window.localStorage.key(i);
|
||||
const val = window.localStorage.getItem(key);
|
||||
|
||||
destFrame.postMessage({
|
||||
cmd: 'storeLocalStorage',
|
||||
data: { key, val },
|
||||
}, TARGET_ORIGIN);
|
||||
++localStorageKeysSent;
|
||||
}
|
||||
|
||||
const summary = await getSummary();
|
||||
let success = false;
|
||||
if (
|
||||
summary.accountStored === accountSent &&
|
||||
summary.sessionsStored === sessionsSent &&
|
||||
summary.inboundGroupSessionsStored === inboundGroupSessionsSent &&
|
||||
summary.deviceDataStored === deviceDataSent &&
|
||||
summary.roomsStored === roomsSent &&
|
||||
summary.localStorageKeysStored === localStorageKeysSent
|
||||
) {
|
||||
success = true;
|
||||
window.localStorage.clear();
|
||||
await cryptoStore.deleteAllData();
|
||||
|
||||
// we don't bother migrating them, but also blow away the sync & logs db,
|
||||
// otherwise they'll just hang about taking up space
|
||||
await new Promise(resolve => {
|
||||
const req = window.indexedDB.deleteDatabase('matrix-js-sdk:riot-web-sync');
|
||||
req.onsuccess = resolve;
|
||||
req.onerror = resolve;
|
||||
});
|
||||
await new Promise(resolve => {
|
||||
const req = window.indexedDB.deleteDatabase('logs');
|
||||
req.onsuccess = resolve;
|
||||
req.onerror = resolve;
|
||||
});
|
||||
}
|
||||
|
||||
window.ipcRenderer.send("origin_migration_complete", success, {
|
||||
accountSent, sessionsSent, inboundGroupSessionsSent,
|
||||
deviceDataSent, roomsSent, localStorageKeysSent,
|
||||
}, summary);
|
||||
}
|
||||
|
||||
window.addEventListener('message', onMessage);
|
||||
202
package.json
202
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "riot-web",
|
||||
"productName": "Riot",
|
||||
"main": "electron_app/src/electron-main.js",
|
||||
"version": "1.5.6",
|
||||
"version": "1.5.9",
|
||||
"description": "A feature-rich client for Matrix.org",
|
||||
"author": "New Vector Ltd.",
|
||||
"repository": {
|
||||
@@ -11,72 +11,63 @@
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"files": [
|
||||
"AUTHORS.rst",
|
||||
"CONTRIBUTING.rst",
|
||||
"deploy",
|
||||
"docs",
|
||||
"karma.conf.js",
|
||||
"lib",
|
||||
"release.sh",
|
||||
"scripts",
|
||||
"res",
|
||||
"src",
|
||||
"test",
|
||||
"webpack.config.js"
|
||||
"webpack.config.js",
|
||||
"scripts",
|
||||
"docs",
|
||||
"release.sh",
|
||||
"deploy",
|
||||
"CHANGELOG.md",
|
||||
"CONTRIBUTING.rst",
|
||||
"LICENSE",
|
||||
"README.md",
|
||||
"AUTHORS.rst",
|
||||
"package.json",
|
||||
"contribute.json"
|
||||
],
|
||||
"style": "bundle.css",
|
||||
"matrix-react-parent": "matrix-react-sdk",
|
||||
"scripts": {
|
||||
"reskindex": "reskindex -h src/header",
|
||||
"reskindex:watch": "reskindex -h src/header -w",
|
||||
"i18n": "matrix-gen-i18n",
|
||||
"prunei18n": "matrix-prune-i18n",
|
||||
"diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && yarn i18n && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
|
||||
"reskindex": "reskindex -h src/header",
|
||||
"reskindex:watch": "reskindex -h src/header -w",
|
||||
"reskindex:watch-react": "node scripts/yarn-sub.js matrix-react-sdk reskindex:watch",
|
||||
"clean": "rimraf lib webapp electron_app/dist",
|
||||
"build": "yarn clean && yarn build:genfiles && yarn build:compile && yarn build:types && yarn build:bundle",
|
||||
"build:res": "node scripts/copy-res.js",
|
||||
"build:genfiles": "yarn reskindex && yarn build:res",
|
||||
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
|
||||
"build:compile": "yarn reskindex && babel --source-maps -d lib src",
|
||||
"build:compile": "babel -d lib --verbose --extensions \".ts,.js\" src",
|
||||
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production",
|
||||
"build:bundle:dev": "webpack --progress --bail --mode development",
|
||||
"build:electron": "yarn clean && yarn build && yarn install:electron && electron-builder -wml --ia32 --x64",
|
||||
"build:electron": "yarn build && yarn install:electron && electron-builder -wml --ia32 --x64",
|
||||
"build:electron:linux": "yarn build && electron-builder -l --x64",
|
||||
"build:electron:macos": "yarn build && electron-builder -m --x64",
|
||||
"build:electron:windows": "yarn build && electron-builder -w --ia32 --x64",
|
||||
"build:react-sdk": "node scripts/yarn-sub.js matrix-react-sdk build",
|
||||
"build:js-sdk": "node scripts/yarn-sub.js matrix-js-sdk start:init",
|
||||
"build": "yarn build:js-sdk && yarn build:react-sdk && yarn reskindex && yarn build:res && yarn build:bundle",
|
||||
"build:dev": "yarn build:js-sdk && yarn build:react-sdk && yarn reskindex && yarn build:res && yarn build:bundle:dev",
|
||||
"dist": "scripts/package.sh",
|
||||
"build:types": "tsc --emitDeclarationOnly",
|
||||
"install:electron": "electron-builder install-app-deps",
|
||||
"electron": "yarn install:electron && electron .",
|
||||
"dist": "scripts/package.sh",
|
||||
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n reskindex,reskindex-react,res,riot-js \"yarn reskindex:watch\" \"yarn reskindex:watch-react\" \"yarn start:res\" \"yarn start:js\"",
|
||||
"start:res": "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",
|
||||
"start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress --mode production",
|
||||
"start:js-sdk": "node scripts/yarn-sub.js matrix-js-sdk start:watch",
|
||||
"start:js-sdk:prod": "cross-env NODE_ENV=production node scripts/yarn-sub.js matrix-js-sdk start:watch",
|
||||
"start:react-sdk": "node scripts/yarn-sub.js matrix-react-sdk start:all",
|
||||
"start:react-sdk:prod": "cross-env NODE_ENV=production node scripts/yarn-sub.js matrix-react-sdk start:all",
|
||||
"start": "yarn build:js-sdk && yarn build:react-sdk && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"yarn start:js-sdk\" \"yarn start:react-sdk\" \"yarn reskindex:watch\" \"yarn start:res\" \"yarn start:js\"",
|
||||
"start:prod": "yarn build:js-sdk && yarn build:react-sdk && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"yarn start:js-sdk:prod\" \"yarn start:react-sdk:prod\" \"yarn reskindex:watch\" \"yarn start:res\" \"yarn start:js:prod\"",
|
||||
"lint": "eslint src/",
|
||||
"lintall": "eslint src/ test/",
|
||||
"clean": "rimraf lib webapp electron_app/dist",
|
||||
"prepare": "yarn clean && yarn build:compile",
|
||||
"test": "karma start --single-run=true --autoWatch=false --browsers VectorChromeHeadless",
|
||||
"test-multi": "karma start"
|
||||
"electron": "yarn build && yarn install:electron && electron .",
|
||||
"lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style",
|
||||
"lint:js": "eslint src",
|
||||
"lint:ts": "echo 'We don't actually have a typescript linter at this layer because tslint is being removed from our stack. Presumably your TS is fine.'",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"lint:style": "stylelint 'res/css/**/*.scss'",
|
||||
"test": "jest"
|
||||
},
|
||||
"dependencies": {
|
||||
"babel-plugin-transform-async-to-bluebird": "^1.1.1",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-runtime": "^6.26.0",
|
||||
"browser-request": "^0.3.3",
|
||||
"draft-js": "^0.11.0-alpha",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"favico.js": "^0.3.10",
|
||||
"gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566",
|
||||
"gfm.css": "^1.1.2",
|
||||
"highlight.js": "^9.13.1",
|
||||
"matrix-js-sdk": "2.4.6",
|
||||
"matrix-react-sdk": "1.7.5",
|
||||
"modernizr": "^3.6.0",
|
||||
"matrix-js-sdk": "5.0.0",
|
||||
"matrix-react-sdk": "2.1.0",
|
||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz",
|
||||
"postcss-easings": "^2.0.0",
|
||||
"prop-types": "^15.7.2",
|
||||
@@ -87,29 +78,36 @@
|
||||
"url": "^0.11.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"autoprefixer": "^6.6.0",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^8.1.1",
|
||||
"babel-loader": "^7.1.5",
|
||||
"babel-plugin-add-module-exports": "^0.2.1",
|
||||
"babel-plugin-syntax-dynamic-import": "^6.18.0",
|
||||
"babel-plugin-transform-builtin-extend": "^1.1.2",
|
||||
"babel-plugin-transform-class-properties": "^6.24.1",
|
||||
"babel-plugin-transform-object-rest-spread": "^6.26.0",
|
||||
"babel-plugin-transform-runtime": "^6.23.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-es2016": "^6.24.1",
|
||||
"babel-preset-es2017": "^6.24.1",
|
||||
"babel-preset-react": "^6.24.1",
|
||||
"babel-preset-stage-2": "^6.24.1",
|
||||
"chokidar": "^2.0.4",
|
||||
"@babel/cli": "^7.7.5",
|
||||
"@babel/core": "^7.7.5",
|
||||
"@babel/plugin-proposal-class-properties": "^7.7.4",
|
||||
"@babel/plugin-proposal-decorators": "^7.7.4",
|
||||
"@babel/plugin-proposal-export-default-from": "^7.7.4",
|
||||
"@babel/plugin-proposal-numeric-separator": "^7.7.4",
|
||||
"@babel/plugin-proposal-object-rest-spread": "^7.7.4",
|
||||
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
|
||||
"@babel/plugin-transform-flow-comments": "^7.7.4",
|
||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
||||
"@babel/preset-env": "^7.7.6",
|
||||
"@babel/preset-flow": "^7.7.4",
|
||||
"@babel/preset-react": "^7.7.4",
|
||||
"@babel/preset-typescript": "^7.7.4",
|
||||
"@babel/register": "^7.7.4",
|
||||
"@babel/runtime": "^7.7.6",
|
||||
"@types/react": "^16.9.17",
|
||||
"@types/react-dom": "^16.9.4",
|
||||
"autoprefixer": "^9.7.3",
|
||||
"babel-eslint": "^10.0.3",
|
||||
"babel-jest": "^24.9.0",
|
||||
"babel-loader": "^8.0.6",
|
||||
"canvas": "^2.6.1",
|
||||
"chokidar": "^3.3.1",
|
||||
"concurrently": "^4.0.1",
|
||||
"cpx": "^1.3.2",
|
||||
"cross-env": "^4.0.0",
|
||||
"css-loader": "^2.1.0",
|
||||
"electron-builder": "^21.2.0",
|
||||
"electron-builder-squirrel-windows": "^21.2.0",
|
||||
"cross-env": "^6.0.3",
|
||||
"css-loader": "^3.3.2",
|
||||
"electron-builder": "^22.3.2",
|
||||
"electron-builder-squirrel-windows": "^22.3.2",
|
||||
"electron-devtools-installer": "^2.2.4",
|
||||
"electron-notarize": "^0.2.0",
|
||||
"eslint": "^5.8.0",
|
||||
@@ -119,44 +117,43 @@
|
||||
"eslint-plugin-jest": "^23.0.4",
|
||||
"eslint-plugin-react": "^7.11.1",
|
||||
"eslint-plugin-react-hooks": "^2.2.0",
|
||||
"expect": "^1.16.0",
|
||||
"file-loader": "^3.0.1",
|
||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||
"fake-indexeddb": "^3.0.0",
|
||||
"file-loader": "^5.0.2",
|
||||
"fs-extra": "^0.30.0",
|
||||
"html-webpack-plugin": "^3.2.0",
|
||||
"jest": "^24.9.0",
|
||||
"jest-environment-jsdom-fourteen": "^1.0.1",
|
||||
"json-loader": "^0.5.3",
|
||||
"karma": "^3.1.2",
|
||||
"karma-chrome-launcher": "^2.2.0",
|
||||
"karma-cli": "^1.0.1",
|
||||
"karma-logcapture-reporter": "0.0.1",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-sourcemap-loader": "^0.3.7",
|
||||
"karma-spec-reporter": "0.0.31",
|
||||
"karma-summary-reporter": "^1.5.1",
|
||||
"karma-webpack": "4.0.0-beta.0",
|
||||
"loader-utils": "^1.2.3",
|
||||
"matrix-mock-request": "^1.2.3",
|
||||
"matrix-react-test-utils": "^0.2.2",
|
||||
"mini-css-extract-plugin": "^0.8.0",
|
||||
"minimist": "^1.2.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"mocha": "^5.2.0",
|
||||
"modernizr": "^3.6.0",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
||||
"postcss-extend": "^1.0.5",
|
||||
"postcss-import": "^11.1.0",
|
||||
"postcss-loader": "^2.1.6",
|
||||
"postcss-mixins": "^6.2.0",
|
||||
"postcss-nested": "^3.0.0",
|
||||
"postcss-scss": "^1.0.6",
|
||||
"postcss-simple-vars": "^4.1.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-mixins": "^6.2.3",
|
||||
"postcss-nested": "^4.2.1",
|
||||
"postcss-preset-env": "^6.7.0",
|
||||
"postcss-scss": "^2.0.0",
|
||||
"postcss-simple-vars": "^5.0.2",
|
||||
"postcss-strip-inline-comments": "^0.1.5",
|
||||
"rimraf": "^2.4.3",
|
||||
"shell-escape": "^0.2.0",
|
||||
"source-map-loader": "^0.2.4",
|
||||
"webpack": "^4.23.1",
|
||||
"webpack-cli": "^3.1.2",
|
||||
"webpack-dev-server": "^3.1.11"
|
||||
"stylelint": "^12.0.1",
|
||||
"terser-webpack-plugin": "^2.3.0",
|
||||
"typescript": "^3.7.3",
|
||||
"webpack": "^4.41.2",
|
||||
"webpack-cli": "^3.3.10",
|
||||
"webpack-dev-server": "^3.9.0"
|
||||
},
|
||||
"build": {
|
||||
"appId": "im.riot.app",
|
||||
"electronVersion": "7.1.3",
|
||||
"electronVersion": "7.1.12",
|
||||
"files": [
|
||||
"node_modules/**",
|
||||
"src/**"
|
||||
@@ -166,8 +163,7 @@
|
||||
"from": "electron_app/img",
|
||||
"to": "img"
|
||||
},
|
||||
"webapp/**/*",
|
||||
"origin_migrator/**/*"
|
||||
"webapp/**/*"
|
||||
],
|
||||
"linux": {
|
||||
"target": "deb",
|
||||
@@ -177,9 +173,6 @@
|
||||
"StartupWMClass": "riot"
|
||||
}
|
||||
},
|
||||
"deb": {
|
||||
"afterInstall": "electron_app/build/linux/after-install.tpl"
|
||||
},
|
||||
"mac": {
|
||||
"category": "public.app-category.social-networking",
|
||||
"darkModeSupport": true
|
||||
@@ -196,5 +189,30 @@
|
||||
"app": "electron_app"
|
||||
},
|
||||
"afterSign": "scripts/electron_afterSign.js"
|
||||
},
|
||||
"jest": {
|
||||
"modulePathIgnorePatterns": [
|
||||
"<rootDir>/electron_app"
|
||||
],
|
||||
"testEnvironment": "jest-environment-jsdom-fourteen",
|
||||
"testMatch": [
|
||||
"<rootDir>/test/**/*-test.js"
|
||||
],
|
||||
"setupFilesAfterEnv": [
|
||||
"<rootDir>/node_modules/matrix-react-sdk/test/setupTests.js"
|
||||
],
|
||||
"moduleNameMapper": {
|
||||
"\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/imageMock.js",
|
||||
"\\$webapp/i18n/languages.json": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/languages.json",
|
||||
"^browser-request$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/browser-request.js",
|
||||
"^react$": "<rootDir>/node_modules/react",
|
||||
"^react-dom$": "<rootDir>/node_modules/react-dom",
|
||||
"^matrix-js-sdk$": "<rootDir>/node_modules/matrix-js-sdk/src",
|
||||
"^matrix-react-sdk$": "<rootDir>/node_modules/matrix-react-sdk/src"
|
||||
},
|
||||
"transformIgnorePatterns": [
|
||||
"/node_modules/(?!matrix-js-sdk).+$",
|
||||
"/node_modules/(?!matrix-react-sdk).+$"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require("postcss-import")(),
|
||||
require("autoprefixer")(),
|
||||
require("postcss-simple-vars")(),
|
||||
require("postcss-extend")(),
|
||||
require("postcss-nested")(),
|
||||
require("postcss-mixins")(),
|
||||
require("postcss-easings")(),
|
||||
require("postcss-strip-inline-comments")(),
|
||||
],
|
||||
"parser": "postcss-scss",
|
||||
"local-plugins": true,
|
||||
};
|
||||
42
release.sh
42
release.sh
@@ -21,25 +21,40 @@ cd `dirname $0`
|
||||
for i in matrix-js-sdk matrix-react-sdk
|
||||
do
|
||||
depver=`cat package.json | jq -r .dependencies[\"$i\"]`
|
||||
latestver=`yarn info -s $i version`
|
||||
latestver=`yarn info -s $i dist-tags.next`
|
||||
if [ "$depver" != "$latestver" ]
|
||||
then
|
||||
echo "The latest version of $i is $latestver but package.json depends on $depver"
|
||||
echo -n "Type 'Yes' to continue anyway: "
|
||||
echo "The latest version of $i is $latestver but package.json depends on $depver."
|
||||
echo -n "Type 'u' to auto-upgrade, 'c' to continue anyway, or 'a' to abort:"
|
||||
read resp
|
||||
if [ "$resp" != "Yes" ]
|
||||
if [ "$resp" != "u" ] && [ "$resp" != "c" ]
|
||||
then
|
||||
echo "OK, never mind."
|
||||
echo "Aborting."
|
||||
exit 1
|
||||
fi
|
||||
if [ "$resp" == "u" ]
|
||||
then
|
||||
echo "Upgrading $i to $latestver..."
|
||||
yarn add -E $i@$latestver
|
||||
git add -u
|
||||
# The `-e` flag opens the editor and gives you a chance to check
|
||||
# the upgrade for correctness.
|
||||
git commit -m "Upgrade $i to $latestver" -e
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# bump Electron's package.json first
|
||||
release="${1#v}"
|
||||
tag="v${release}"
|
||||
echo "electron yarn version"
|
||||
prerelease=0
|
||||
# We check if this build is a prerelease by looking to
|
||||
# see if the version has a hyphen in it. Crude,
|
||||
# but semver doesn't support postreleases so anything
|
||||
# with a hyphen is a prerelease.
|
||||
echo $release | grep -q '-' && prerelease=1
|
||||
|
||||
# bump Electron's package.json first
|
||||
echo "electron yarn version"
|
||||
cd electron_app
|
||||
yarn version --no-git-tag-version --new-version "$release"
|
||||
git commit package.json -m "$tag"
|
||||
@@ -47,3 +62,16 @@ git commit package.json -m "$tag"
|
||||
cd ..
|
||||
|
||||
exec ./node_modules/matrix-js-sdk/release.sh -u vector-im -z "$orig_args"
|
||||
|
||||
if [ $prerelease -eq 0 ]
|
||||
then
|
||||
# For a release, reset SDK deps back to the `develop` branch.
|
||||
for i in matrix-js-sdk matrix-react-sdk
|
||||
do
|
||||
echo "Resetting $i to develop branch..."
|
||||
yarn add github:matrix-org/$i#develop
|
||||
git add -u
|
||||
git commit -m "Reset $i back to develop branch"
|
||||
done
|
||||
git push origin develop
|
||||
fi
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"piwik": {
|
||||
"url": "https://piwik.riot.im/",
|
||||
"siteId": 1,
|
||||
"policyUrl": "https://matrix.org/docs/guides/riot_im_cookie_policy"
|
||||
"policyUrl": "https://matrix.org/legal/riot-im-cookie-policy"
|
||||
},
|
||||
"roomDirectory": {
|
||||
"servers": [
|
||||
@@ -35,7 +35,7 @@
|
||||
"text": "Privacy Policy"
|
||||
},
|
||||
{
|
||||
"url": "https://matrix.org/docs/guides/riot_im_cookie_policy",
|
||||
"url": "https://matrix.org/legal/riot-im-cookie-policy",
|
||||
"text": "Cookie Policy"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -20,14 +20,17 @@
|
||||
"feature_many_integration_managers": "labs",
|
||||
"feature_mjolnir": "labs",
|
||||
"feature_dm_verification": "labs",
|
||||
"feature_cross_signing": "labs",
|
||||
"feature_event_indexing": "labs"
|
||||
"feature_cross_signing": "enable",
|
||||
"feature_invite_only_padlocks": "enable",
|
||||
"feature_event_indexing": "disable",
|
||||
"feature_bridge_state": "labs",
|
||||
"feature_presence_in_room_list": "labs"
|
||||
},
|
||||
"welcomeUserId": "@riot-bot:matrix.org",
|
||||
"piwik": {
|
||||
"url": "https://piwik.riot.im/",
|
||||
"siteId": 1,
|
||||
"policyUrl": "https://matrix.org/docs/guides/riot_im_cookie_policy"
|
||||
"policyUrl": "https://matrix.org/legal/riot-im-cookie-policy"
|
||||
},
|
||||
"roomDirectory": {
|
||||
"servers": [
|
||||
@@ -44,7 +47,7 @@
|
||||
"text": "Privacy Policy"
|
||||
},
|
||||
{
|
||||
"url": "https://matrix.org/docs/guides/riot_im_cookie_policy",
|
||||
"url": "https://matrix.org/legal/riot-im-cookie-policy",
|
||||
"text": "Cookie Policy"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -14,4 +14,4 @@ JSSDK_SHA=$(cd node_modules/matrix-js-sdk; git rev-parse --short=12 HEAD)
|
||||
|
||||
VECTOR_SHA=$(git rev-parse --short=12 HEAD) # use the ACTUAL SHA rather than assume develop
|
||||
|
||||
DIST_VERSION=$VECTOR_SHA-react-$REACT_SHA-js-$JSSDK_SHA scripts/package.sh -d
|
||||
CI_PACKAGE=true DIST_VERSION=$VECTOR_SHA-react-$REACT_SHA-js-$JSSDK_SHA scripts/package.sh -d
|
||||
|
||||
@@ -58,6 +58,7 @@ const INCLUDE_LANGS = [
|
||||
// "dest/b/...".
|
||||
const COPY_LIST = [
|
||||
["res/manifest.json", "webapp"],
|
||||
["res/sw.js", "webapp"],
|
||||
["res/welcome.html", "webapp"],
|
||||
["res/welcome/**", "webapp/welcome"],
|
||||
["res/themes/**", "webapp/themes"],
|
||||
@@ -65,6 +66,7 @@ const COPY_LIST = [
|
||||
["node_modules/matrix-react-sdk/res/media/**", "webapp/media"],
|
||||
["node_modules/olm/olm_legacy.js", "webapp", { directwatch: 1 }],
|
||||
["./config.json", "webapp", { directwatch: 1 }],
|
||||
["contribute.json", "webapp"],
|
||||
];
|
||||
|
||||
const parseArgs = require('minimist');
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
|
||||
@@ -1,15 +1,17 @@
|
||||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -ex
|
||||
|
||||
TAG=$(git describe --dirty --tags)
|
||||
TAG=$(git describe --tags)
|
||||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
DIST_VERSION=$TAG
|
||||
|
||||
# If the branch comes out as HEAD then we're probably checked out to a tag, so if the thing is *not*
|
||||
# coming out as HEAD then we're on a branch. When we're on a branch, we want to resolve ourselves to
|
||||
# a few SHAs rather than a version.
|
||||
if [ $BRANCH != 'HEAD' ]
|
||||
# Docker Hub doesn't always check out the tag and sometimes checks out the branch, so we should look
|
||||
# for an appropriately tagged branch as well (heads/v1.2.3).
|
||||
if [ $BRANCH != 'HEAD' && $BRANCH != 'heads/v*' ]
|
||||
then
|
||||
REACT_SHA=$(cd node_modules/matrix-react-sdk; git rev-parse --short=12 HEAD)
|
||||
JSSDK_SHA=$(cd node_modules/matrix-js-sdk; git rev-parse --short=12 HEAD)
|
||||
|
||||
@@ -78,6 +78,7 @@ dodep matrix-org matrix-js-sdk
|
||||
pushd matrix-js-sdk
|
||||
yarn link
|
||||
yarn install
|
||||
yarn build
|
||||
popd
|
||||
|
||||
yarn link matrix-js-sdk
|
||||
@@ -95,6 +96,7 @@ pushd matrix-react-sdk
|
||||
yarn link
|
||||
yarn link matrix-js-sdk
|
||||
yarn install
|
||||
yarn build
|
||||
popd
|
||||
|
||||
yarn link matrix-react-sdk
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
set -e
|
||||
|
||||
dev=""
|
||||
if [ "$1" = '-d' ]; then
|
||||
dev=":dev"
|
||||
fi
|
||||
|
||||
if [ -n "$DIST_VERSION" ]; then
|
||||
version=$DIST_VERSION
|
||||
else
|
||||
@@ -14,7 +9,7 @@ else
|
||||
fi
|
||||
|
||||
yarn clean
|
||||
yarn build$dev
|
||||
yarn build
|
||||
|
||||
# include the sample config in the tarball. Arguably this should be done by
|
||||
# `yarn build`, but it's just too painful.
|
||||
|
||||
@@ -18,9 +18,9 @@ limitations under the License.
|
||||
|
||||
'use strict';
|
||||
|
||||
import EmbeddedPage from 'matrix-react-sdk/lib/components/structures/EmbeddedPage';
|
||||
import EmbeddedPage from 'matrix-react-sdk/src/components/structures/EmbeddedPage';
|
||||
import sanitizeHtml from 'sanitize-html';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
||||
|
||||
export default class VectorEmbeddedPage extends EmbeddedPage {
|
||||
static replaces = 'EmbeddedPage';
|
||||
|
||||
@@ -16,14 +16,13 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import SdkConfig from 'matrix-react-sdk/lib/SdkConfig';
|
||||
import SdkConfig from 'matrix-react-sdk/src/SdkConfig';
|
||||
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
||||
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
|
||||
module.exports = () => {
|
||||
const VectorAuthFooter = () => {
|
||||
const brandingConfig = SdkConfig.get().branding;
|
||||
let links = [
|
||||
{"text": "blog", "url": "https://medium.com/@RiotChat"},
|
||||
{"text": "blog", "url": "https://blog.riot.im"},
|
||||
{"text": "twitter", "url": "https://twitter.com/@RiotChat"},
|
||||
{"text": "github", "url": "https://github.com/vector-im/riot-web"},
|
||||
];
|
||||
@@ -48,4 +47,7 @@ module.exports = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
module.exports.replaces = 'AuthFooter';
|
||||
|
||||
VectorAuthFooter.replaces = 'AuthFooter';
|
||||
|
||||
export default VectorAuthFooter;
|
||||
|
||||
@@ -19,7 +19,7 @@ limitations under the License.
|
||||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import SdkConfig from 'matrix-react-sdk/lib/SdkConfig';
|
||||
import SdkConfig from 'matrix-react-sdk/src/SdkConfig';
|
||||
|
||||
export default class VectorAuthHeaderLogo extends React.PureComponent {
|
||||
static replaces = 'AuthHeaderLogo'
|
||||
|
||||
@@ -17,8 +17,8 @@ limitations under the License.
|
||||
'use strict';
|
||||
|
||||
import React from 'react';
|
||||
import sdk from 'matrix-react-sdk/lib/index';
|
||||
import SdkConfig from 'matrix-react-sdk/lib/SdkConfig';
|
||||
import * as sdk from 'matrix-react-sdk/src/index';
|
||||
import SdkConfig from 'matrix-react-sdk/src/SdkConfig';
|
||||
|
||||
export default class VectorAuthPage extends React.PureComponent {
|
||||
static replaces = 'AuthPage'
|
||||
|
||||
@@ -16,13 +16,13 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import React from "react";
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
||||
|
||||
/**
|
||||
* This is identical to `CustomServerDialog` except for replacing "this app"
|
||||
* with "Riot".
|
||||
*/
|
||||
module.exports = ({onFinished}) => {
|
||||
const VectorCustomServerDialog = ({onFinished}) => {
|
||||
return (
|
||||
<div className="mx_ErrorDialog">
|
||||
<div className="mx_Dialog_title">
|
||||
@@ -44,4 +44,7 @@ module.exports = ({onFinished}) => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
module.exports.replaces = 'CustomServerDialog';
|
||||
|
||||
VectorCustomServerDialog.replaces = 'CustomServerDialog';
|
||||
|
||||
export default VectorCustomServerDialog;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"Riot Desktop on %(platformName)s": "%(platformName)s-da Riot Desktop",
|
||||
"Unknown device": "Naməlum qurğu",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "İş stolunun birgə istifadəsi üçün HTTPS-dan istifadə tələb olunur.",
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Riot konfiqurasiyanızda yanlış JSON var. Lütfən, xətanı düzəldin və səhifəni yeniləyin",
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Riot konfiqurasiyanızda yanlış JSON var. Lütfən, xətanı düzəldin və səhifəni yeniləyin.",
|
||||
"Invalid JSON": "Yanlış JSON",
|
||||
"Sign In": "Daxil ol",
|
||||
"Create Account": "Hesab Aç",
|
||||
@@ -10,8 +10,16 @@
|
||||
"Chat with Riot Bot": "Riot Bot-la söhbət edin",
|
||||
"Explore rooms": "Otaqları kəşf edin",
|
||||
"Your Riot is misconfigured": "Riot yanlış quraşdırılıb",
|
||||
"Unexpected error preparing the app. See console for details.": "Proqramı başladarkən gözlənilməz xəta. Ətraflı məlumat üçün konsola baxın.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Yanlış konfiqurasiya: default_server_config, default_server_name, və ya default_hs_url-dən yalnız birini təyin etməlisiniz.",
|
||||
"Invalid configuration: no default server specified.": "Yanlış konfiqurasiya: ilkin server təyin edilməyib.",
|
||||
"%(appName)s via %(browserName)s on %(osName)s": "%(osName)s-da %(browserName)s ilə %(appName)s"
|
||||
"Unexpected error preparing the app. See console for details.": "Proqramın başlanmasında gözlənilməz xəta. İzah üçün konsola baxın",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Yanlış konfiqurasiya: bunlardan yalnız birini təyin edin - default_server_config, default_server_name, və ya default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "Yanlış konfiqurasiya: ilkin server təyin edilməyib",
|
||||
"%(appName)s via %(browserName)s on %(osName)s": "%(osName)s-da %(browserName)s ilə %(appName)s",
|
||||
"The message from the parser is: %(message)s": "Sözügedən mesaj: %(message)s",
|
||||
"powered by Matrix": "Matrix tərəfindən təchiz edilmişdir",
|
||||
"Custom Server Options": "Fərdi Server Seçimləri",
|
||||
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Riot with an existing Matrix account on a different homeserver.": "Fərqli server URL-ni təyin etməklə digər Matrix serverlərinə daxil olmaq üçün fərdi server seçimlərini istifadə edə bilərsiniz. Bu sizə başqa serverdə qaldırılmış mövcud Matrix hesabınızla Riot-u işlətməyə imkan verir.",
|
||||
"Dismiss": "Nəzərə almayın",
|
||||
"Room Directory": "Otaq kataloqu",
|
||||
"Welcome to Riot.im": "Riot.im-ə xoş gəlmişsiniz",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "[matrix] tərəfindən təchiz edilmiş mərkəziləşdirilməmiş, şifrələnmiş çat və əməkdaşlıq platforması"
|
||||
}
|
||||
|
||||
@@ -14,5 +14,12 @@
|
||||
"Create Account": "Crear conta",
|
||||
"Need help?": "¿Precisas axuda?",
|
||||
"Explore rooms": "Explorar salas",
|
||||
"Room Directory": "Directorio de salas"
|
||||
"Room Directory": "Directorio de salas",
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "A configuración de Riot contén JSON non válido. Corrixe o problema e recarga a páxina.",
|
||||
"The message from the parser is: %(message)s": "A mensaxe desde o intérprete é: %(message)s",
|
||||
"Invalid JSON": "JSON non válido",
|
||||
"Your Riot is misconfigured": "Riot está mal configurado",
|
||||
"Unexpected error preparing the app. See console for details.": "Fallo non agardado ao preparar a app. Detalles na consola.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Configuración non válida: só se pode indicar un de default_server_config, default_server_name, ou default_hs_url.",
|
||||
"Invalid configuration: no default server specified.": "Configuración non válida: non se indicou servidor por omisión."
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"Create Account": "Fiók készítés",
|
||||
"Need help?": "Segíthetünk?",
|
||||
"Explore rooms": "Szobák felderítése",
|
||||
"Room Directory": "Szoba lista",
|
||||
"Room Directory": "Szobalista",
|
||||
"Unexpected error preparing the app. See console for details.": "Váratlan hiba történt az alkalmazás előkészítésénél. A részletekért nézd meg a konzolt.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Érvénytelen konfiguráció: csak egyet lehet megadni a default_server_config, default_server_name és default_hs_url közül.",
|
||||
"Invalid configuration: no default server specified.": "Érvénytelen konfiguráció: nincs megadva alapértelmezett szerver.",
|
||||
|
||||
1
src/i18n/strings/kab.json
Normal file
1
src/i18n/strings/kab.json
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -12,7 +12,7 @@
|
||||
"Sign In": "Prisijungti",
|
||||
"Create Account": "Sukurti paskyrą",
|
||||
"Need help?": "Reikia pagalbos?",
|
||||
"Explore rooms": "Peržiūrėti kambarius",
|
||||
"Explore rooms": "Žvalgyti kambarius",
|
||||
"Room Directory": "Kambarių katalogas",
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Jūsų Riot konfigūracijoje yra klaidingas JSON. Prašome pataisyti problemą ir iš naujo užkrauti puslapį.",
|
||||
"The message from the parser is: %(message)s": "Analizatoriaus žinutė yra: %(message)s",
|
||||
|
||||
25
src/i18n/strings/mn.json
Normal file
25
src/i18n/strings/mn.json
Normal file
@@ -0,0 +1,25 @@
|
||||
{
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Таны Риот тохиргоо буруу ЖСОН агуулж байна. Зөв болгоод, хуудсыг ахин дуудна уу.",
|
||||
"The message from the parser is: %(message)s": "Парсераас ирсэн мессеж нь: %(message)s",
|
||||
"Invalid JSON": "Буруу ЖСОН",
|
||||
"Your Riot is misconfigured": "Таны РИОТ тохиргоо буруу",
|
||||
"Unexpected error preparing the app. See console for details.": "Апп бэлдэх үед гарах ёсгүй алдаа. Дэлгэрэнгүйг консолоос харна уу.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Буруу тохиргоо: default_server_config, default_server_name, эсвэл default_hs_url утгын зөвхөн аль нэгийг л зааж болно.",
|
||||
"Invalid configuration: no default server specified.": "Буруу тохиргоо: Өгөгдсөл серверийг зааж өгөөгүй байна.",
|
||||
"Riot Desktop on %(platformName)s": "%(platformName)s дээрх Риот Десктоп",
|
||||
"Unknown device": "Үл мэдэгдэх төхөөрөмж",
|
||||
"%(appName)s via %(browserName)s on %(osName)s": "%(osName)s дээр %(browserName)s -ээр дамжсан %(appName)s",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Та дэлгэц хуваалцах дуудлага хийхдээ HTTPS ашиглах ёстой.",
|
||||
"powered by Matrix": "Matrix - Ивээв",
|
||||
"Custom Server Options": "Кастом серверийн сонголтууд",
|
||||
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Riot with an existing Matrix account on a different homeserver.": "Та кастом серверийн сонголтууд ашиглан серверийн хаягийг зааж, өөр сервер рүү нэвтэрч болно. Энэ нь танд Риотыг одоо байгаа матрикс аккаунтаараа өөр сервер дээр ашиглах боломж олгоно.",
|
||||
"Dismiss": "Орхих",
|
||||
"Welcome to Riot.im": "Riot.im -д тавтай морил",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Төвлөрсөн бус, нууцлалтай чат & хамтын ажиллагааг [matrix] - ивээв",
|
||||
"Sign In": "Нэвтрэх",
|
||||
"Create Account": "Хэрэглэгч үүсгэх",
|
||||
"Need help?": "Тусламж хэрэгтэй юу?",
|
||||
"Chat with Riot Bot": "Риот боттой чатлах",
|
||||
"Explore rooms": "Өрөөнүүд үзэх",
|
||||
"Room Directory": "Өрөөний директор"
|
||||
}
|
||||
@@ -2,17 +2,24 @@
|
||||
"%(appName)s via %(browserName)s on %(osName)s": "%(osName)s işletim sisteminde %(browserName)s ile %(appName)s",
|
||||
"Custom Server Options": "Özelleştirilebilir Sunucu Seçenekleri",
|
||||
"Dismiss": "Kapat",
|
||||
"powered by Matrix": "Matrix'den besleniyor",
|
||||
"powered by Matrix": "Matrix tarafından destekleniyor",
|
||||
"Riot Desktop on %(platformName)s": "%(platformName)s platformunda Riot Masaüstü",
|
||||
"Unknown device": "Bilinmeyen aygıt",
|
||||
"You need to be using HTTPS to place a screen-sharing call.": "Ekran paylaşımlı arama yapmak için HTTPS kullanıyor olmalısınız.",
|
||||
"Welcome to Riot.im": "Riot.im'e hoş geldiniz",
|
||||
"Decentralised, encrypted chat & collaboration powered by [matrix]": "Merkezsiz, şifreli sohbet & işbirliği ile Matrix tarafından desteklenmektedir",
|
||||
"Chat with Riot Bot": "Riot Bot ile sohbet et",
|
||||
"Chat with Riot Bot": "Riot Bot ile Sohbet Et",
|
||||
"You can use the custom server options to sign into other Matrix servers by specifying a different homeserver URL. This allows you to use Riot with an existing Matrix account on a different homeserver.": "Özel sunucu seçenekleri kullanıp farklı bir anamakine URL'si belirleyerek diğer Matrix sunucularına giriş yapabilirsin. Bu Riot'u varolan bir Matrix hesabı ile farklı anamakine de kullanmanı sağlar.",
|
||||
"Sign In": "Giriş yap",
|
||||
"Sign In": "Giriş Yap",
|
||||
"Create Account": "Kayıt Ol",
|
||||
"Need help?": "Yardıma mı ihtiyacın var?",
|
||||
"Explore rooms": "Odaları keşfet",
|
||||
"Room Directory": "Oda Dizini"
|
||||
"Room Directory": "Oda Dizini",
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem and reload the page.": "Riot yapılandırmanız geçersiz JSON ifadesi içermektedir. Lütfen problemi düzeltin ve sayfayı yenileyin.",
|
||||
"Invalid JSON": "Geçersiz JSON",
|
||||
"Your Riot is misconfigured": "Rioutunuz hatalı yapılandırılmış",
|
||||
"Unexpected error preparing the app. See console for details.": "Uygulamayı hazırlarken beklenmeyen hata oluştu. Lütfen detaylar için konsola bakınız.",
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, or default_hs_url.": "Geçersiz yapılandırma: default_server_config, default_server_name, yada default_hs_url den sadece birisi seçilebilir.",
|
||||
"Invalid configuration: no default server specified.": "Geçersiz yapılandırma: varsayılan sunucu seçilmemiş.",
|
||||
"The message from the parser is: %(message)s": "Ayrıştırıcıdan gelen mesaj: %(message)s"
|
||||
}
|
||||
|
||||
486
src/vector/app.js
Normal file
486
src/vector/app.js
Normal file
@@ -0,0 +1,486 @@
|
||||
/*
|
||||
Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2018, 2019 New Vector Ltd
|
||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
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 olmWasmPath from 'olm/olm.wasm';
|
||||
|
||||
import React from 'react';
|
||||
// add React and ReactPerf to the global namespace, to make them easier to
|
||||
// access via the console
|
||||
global.React = React;
|
||||
|
||||
import ReactDOM from 'react-dom';
|
||||
import * as sdk from 'matrix-react-sdk';
|
||||
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
||||
import * as VectorConferenceHandler from 'matrix-react-sdk/src/VectorConferenceHandler';
|
||||
import * as languageHandler 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 url from 'url';
|
||||
|
||||
import {parseQs, parseQsFromFragment} from './url_utils';
|
||||
|
||||
import ElectronPlatform from './platform/ElectronPlatform';
|
||||
import WebPlatform from './platform/WebPlatform';
|
||||
|
||||
import {MatrixClientPeg} from 'matrix-react-sdk/src/MatrixClientPeg';
|
||||
import SettingsStore from "matrix-react-sdk/src/settings/SettingsStore";
|
||||
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
||||
import {setTheme} from "matrix-react-sdk/src/theme";
|
||||
|
||||
import Olm from 'olm';
|
||||
|
||||
import CallHandler from 'matrix-react-sdk/src/CallHandler';
|
||||
|
||||
let lastLocationHashSet = null;
|
||||
|
||||
function checkBrowserFeatures() {
|
||||
if (!window.Modernizr) {
|
||||
console.error("Cannot check features - Modernizr global is missing.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// custom checks atop Modernizr because it doesn't have ES2018/ES2019 checks in it for some features we depend on,
|
||||
// Modernizr requires rules to be lowercase with no punctuation:
|
||||
// ES2018: http://www.ecma-international.org/ecma-262/9.0/#sec-promise.prototype.finally
|
||||
window.Modernizr.addTest("promiseprototypefinally", () =>
|
||||
window.Promise && window.Promise.prototype && typeof window.Promise.prototype.finally === "function");
|
||||
// ES2019: http://www.ecma-international.org/ecma-262/10.0/#sec-object.fromentries
|
||||
window.Modernizr.addTest("objectfromentries", () =>
|
||||
window.Object && typeof window.Object.fromEntries === "function");
|
||||
|
||||
const featureList = Object.keys(window.Modernizr);
|
||||
|
||||
let featureComplete = true;
|
||||
for (let i = 0; i < featureList.length; i++) {
|
||||
if (window.Modernizr[featureList[i]] === undefined) {
|
||||
console.error(
|
||||
"Looked for feature '%s' but Modernizr has no results for this. " +
|
||||
"Has it been configured correctly?", featureList[i],
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (window.Modernizr[featureList[i]] === false) {
|
||||
console.error("Browser missing feature: '%s'", featureList[i]);
|
||||
// toggle flag rather than return early so we log all missing features rather than just the first.
|
||||
featureComplete = false;
|
||||
}
|
||||
}
|
||||
return featureComplete;
|
||||
}
|
||||
|
||||
// Parse the given window.location and return parameters that can be used when calling
|
||||
// MatrixChat.showScreen(screen, params)
|
||||
function getScreenFromLocation(location) {
|
||||
const fragparts = parseQsFromFragment(location);
|
||||
return {
|
||||
screen: fragparts.location.substring(1),
|
||||
params: fragparts.params,
|
||||
};
|
||||
}
|
||||
|
||||
// Here, we do some crude URL analysis to allow
|
||||
// deep-linking.
|
||||
function routeUrl(location) {
|
||||
if (!window.matrixChat) return;
|
||||
|
||||
console.log("Routing URL ", location.href);
|
||||
const s = getScreenFromLocation(location);
|
||||
window.matrixChat.showScreen(s.screen, s.params);
|
||||
}
|
||||
|
||||
function onHashChange(ev) {
|
||||
if (decodeURIComponent(window.location.hash) === lastLocationHashSet) {
|
||||
// we just set this: no need to route it!
|
||||
return;
|
||||
}
|
||||
routeUrl(window.location);
|
||||
}
|
||||
|
||||
// This will be called whenever the SDK changes screens,
|
||||
// so a web page can update the URL bar appropriately.
|
||||
function onNewScreen(screen) {
|
||||
console.log("newscreen "+screen);
|
||||
const hash = '#/' + screen;
|
||||
lastLocationHashSet = hash;
|
||||
window.location.hash = hash;
|
||||
}
|
||||
|
||||
// We use this to work out what URL the SDK should
|
||||
// pass through when registering to allow the user to
|
||||
// click back to the client having registered.
|
||||
// It's up to us to recognise if we're loaded with
|
||||
// this URL and tell MatrixClient to resume registration.
|
||||
//
|
||||
// If we're in electron, we should never pass through a file:// URL otherwise
|
||||
// the identity server will try to 302 the browser to it, which breaks horribly.
|
||||
// so in that instance, hardcode to use riot.im/app for now instead.
|
||||
function makeRegistrationUrl(params) {
|
||||
let url;
|
||||
if (window.location.protocol === "vector:") {
|
||||
url = 'https://riot.im/app/#/register';
|
||||
} else {
|
||||
url = (
|
||||
window.location.protocol + '//' +
|
||||
window.location.host +
|
||||
window.location.pathname +
|
||||
'#/register'
|
||||
);
|
||||
}
|
||||
|
||||
const keys = Object.keys(params);
|
||||
for (let i = 0; i < keys.length; ++i) {
|
||||
if (i === 0) {
|
||||
url += '?';
|
||||
} else {
|
||||
url += '&';
|
||||
}
|
||||
const k = keys[i];
|
||||
url += k + '=' + encodeURIComponent(params[k]);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
function onTokenLoginCompleted() {
|
||||
// if we did a token login, we're now left with the token, hs and is
|
||||
// url as query params in the url; a little nasty but let's redirect to
|
||||
// clear them.
|
||||
const parsedUrl = url.parse(window.location.href);
|
||||
parsedUrl.search = "";
|
||||
const formatted = url.format(parsedUrl);
|
||||
console.log("Redirecting to " + formatted + " to drop loginToken " +
|
||||
"from queryparams");
|
||||
window.location.href = formatted;
|
||||
}
|
||||
|
||||
export async function loadApp() {
|
||||
// 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 new Error("Missing indexeddb worker script!");
|
||||
}
|
||||
MatrixClientPeg.setIndexedDbWorkerScript(vectorIndexeddbWorkerScript);
|
||||
CallHandler.setConferenceHandler(VectorConferenceHandler);
|
||||
|
||||
window.addEventListener('hashchange', onHashChange);
|
||||
|
||||
await loadOlm();
|
||||
|
||||
// set the platform for react sdk
|
||||
if (window.ipcRenderer) {
|
||||
console.log("Using Electron platform");
|
||||
const plaf = new ElectronPlatform();
|
||||
PlatformPeg.set(plaf);
|
||||
} else {
|
||||
console.log("Using Web platform");
|
||||
PlatformPeg.set(new WebPlatform());
|
||||
}
|
||||
|
||||
const platform = PlatformPeg.get();
|
||||
|
||||
let configJson;
|
||||
let configError;
|
||||
let configSyntaxError = false;
|
||||
try {
|
||||
configJson = await platform.getConfig();
|
||||
} catch (e) {
|
||||
configError = e;
|
||||
|
||||
if (e && e.err && e.err instanceof SyntaxError) {
|
||||
console.error("SyntaxError loading config:", e);
|
||||
configSyntaxError = true;
|
||||
configJson = {}; // to prevent errors between here and loading CSS for the error box
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure
|
||||
// granular settings are loaded correctly and to avoid duplicating the override logic for the theme.
|
||||
SdkConfig.put(configJson);
|
||||
|
||||
// Load language after loading config.json so that settingsDefaults.language can be applied
|
||||
await loadLanguage();
|
||||
|
||||
const fragparts = parseQsFromFragment(window.location);
|
||||
const params = parseQs(window.location);
|
||||
|
||||
// don't try to redirect to the native apps if we're
|
||||
// verifying a 3pid (but after we've loaded the config)
|
||||
// or if the user is following a deep link
|
||||
// (https://github.com/vector-im/riot-web/issues/7378)
|
||||
const preventRedirect = fragparts.params.client_secret || fragparts.location.length > 0;
|
||||
|
||||
if (!preventRedirect) {
|
||||
const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||
const isAndroid = /Android/.test(navigator.userAgent);
|
||||
if (isIos || isAndroid) {
|
||||
if (document.cookie.indexOf("riot_mobile_redirect_to_guide=false") === -1) {
|
||||
window.location = "mobile_guide/";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// as quickly as we possibly can, set a default theme...
|
||||
await setTheme();
|
||||
|
||||
// Now that we've loaded the theme (CSS), display the config syntax error if needed.
|
||||
if (configSyntaxError) {
|
||||
const errorMessage = (
|
||||
<div>
|
||||
<p>
|
||||
{_t(
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem " +
|
||||
"and reload the page.",
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{_t(
|
||||
"The message from the parser is: %(message)s",
|
||||
{message: configError.err.message || _t("Invalid JSON")},
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage");
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<GenericErrorPage message={errorMessage} title={_t("Your Riot is misconfigured")} />,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const validBrowser = checkBrowserFeatures();
|
||||
|
||||
const acceptInvalidBrowser = window.localStorage && window.localStorage.getItem('mx_accepts_unsupported_browser');
|
||||
|
||||
const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
||||
console.log("Vector starting at " + urlWithoutQuery);
|
||||
if (configError) {
|
||||
window.matrixChat = ReactDOM.render(<div className="error">
|
||||
Unable to load config file: please refresh the page to try again.
|
||||
</div>, document.getElementById('matrixchat'));
|
||||
} else if (validBrowser || acceptInvalidBrowser) {
|
||||
platform.startUpdater();
|
||||
|
||||
// Don't bother loading the app until the config is verified
|
||||
verifyServerConfig().then((newConfig) => {
|
||||
const MatrixChat = sdk.getComponent('structures.MatrixChat');
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<MatrixChat
|
||||
onNewScreen={onNewScreen}
|
||||
makeRegistrationUrl={makeRegistrationUrl}
|
||||
ConferenceHandler={VectorConferenceHandler}
|
||||
config={newConfig}
|
||||
realQueryParams={params}
|
||||
startingFragmentQueryParams={fragparts.params}
|
||||
enableGuest={!configJson.disable_guests}
|
||||
onTokenLoginCompleted={onTokenLoginCompleted}
|
||||
initialScreenAfterLogin={getScreenFromLocation(window.location)}
|
||||
defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()}
|
||||
/>,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
|
||||
let errorMessage = err.translatedMessage
|
||||
|| _t("Unexpected error preparing the app. See console for details.");
|
||||
errorMessage = <span>{errorMessage}</span>;
|
||||
|
||||
// Like the compatibility page, AWOOOOOGA at the user
|
||||
const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage");
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<GenericErrorPage message={errorMessage} title={_t("Your Riot is misconfigured")} />,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
console.error("Browser is missing required features.");
|
||||
// take to a different landing page to AWOOOOOGA at the user
|
||||
const CompatibilityPage = sdk.getComponent("structures.CompatibilityPage");
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<CompatibilityPage onAccept={function() {
|
||||
if (window.localStorage) window.localStorage.setItem('mx_accepts_unsupported_browser', true);
|
||||
console.log("User accepts the compatibility risks.");
|
||||
loadApp();
|
||||
}} />,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function loadOlm() {
|
||||
/* Load Olm. We try the WebAssembly version first, and then the legacy,
|
||||
* asm.js version if that fails. For this reason we need to wait for this
|
||||
* to finish before continuing to load the rest of the app. In future
|
||||
* we could somehow pass a promise down to react-sdk and have it wait on
|
||||
* that so olm can be loading in parallel with the rest of the app.
|
||||
*
|
||||
* We also need to tell the Olm js to look for its wasm file at the same
|
||||
* level as index.html. It really should be in the same place as the js,
|
||||
* ie. in the bundle directory, but as far as I can tell this is
|
||||
* completely impossible with webpack. We do, however, use a hashed
|
||||
* filename to avoid caching issues.
|
||||
*/
|
||||
return Olm.init({
|
||||
locateFile: () => olmWasmPath,
|
||||
}).then(() => {
|
||||
console.log("Using WebAssembly Olm");
|
||||
}).catch((e) => {
|
||||
console.log("Failed to load Olm: trying legacy version", e);
|
||||
return new Promise((resolve, reject) => {
|
||||
const s = document.createElement('script');
|
||||
s.src = 'olm_legacy.js'; // XXX: This should be cache-busted too
|
||||
s.onload = resolve;
|
||||
s.onerror = reject;
|
||||
document.body.appendChild(s);
|
||||
}).then(() => {
|
||||
// Init window.Olm, ie. the one just loaded by the script tag,
|
||||
// not 'Olm' which is still the failed wasm version.
|
||||
return window.Olm.init();
|
||||
}).then(() => {
|
||||
console.log("Using legacy Olm");
|
||||
}).catch((e) => {
|
||||
console.log("Both WebAssembly and asm.js Olm failed!", e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loadLanguage() {
|
||||
const prefLang = SettingsStore.getValue("language", null, /*excludeDefault=*/true);
|
||||
let langs = [];
|
||||
|
||||
if (!prefLang) {
|
||||
languageHandler.getLanguagesFromBrowser().forEach((l) => {
|
||||
langs.push(...languageHandler.getNormalizedLanguageKeys(l));
|
||||
});
|
||||
} else {
|
||||
langs = [prefLang];
|
||||
}
|
||||
try {
|
||||
await languageHandler.setLanguage(langs);
|
||||
document.documentElement.setAttribute("lang", languageHandler.getCurrentLanguage());
|
||||
} catch (e) {
|
||||
console.error("Unable to set language", e);
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyServerConfig() {
|
||||
let validatedConfig;
|
||||
try {
|
||||
console.log("Verifying homeserver configuration");
|
||||
|
||||
// Note: the query string may include is_url and hs_url - we only respect these in the
|
||||
// context of email validation. Because we don't respect them otherwise, we do not need
|
||||
// to parse or consider them here.
|
||||
|
||||
// Note: Although we throw all 3 possible configuration options through a .well-known-style
|
||||
// verification, we do not care if the servers are online at this point. We do moderately
|
||||
// care if they are syntactically correct though, so we shove them through the .well-known
|
||||
// validators for that purpose.
|
||||
|
||||
const config = SdkConfig.get();
|
||||
let wkConfig = config['default_server_config']; // overwritten later under some conditions
|
||||
const serverName = config['default_server_name'];
|
||||
const hsUrl = config['default_hs_url'];
|
||||
const isUrl = config['default_is_url'];
|
||||
|
||||
const incompatibleOptions = [wkConfig, serverName, hsUrl].filter(i => !!i);
|
||||
if (incompatibleOptions.length > 1) {
|
||||
// noinspection ExceptionCaughtLocallyJS
|
||||
throw newTranslatableError(_td(
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, " +
|
||||
"or default_hs_url.",
|
||||
));
|
||||
}
|
||||
if (incompatibleOptions.length < 1) {
|
||||
// noinspection ExceptionCaughtLocallyJS
|
||||
throw newTranslatableError(_td("Invalid configuration: no default server specified."));
|
||||
}
|
||||
|
||||
if (hsUrl) {
|
||||
console.log("Config uses a default_hs_url - constructing a default_server_config using this information");
|
||||
console.warn(
|
||||
"DEPRECATED CONFIG OPTION: In the future, default_hs_url will not be accepted. Please use " +
|
||||
"default_server_config instead.",
|
||||
);
|
||||
|
||||
wkConfig = {
|
||||
"m.homeserver": {
|
||||
"base_url": hsUrl,
|
||||
},
|
||||
};
|
||||
if (isUrl) {
|
||||
wkConfig["m.identity_server"] = {
|
||||
"base_url": isUrl,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let discoveryResult = null;
|
||||
if (wkConfig) {
|
||||
console.log("Config uses a default_server_config - validating object");
|
||||
discoveryResult = await AutoDiscovery.fromDiscoveryConfig(wkConfig);
|
||||
}
|
||||
|
||||
if (serverName) {
|
||||
console.log("Config uses a default_server_name - doing .well-known lookup");
|
||||
console.warn(
|
||||
"DEPRECATED CONFIG OPTION: In the future, default_server_name will not be accepted. Please " +
|
||||
"use default_server_config instead.",
|
||||
);
|
||||
discoveryResult = await AutoDiscovery.findClientConfig(serverName);
|
||||
}
|
||||
|
||||
validatedConfig = AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, discoveryResult, true);
|
||||
} catch (e) {
|
||||
const {hsUrl, isUrl, userId} = Lifecycle.getLocalStorageSessionVars();
|
||||
if (hsUrl && userId) {
|
||||
console.error(e);
|
||||
console.warn("A session was found - suppressing config error and using the session's homeserver");
|
||||
|
||||
console.log("Using pre-existing hsUrl and isUrl: ", {hsUrl, isUrl});
|
||||
validatedConfig = await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(hsUrl, isUrl, true);
|
||||
} else {
|
||||
// the user is not logged in, so scream
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
validatedConfig.isDefault = true;
|
||||
|
||||
// Just in case we ever have to debug this
|
||||
console.log("Using homeserver config:", validatedConfig);
|
||||
|
||||
// Add the newly built config to the actual config for use by the app
|
||||
console.log("Updating SdkConfig with validated discovery information");
|
||||
SdkConfig.add({"validated_server_config": validatedConfig});
|
||||
|
||||
return SdkConfig.get();
|
||||
}
|
||||
@@ -22,6 +22,21 @@
|
||||
<meta name="msapplication-config" content="<%= require('../../res/vector-icons/browserconfig.xml') %>">
|
||||
<meta name="theme-color" content="#ffffff">
|
||||
<meta property="og:image" content="<%= htmlWebpackPlugin.options.vars.og_image_url %>" />
|
||||
<meta http-equiv="Content-Security-Policy" content="
|
||||
default-src 'none';
|
||||
style-src 'self' 'unsafe-inline';
|
||||
script-src 'self' 'unsafe-eval' https://www.recaptcha.net https://www.gstatic.com;
|
||||
img-src * blob: data:;
|
||||
connect-src *;
|
||||
font-src 'self' data:;
|
||||
media-src * blob: data:;
|
||||
child-src * blob: data:;
|
||||
worker-src 'self';
|
||||
frame-src * blob: data:;
|
||||
form-action 'self';
|
||||
object-src 'self';
|
||||
manifest-src 'self';
|
||||
">
|
||||
<% for (var i=0; i < htmlWebpackPlugin.files.css.length; i++) {
|
||||
var file = htmlWebpackPlugin.files.css[i];
|
||||
var match = file.match(/^bundles\/.*?\/theme-(.*)\.css$/);
|
||||
@@ -34,12 +49,9 @@
|
||||
<% }
|
||||
} %>
|
||||
</head>
|
||||
<body style="height: 100%;">
|
||||
<body style="height: 100%;" data-vector-indexeddb-worker-script="<%= htmlWebpackPlugin.files.chunks['indexeddb-worker'].entry %>">
|
||||
<section id="matrixchat" style="height: 100%; overflow: auto;"></section>
|
||||
<noscript>Sorry, Riot requires JavaScript to be enabled.</noscript> <!-- TODO: Translate this? -->
|
||||
<script>
|
||||
window.vector_indexeddb_worker_script = '<%= htmlWebpackPlugin.files.chunks['indexeddb-worker'].entry %>';
|
||||
</script>
|
||||
<script src="<%= htmlWebpackPlugin.files.chunks['bundle'].entry %>"></script>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/warning.svg') %>" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
<img src="<%= require('matrix-react-sdk/res/img/e2e/warning.svg') %>" width="24" height="23" style="visibility: hidden; position: absolute; top: 0px; left: 0px;"/>
|
||||
|
||||
@@ -3,6 +3,7 @@ Copyright 2015, 2016 OpenMarket Ltd
|
||||
Copyright 2017 Vector Creations Ltd
|
||||
Copyright 2018, 2019 New Vector Ltd
|
||||
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
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.
|
||||
@@ -23,474 +24,25 @@ limitations under the License.
|
||||
require('gemini-scrollbar/gemini-scrollbar.css');
|
||||
require('gfm.css/gfm.css');
|
||||
require('highlight.js/styles/github.css');
|
||||
require('draft-js/dist/Draft.css');
|
||||
|
||||
import olmWasmPath from 'olm/olm.wasm';
|
||||
|
||||
// These are things that can run before the skin loads - be careful not to reference the react-sdk though.
|
||||
import './rageshakesetup';
|
||||
|
||||
import React from 'react';
|
||||
// add React and ReactPerf to the global namespace, to make them easier to
|
||||
// access via the console
|
||||
global.React = React;
|
||||
|
||||
import './modernizr';
|
||||
import ReactDOM from 'react-dom';
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
||||
sdk.loadSkin(require('../component-index'));
|
||||
import VectorConferenceHandler from 'matrix-react-sdk/lib/VectorConferenceHandler';
|
||||
import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
|
||||
import {_t, _td, newTranslatableError} from 'matrix-react-sdk/lib/languageHandler';
|
||||
import AutoDiscoveryUtils from 'matrix-react-sdk/lib/utils/AutoDiscoveryUtils';
|
||||
import {AutoDiscovery} from "matrix-js-sdk/lib/autodiscovery";
|
||||
import * as Lifecycle from "matrix-react-sdk/lib/Lifecycle";
|
||||
|
||||
import url from 'url';
|
||||
|
||||
import {parseQs, parseQsFromFragment} from './url_utils';
|
||||
|
||||
import ElectronPlatform from './platform/ElectronPlatform';
|
||||
import WebPlatform from './platform/WebPlatform';
|
||||
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
import SettingsStore from "matrix-react-sdk/lib/settings/SettingsStore";
|
||||
import SdkConfig from "matrix-react-sdk/lib/SdkConfig";
|
||||
import {setTheme} from "matrix-react-sdk/lib/theme";
|
||||
|
||||
import Olm from 'olm';
|
||||
|
||||
import CallHandler from 'matrix-react-sdk/lib/CallHandler';
|
||||
|
||||
let lastLocationHashSet = null;
|
||||
|
||||
function checkBrowserFeatures(featureList) {
|
||||
if (!window.Modernizr) {
|
||||
console.error("Cannot check features - Modernizr global is missing.");
|
||||
return false;
|
||||
}
|
||||
let featureComplete = true;
|
||||
for (let i = 0; i < featureList.length; i++) {
|
||||
if (window.Modernizr[featureList[i]] === undefined) {
|
||||
console.error(
|
||||
"Looked for feature '%s' but Modernizr has no results for this. " +
|
||||
"Has it been configured correctly?", featureList[i],
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (window.Modernizr[featureList[i]] === false) {
|
||||
console.error("Browser missing feature: '%s'", featureList[i]);
|
||||
// toggle flag rather than return early so we log all missing features
|
||||
// rather than just the first.
|
||||
featureComplete = false;
|
||||
}
|
||||
}
|
||||
return featureComplete;
|
||||
// load service worker if available on this platform
|
||||
if ('serviceWorker' in navigator) {
|
||||
navigator.serviceWorker.register('sw.js');
|
||||
}
|
||||
|
||||
// Parse the given window.location and return parameters that can be used when calling
|
||||
// MatrixChat.showScreen(screen, params)
|
||||
function getScreenFromLocation(location) {
|
||||
const fragparts = parseQsFromFragment(location);
|
||||
return {
|
||||
screen: fragparts.location.substring(1),
|
||||
params: fragparts.params,
|
||||
};
|
||||
}
|
||||
// Ensure the skin is the very first thing to load for the react-sdk. We don't even want to reference
|
||||
// the SDK until we have to in imports.
|
||||
console.log("Loading skin...");
|
||||
import * as sdk from 'matrix-react-sdk';
|
||||
import * as skin from "../component-index";
|
||||
sdk.loadSkin(skin);
|
||||
console.log("Skin loaded!");
|
||||
|
||||
// Here, we do some crude URL analysis to allow
|
||||
// deep-linking.
|
||||
function routeUrl(location) {
|
||||
if (!window.matrixChat) return;
|
||||
|
||||
console.log("Routing URL ", location.href);
|
||||
const s = getScreenFromLocation(location);
|
||||
window.matrixChat.showScreen(s.screen, s.params);
|
||||
}
|
||||
|
||||
function onHashChange(ev) {
|
||||
if (decodeURIComponent(window.location.hash) === lastLocationHashSet) {
|
||||
// we just set this: no need to route it!
|
||||
return;
|
||||
}
|
||||
routeUrl(window.location);
|
||||
}
|
||||
|
||||
// This will be called whenever the SDK changes screens,
|
||||
// so a web page can update the URL bar appropriately.
|
||||
function onNewScreen(screen) {
|
||||
console.log("newscreen "+screen);
|
||||
const hash = '#/' + screen;
|
||||
lastLocationHashSet = hash;
|
||||
window.location.hash = hash;
|
||||
}
|
||||
|
||||
// We use this to work out what URL the SDK should
|
||||
// pass through when registering to allow the user to
|
||||
// click back to the client having registered.
|
||||
// It's up to us to recognise if we're loaded with
|
||||
// this URL and tell MatrixClient to resume registration.
|
||||
//
|
||||
// If we're in electron, we should never pass through a file:// URL otherwise
|
||||
// the identity server will try to 302 the browser to it, which breaks horribly.
|
||||
// so in that instance, hardcode to use riot.im/app for now instead.
|
||||
function makeRegistrationUrl(params) {
|
||||
let url;
|
||||
if (window.location.protocol === "vector:") {
|
||||
url = 'https://riot.im/app/#/register';
|
||||
} else {
|
||||
url = (
|
||||
window.location.protocol + '//' +
|
||||
window.location.host +
|
||||
window.location.pathname +
|
||||
'#/register'
|
||||
);
|
||||
}
|
||||
|
||||
const keys = Object.keys(params);
|
||||
for (let i = 0; i < keys.length; ++i) {
|
||||
if (i === 0) {
|
||||
url += '?';
|
||||
} else {
|
||||
url += '&';
|
||||
}
|
||||
const k = keys[i];
|
||||
url += k + '=' + encodeURIComponent(params[k]);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
||||
function onTokenLoginCompleted() {
|
||||
// if we did a token login, we're now left with the token, hs and is
|
||||
// url as query params in the url; a little nasty but let's redirect to
|
||||
// clear them.
|
||||
const parsedUrl = url.parse(window.location.href);
|
||||
parsedUrl.search = "";
|
||||
const formatted = url.format(parsedUrl);
|
||||
console.log("Redirecting to " + formatted + " to drop loginToken " +
|
||||
"from queryparams");
|
||||
window.location.href = formatted;
|
||||
}
|
||||
|
||||
async function loadApp() {
|
||||
if (window.vector_indexeddb_worker_script === undefined) {
|
||||
// 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 new Error("Missing indexeddb worker script!");
|
||||
}
|
||||
MatrixClientPeg.setIndexedDbWorkerScript(window.vector_indexeddb_worker_script);
|
||||
CallHandler.setConferenceHandler(VectorConferenceHandler);
|
||||
|
||||
window.addEventListener('hashchange', onHashChange);
|
||||
|
||||
await loadOlm();
|
||||
|
||||
// set the platform for react sdk
|
||||
if (window.ipcRenderer) {
|
||||
console.log("Using Electron platform");
|
||||
const plaf = new ElectronPlatform();
|
||||
PlatformPeg.set(plaf);
|
||||
|
||||
// Electron only: see if we need to do a one-time data
|
||||
// migration
|
||||
if (window.localStorage.getItem('mx_user_id') === null) {
|
||||
console.log("Migrating session from old origin...");
|
||||
await plaf.migrateFromOldOrigin();
|
||||
console.log("Origin migration complete");
|
||||
}
|
||||
} else {
|
||||
console.log("Using Web platform");
|
||||
PlatformPeg.set(new WebPlatform());
|
||||
}
|
||||
|
||||
const platform = PlatformPeg.get();
|
||||
|
||||
let configJson;
|
||||
let configError;
|
||||
let configSyntaxError = false;
|
||||
try {
|
||||
configJson = await platform.getConfig();
|
||||
} catch (e) {
|
||||
configError = e;
|
||||
|
||||
if (e && e.err && e.err instanceof SyntaxError) {
|
||||
console.error("SyntaxError loading config:", e);
|
||||
configSyntaxError = true;
|
||||
configJson = {}; // to prevent errors between here and loading CSS for the error box
|
||||
}
|
||||
}
|
||||
|
||||
// XXX: We call this twice, once here and once in MatrixChat as a prop. We call it here to ensure
|
||||
// granular settings are loaded correctly and to avoid duplicating the override logic for the theme.
|
||||
SdkConfig.put(configJson);
|
||||
|
||||
// Load language after loading config.json so that settingsDefaults.language can be applied
|
||||
await loadLanguage();
|
||||
|
||||
const fragparts = parseQsFromFragment(window.location);
|
||||
const params = parseQs(window.location);
|
||||
|
||||
// don't try to redirect to the native apps if we're
|
||||
// verifying a 3pid (but after we've loaded the config)
|
||||
// or if the user is following a deep link
|
||||
// (https://github.com/vector-im/riot-web/issues/7378)
|
||||
const preventRedirect = fragparts.params.client_secret || fragparts.location.length > 0;
|
||||
|
||||
if (!preventRedirect) {
|
||||
const isIos = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;
|
||||
const isAndroid = /Android/.test(navigator.userAgent);
|
||||
if (isIos || isAndroid) {
|
||||
if (document.cookie.indexOf("riot_mobile_redirect_to_guide=false") === -1) {
|
||||
window.location = "mobile_guide/";
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// as quickly as we possibly can, set a default theme...
|
||||
await setTheme();
|
||||
|
||||
// Now that we've loaded the theme (CSS), display the config syntax error if needed.
|
||||
if (configSyntaxError) {
|
||||
const errorMessage = (
|
||||
<div>
|
||||
<p>
|
||||
{_t(
|
||||
"Your Riot configuration contains invalid JSON. Please correct the problem " +
|
||||
"and reload the page.",
|
||||
)}
|
||||
</p>
|
||||
<p>
|
||||
{_t(
|
||||
"The message from the parser is: %(message)s",
|
||||
{message: configError.err.message || _t("Invalid JSON")},
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
|
||||
const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage");
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<GenericErrorPage message={errorMessage} title={_t("Your Riot is misconfigured")} />,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const validBrowser = checkBrowserFeatures([
|
||||
"displaytable", "flexbox", "es5object", "es5function", "localstorage",
|
||||
"objectfit", "indexeddb", "webworkers",
|
||||
]);
|
||||
|
||||
const acceptInvalidBrowser = window.localStorage && window.localStorage.getItem('mx_accepts_unsupported_browser');
|
||||
|
||||
const urlWithoutQuery = window.location.protocol + '//' + window.location.host + window.location.pathname;
|
||||
console.log("Vector starting at " + urlWithoutQuery);
|
||||
if (configError) {
|
||||
window.matrixChat = ReactDOM.render(<div className="error">
|
||||
Unable to load config file: please refresh the page to try again.
|
||||
</div>, document.getElementById('matrixchat'));
|
||||
} else if (validBrowser || acceptInvalidBrowser) {
|
||||
platform.startUpdater();
|
||||
|
||||
// Don't bother loading the app until the config is verified
|
||||
verifyServerConfig().then((newConfig) => {
|
||||
const MatrixChat = sdk.getComponent('structures.MatrixChat');
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<MatrixChat
|
||||
onNewScreen={onNewScreen}
|
||||
makeRegistrationUrl={makeRegistrationUrl}
|
||||
ConferenceHandler={VectorConferenceHandler}
|
||||
config={newConfig}
|
||||
realQueryParams={params}
|
||||
startingFragmentQueryParams={fragparts.params}
|
||||
enableGuest={!configJson.disable_guests}
|
||||
onTokenLoginCompleted={onTokenLoginCompleted}
|
||||
initialScreenAfterLogin={getScreenFromLocation(window.location)}
|
||||
defaultDeviceDisplayName={platform.getDefaultDeviceDisplayName()}
|
||||
/>,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
}).catch(err => {
|
||||
console.error(err);
|
||||
|
||||
let errorMessage = err.translatedMessage
|
||||
|| _t("Unexpected error preparing the app. See console for details.");
|
||||
errorMessage = <span>{errorMessage}</span>;
|
||||
|
||||
// Like the compatibility page, AWOOOOOGA at the user
|
||||
const GenericErrorPage = sdk.getComponent("structures.GenericErrorPage");
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<GenericErrorPage message={errorMessage} title={_t("Your Riot is misconfigured")} />,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
});
|
||||
} else {
|
||||
console.error("Browser is missing required features.");
|
||||
// take to a different landing page to AWOOOOOGA at the user
|
||||
const CompatibilityPage = sdk.getComponent("structures.CompatibilityPage");
|
||||
window.matrixChat = ReactDOM.render(
|
||||
<CompatibilityPage onAccept={function() {
|
||||
if (window.localStorage) window.localStorage.setItem('mx_accepts_unsupported_browser', true);
|
||||
console.log("User accepts the compatibility risks.");
|
||||
loadApp();
|
||||
}} />,
|
||||
document.getElementById('matrixchat'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function loadOlm() {
|
||||
/* Load Olm. We try the WebAssembly version first, and then the legacy,
|
||||
* asm.js version if that fails. For this reason we need to wait for this
|
||||
* to finish before continuing to load the rest of the app. In future
|
||||
* we could somehow pass a promise down to react-sdk and have it wait on
|
||||
* that so olm can be loading in parallel with the rest of the app.
|
||||
*
|
||||
* We also need to tell the Olm js to look for its wasm file at the same
|
||||
* level as index.html. It really should be in the same place as the js,
|
||||
* ie. in the bundle directory, but as far as I can tell this is
|
||||
* completely impossible with webpack. We do, however, use a hashed
|
||||
* filename to avoid caching issues.
|
||||
*/
|
||||
return Olm.init({
|
||||
locateFile: () => olmWasmPath,
|
||||
}).then(() => {
|
||||
console.log("Using WebAssembly Olm");
|
||||
}).catch((e) => {
|
||||
console.log("Failed to load Olm: trying legacy version", e);
|
||||
return new Promise((resolve, reject) => {
|
||||
const s = document.createElement('script');
|
||||
s.src = 'olm_legacy.js'; // XXX: This should be cache-busted too
|
||||
s.onload = resolve;
|
||||
s.onerror = reject;
|
||||
document.body.appendChild(s);
|
||||
}).then(() => {
|
||||
// Init window.Olm, ie. the one just loaded by the script tag,
|
||||
// not 'Olm' which is still the failed wasm version.
|
||||
return window.Olm.init();
|
||||
}).then(() => {
|
||||
console.log("Using legacy Olm");
|
||||
}).catch((e) => {
|
||||
console.log("Both WebAssembly and asm.js Olm failed!", e);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function loadLanguage() {
|
||||
const prefLang = SettingsStore.getValue("language", null, /*excludeDefault=*/true);
|
||||
let langs = [];
|
||||
|
||||
if (!prefLang) {
|
||||
languageHandler.getLanguagesFromBrowser().forEach((l) => {
|
||||
langs.push(...languageHandler.getNormalizedLanguageKeys(l));
|
||||
});
|
||||
} else {
|
||||
langs = [prefLang];
|
||||
}
|
||||
try {
|
||||
await languageHandler.setLanguage(langs);
|
||||
document.documentElement.setAttribute("lang", languageHandler.getCurrentLanguage());
|
||||
} catch (e) {
|
||||
console.error("Unable to set language", e);
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyServerConfig() {
|
||||
let validatedConfig;
|
||||
try {
|
||||
console.log("Verifying homeserver configuration");
|
||||
|
||||
// Note: the query string may include is_url and hs_url - we only respect these in the
|
||||
// context of email validation. Because we don't respect them otherwise, we do not need
|
||||
// to parse or consider them here.
|
||||
|
||||
// Note: Although we throw all 3 possible configuration options through a .well-known-style
|
||||
// verification, we do not care if the servers are online at this point. We do moderately
|
||||
// care if they are syntactically correct though, so we shove them through the .well-known
|
||||
// validators for that purpose.
|
||||
|
||||
const config = SdkConfig.get();
|
||||
let wkConfig = config['default_server_config']; // overwritten later under some conditions
|
||||
const serverName = config['default_server_name'];
|
||||
const hsUrl = config['default_hs_url'];
|
||||
const isUrl = config['default_is_url'];
|
||||
|
||||
const incompatibleOptions = [wkConfig, serverName, hsUrl].filter(i => !!i);
|
||||
if (incompatibleOptions.length > 1) {
|
||||
// noinspection ExceptionCaughtLocallyJS
|
||||
throw newTranslatableError(_td(
|
||||
"Invalid configuration: can only specify one of default_server_config, default_server_name, " +
|
||||
"or default_hs_url.",
|
||||
));
|
||||
}
|
||||
if (incompatibleOptions.length < 1) {
|
||||
// noinspection ExceptionCaughtLocallyJS
|
||||
throw newTranslatableError(_td("Invalid configuration: no default server specified."));
|
||||
}
|
||||
|
||||
if (hsUrl) {
|
||||
console.log("Config uses a default_hs_url - constructing a default_server_config using this information");
|
||||
console.warn(
|
||||
"DEPRECATED CONFIG OPTION: In the future, default_hs_url will not be accepted. Please use " +
|
||||
"default_server_config instead.",
|
||||
);
|
||||
|
||||
wkConfig = {
|
||||
"m.homeserver": {
|
||||
"base_url": hsUrl,
|
||||
},
|
||||
};
|
||||
if (isUrl) {
|
||||
wkConfig["m.identity_server"] = {
|
||||
"base_url": isUrl,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
let discoveryResult = null;
|
||||
if (wkConfig) {
|
||||
console.log("Config uses a default_server_config - validating object");
|
||||
discoveryResult = await AutoDiscovery.fromDiscoveryConfig(wkConfig);
|
||||
}
|
||||
|
||||
if (serverName) {
|
||||
console.log("Config uses a default_server_name - doing .well-known lookup");
|
||||
console.warn(
|
||||
"DEPRECATED CONFIG OPTION: In the future, default_server_name will not be accepted. Please " +
|
||||
"use default_server_config instead.",
|
||||
);
|
||||
discoveryResult = await AutoDiscovery.findClientConfig(serverName);
|
||||
}
|
||||
|
||||
validatedConfig = AutoDiscoveryUtils.buildValidatedConfigFromDiscovery(serverName, discoveryResult, true);
|
||||
} catch (e) {
|
||||
const {hsUrl, isUrl, userId} = Lifecycle.getLocalStorageSessionVars();
|
||||
if (hsUrl && userId) {
|
||||
console.error(e);
|
||||
console.warn("A session was found - suppressing config error and using the session's homeserver");
|
||||
|
||||
console.log("Using pre-existing hsUrl and isUrl: ", {hsUrl, isUrl});
|
||||
validatedConfig = await AutoDiscoveryUtils.validateServerConfigWithStaticUrls(hsUrl, isUrl, true);
|
||||
} else {
|
||||
// the user is not logged in, so scream
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
validatedConfig.isDefault = true;
|
||||
|
||||
// Just in case we ever have to debug this
|
||||
console.log("Using homeserver config:", validatedConfig);
|
||||
|
||||
// Add the newly built config to the actual config for use by the app
|
||||
console.log("Updating SdkConfig with validated discovery information");
|
||||
SdkConfig.add({"validated_server_config": validatedConfig});
|
||||
|
||||
return SdkConfig.get();
|
||||
}
|
||||
|
||||
loadApp();
|
||||
// Finally, load the app. All of the other react-sdk imports are in this file which causes the skinner to
|
||||
// run on the components. We use `require` here to make sure webpack doesn't optimize this into an async
|
||||
// import and thus running before the skin can load.
|
||||
require("./app").loadApp();
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import {IndexedDBStoreWorker} from 'matrix-js-sdk/lib/indexeddb-worker.js';
|
||||
import {IndexedDBStoreWorker} from 'matrix-js-sdk/src/indexeddb-worker.js';
|
||||
|
||||
const remoteWorker = new IndexedDBStoreWorker(postMessage);
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -20,10 +20,10 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform';
|
||||
import BaseEventIndexManager from 'matrix-react-sdk/lib/indexing/BaseEventIndexManager';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import rageshake from 'matrix-react-sdk/lib/rageshake/rageshake';
|
||||
import BaseEventIndexManager from 'matrix-react-sdk/src/indexing/BaseEventIndexManager';
|
||||
import dis from 'matrix-react-sdk/src/dispatcher';
|
||||
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
||||
import * as rageshake from 'matrix-react-sdk/src/rageshake/rageshake';
|
||||
|
||||
const ipcRenderer = window.ipcRenderer;
|
||||
|
||||
@@ -144,6 +144,10 @@ class SeshatIndexManager extends BaseEventIndexManager {
|
||||
return this._ipcCall('removeCrawlerCheckpoint', checkpoint);
|
||||
}
|
||||
|
||||
async loadFileEvents(args): Promise<[EventAndProfile]> {
|
||||
return this._ipcCall('loadFileEvents', args);
|
||||
}
|
||||
|
||||
async loadCheckpoints(): Promise<[CrawlerCheckpoint]> {
|
||||
return this._ipcCall('loadCheckpoints');
|
||||
}
|
||||
@@ -152,6 +156,10 @@ class SeshatIndexManager extends BaseEventIndexManager {
|
||||
return this._ipcCall('closeEventIndex');
|
||||
}
|
||||
|
||||
async getStats(): Promise<> {
|
||||
return this._ipcCall('getStats');
|
||||
}
|
||||
|
||||
async deleteEventIndex(): Promise<> {
|
||||
return this._ipcCall('deleteEventIndex');
|
||||
}
|
||||
@@ -355,10 +363,6 @@ export default class ElectronPlatform extends VectorBasePlatform {
|
||||
window.location.reload(false);
|
||||
}
|
||||
|
||||
async migrateFromOldOrigin() {
|
||||
return this._ipcCall('origin_migrate');
|
||||
}
|
||||
|
||||
async _ipcCall(name, ...args) {
|
||||
const ipcCallId = ++this._nextIpcCallId;
|
||||
return new Promise((resolve, reject) => {
|
||||
|
||||
@@ -19,9 +19,9 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import BasePlatform from 'matrix-react-sdk/lib/BasePlatform';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
import BasePlatform from 'matrix-react-sdk/src/BasePlatform';
|
||||
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
||||
import dis from 'matrix-react-sdk/src/dispatcher';
|
||||
import {getVectorConfig} from "../getconfig";
|
||||
|
||||
import Favico from 'favico.js';
|
||||
@@ -173,12 +173,4 @@ export default class VectorBasePlatform extends BasePlatform {
|
||||
getDefaultDeviceDisplayName(): string {
|
||||
return _t("Unknown device");
|
||||
}
|
||||
|
||||
/**
|
||||
* Migrate account data from a previous origin
|
||||
* Used only for the electron app
|
||||
*/
|
||||
async migrateFromOldOrigin() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,8 +19,8 @@ limitations under the License.
|
||||
|
||||
import VectorBasePlatform, {updateCheckStatusEnum} from './VectorBasePlatform';
|
||||
import request from 'browser-request';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher.js';
|
||||
import { _t } from 'matrix-react-sdk/lib/languageHandler';
|
||||
import dis from 'matrix-react-sdk/src/dispatcher.js';
|
||||
import { _t } from 'matrix-react-sdk/src/languageHandler';
|
||||
|
||||
import url from 'url';
|
||||
import UAParser from 'ua-parser-js';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright 2018 New Vector Ltd
|
||||
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.
|
||||
@@ -25,8 +26,9 @@ limitations under the License.
|
||||
* from the rageshake.)
|
||||
*/
|
||||
|
||||
import rageshake from "matrix-react-sdk/lib/rageshake/rageshake";
|
||||
import SdkConfig from "matrix-react-sdk/lib/SdkConfig";
|
||||
import * as rageshake from "matrix-react-sdk/src/rageshake/rageshake";
|
||||
import SdkConfig from "matrix-react-sdk/src/SdkConfig";
|
||||
import sendBugReport from "matrix-react-sdk/src/rageshake/submit-rageshake";
|
||||
|
||||
function initRageshake() {
|
||||
rageshake.init().then(() => {
|
||||
@@ -54,15 +56,13 @@ global.mxSendRageshake = function(text, withLogs) {
|
||||
console.error("Cannot send a rageshake without a message - please tell us what went wrong");
|
||||
return;
|
||||
}
|
||||
require(['matrix-react-sdk/lib/rageshake/submit-rageshake'], (s) => {
|
||||
s(SdkConfig.get().bug_report_endpoint_url, {
|
||||
userText: text,
|
||||
sendLogs: withLogs,
|
||||
progressCallback: console.log.bind(console),
|
||||
}).then(() => {
|
||||
console.log("Bug report sent!");
|
||||
}, (err) => {
|
||||
console.error(err);
|
||||
});
|
||||
sendBugReport(SdkConfig.get().bug_report_endpoint_url, {
|
||||
userText: text,
|
||||
sendLogs: withLogs,
|
||||
progressCallback: console.log.bind(console),
|
||||
}).then(() => {
|
||||
console.log("Bug report sent!");
|
||||
}, (err) => {
|
||||
console.error(err);
|
||||
});
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import qs from 'querystring';
|
||||
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
|
||||
@@ -1,13 +0,0 @@
|
||||
// all-tests.js
|
||||
//
|
||||
// Our master test file: uses the webpack require API to find our test files
|
||||
// and run them
|
||||
|
||||
// ideally these unit tests could be run under nodejs rather than in a browser
|
||||
// via karma, but having two separate test frameworks in the same project
|
||||
// seems confusing
|
||||
const unit_tests = require.context('./unit-tests', true, /\.js$/);
|
||||
unit_tests.keys().forEach(unit_tests);
|
||||
|
||||
const app_tests = require.context('./app-tests', true, /\.jsx?$/);
|
||||
app_tests.keys().forEach(app_tests);
|
||||
@@ -16,30 +16,28 @@ limitations under the License.
|
||||
|
||||
/* joining.js: tests for the various paths when joining a room */
|
||||
|
||||
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
||||
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
||||
import WebPlatform from '../../src/vector/platform/WebPlatform';
|
||||
import * as sdk from "matrix-react-sdk";
|
||||
import * as jssdk from "matrix-js-sdk";
|
||||
import "../skin-sdk";
|
||||
import "../jest-mocks";
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom";
|
||||
import ReactTestUtils from "react-dom/test-utils";
|
||||
import {makeType} from "matrix-react-sdk/src/utils/TypeUtils";
|
||||
import {ValidatedServerConfig} from "matrix-react-sdk/src/utils/AutoDiscoveryUtils";
|
||||
import {sleep} from "../test-utils";
|
||||
import * as test_utils from "../test-utils";
|
||||
import MockHttpBackend from "matrix-mock-request";
|
||||
import "fake-indexeddb/auto";
|
||||
|
||||
require('skin-sdk');
|
||||
|
||||
const jssdk = require('matrix-js-sdk');
|
||||
|
||||
const sdk = require('matrix-react-sdk');
|
||||
const MatrixChat = sdk.getComponent('structures.MatrixChat');
|
||||
const RoomDirectory = sdk.getComponent('structures.RoomDirectory');
|
||||
const RoomPreviewBar = sdk.getComponent('rooms.RoomPreviewBar');
|
||||
const RoomView = sdk.getComponent('structures.RoomView');
|
||||
|
||||
const React = require('react');
|
||||
const ReactDOM = require('react-dom');
|
||||
const ReactTestUtils = require('react-dom/test-utils');
|
||||
const expect = require('expect');
|
||||
import {makeType} from "matrix-react-sdk/lib/utils/TypeUtils";
|
||||
import {ValidatedServerConfig} from "matrix-react-sdk/lib/utils/AutoDiscoveryUtils";
|
||||
import {sleep} from "../test-utils";
|
||||
|
||||
const test_utils = require('../test-utils');
|
||||
const MockHttpBackend = require('matrix-mock-request');
|
||||
|
||||
const HS_URL='http://localhost';
|
||||
const IS_URL='http://localhost';
|
||||
const USER_ID='@me:localhost';
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
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.
|
||||
@@ -16,46 +17,32 @@ limitations under the License.
|
||||
|
||||
/* loading.js: test the myriad paths we have for loading the application */
|
||||
|
||||
import PlatformPeg from 'matrix-react-sdk/lib/PlatformPeg';
|
||||
import PlatformPeg from 'matrix-react-sdk/src/PlatformPeg';
|
||||
import WebPlatform from '../../src/vector/platform/WebPlatform';
|
||||
|
||||
import 'skin-sdk';
|
||||
|
||||
import '../skin-sdk';
|
||||
import "../jest-mocks";
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import ReactTestUtils from 'react-dom/test-utils';
|
||||
import expect from 'expect';
|
||||
import MatrixReactTestUtils from 'matrix-react-test-utils';
|
||||
|
||||
import jssdk from 'matrix-js-sdk';
|
||||
|
||||
import sdk from 'matrix-react-sdk';
|
||||
import MatrixClientPeg from 'matrix-react-sdk/lib/MatrixClientPeg';
|
||||
import * as languageHandler from 'matrix-react-sdk/lib/languageHandler';
|
||||
import {VIEWS} from 'matrix-react-sdk/lib/components/structures/MatrixChat';
|
||||
import dis from 'matrix-react-sdk/lib/dispatcher';
|
||||
|
||||
import * as jssdk from 'matrix-js-sdk';
|
||||
import * as sdk from 'matrix-react-sdk';
|
||||
import {MatrixClientPeg} from 'matrix-react-sdk/src/MatrixClientPeg';
|
||||
import {VIEWS} from 'matrix-react-sdk/src/components/structures/MatrixChat';
|
||||
import dis from 'matrix-react-sdk/src/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/lib/utils/TypeUtils";
|
||||
import {ValidatedServerConfig} from "matrix-react-sdk/lib/utils/AutoDiscoveryUtils";
|
||||
import {makeType} from "matrix-react-sdk/src/utils/TypeUtils";
|
||||
import {ValidatedServerConfig} from "matrix-react-sdk/src/utils/AutoDiscoveryUtils";
|
||||
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";
|
||||
|
||||
const DEFAULT_HS_URL='http://my_server';
|
||||
const DEFAULT_IS_URL='http://my_is';
|
||||
|
||||
expect.extend({
|
||||
toStartWith(prefix) {
|
||||
expect.assert(
|
||||
this.actual.startsWith(prefix),
|
||||
'expected %s to start with %s',
|
||||
this.actual, prefix,
|
||||
);
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
describe('loading:', function() {
|
||||
let parentDiv;
|
||||
let httpBackend;
|
||||
@@ -70,7 +57,6 @@ describe('loading:', function() {
|
||||
let tokenLoginCompletePromise;
|
||||
|
||||
beforeEach(function() {
|
||||
test_utils.beforeEach(this);
|
||||
httpBackend = new MockHttpBackend();
|
||||
jssdk.request(httpBackend.requestFn);
|
||||
parentDiv = document.createElement('div');
|
||||
@@ -81,10 +67,6 @@ describe('loading:', function() {
|
||||
|
||||
windowLocation = null;
|
||||
matrixChat = null;
|
||||
|
||||
languageHandler.setMissingEntryGenerator(function(key) {
|
||||
return key.split('|', 2)[1];
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(async function() {
|
||||
@@ -98,14 +80,12 @@ describe('loading:', function() {
|
||||
// unmounting should have cleared the MatrixClientPeg
|
||||
expect(MatrixClientPeg.get()).toBe(null);
|
||||
|
||||
// chrome seems to take *ages* to delete the indexeddbs.
|
||||
this.timeout(10000);
|
||||
|
||||
// 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();
|
||||
console.log(`${Date.now()}: loading: afterEach complete`);
|
||||
});
|
||||
|
||||
@@ -323,7 +303,7 @@ describe('loading:', function() {
|
||||
localStorage.setItem("mx_last_room_id", "!last_room:id");
|
||||
|
||||
// Create a crypto store as well to satisfy storage consistency checks
|
||||
const cryptoStore = new jssdk.IndexedDBCryptoStore(
|
||||
const cryptoStore = new IndexedDBCryptoStore(
|
||||
indexedDB,
|
||||
"matrix-js-sdk:crypto",
|
||||
);
|
||||
@@ -481,7 +461,7 @@ describe('loading:', function() {
|
||||
assertAtLoadingSpinner(matrixChat);
|
||||
|
||||
httpBackend.when('POST', '/register').check(function(req) {
|
||||
expect(req.path).toStartWith(DEFAULT_HS_URL);
|
||||
expect(req.path.startsWith(DEFAULT_HS_URL)).toBe(true);
|
||||
expect(req.queryParams.kind).toEqual('guest');
|
||||
}).respond(200, {
|
||||
user_id: "@guest:localhost",
|
||||
@@ -494,7 +474,7 @@ describe('loading:', function() {
|
||||
}).then(() => {
|
||||
return expectAndAwaitSync({isGuest: true});
|
||||
}).then((req) => {
|
||||
expect(req.path).toStartWith(DEFAULT_HS_URL);
|
||||
expect(req.path.startsWith(DEFAULT_HS_URL)).toBe(true);
|
||||
|
||||
// once the sync completes, we should have a welcome page
|
||||
httpBackend.verifyNoOutstandingExpectation();
|
||||
@@ -682,10 +662,6 @@ describe('loading:', function() {
|
||||
// Wait for another trip around the event loop for the UI to update
|
||||
return sleep(1);
|
||||
}).then(() => {
|
||||
// we expect a spinner
|
||||
ReactTestUtils.findRenderedComponentWithType(
|
||||
matrixChat, sdk.getComponent('elements.Spinner'));
|
||||
|
||||
httpBackend.when('GET', '/pushrules').respond(200, {});
|
||||
httpBackend.when('POST', '/filter').respond(200, { filter_id: 'fid' });
|
||||
return expectAndAwaitSync().catch((e) => {
|
||||
14
test/jest-mocks.js
Normal file
14
test/jest-mocks.js
Normal file
@@ -0,0 +1,14 @@
|
||||
// https://jestjs.io/docs/en/manual-mocks#mocking-methods-which-are-not-implemented-in-jsdom
|
||||
Object.defineProperty(window, 'matchMedia', {
|
||||
writable: true,
|
||||
value: jest.fn().mockImplementation(query => ({
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: jest.fn(), // deprecated
|
||||
removeListener: jest.fn(), // deprecated
|
||||
addEventListener: jest.fn(),
|
||||
removeEventListener: jest.fn(),
|
||||
dispatchEvent: jest.fn(),
|
||||
})),
|
||||
});
|
||||
@@ -4,5 +4,6 @@
|
||||
* Skins the react-sdk with the vector components
|
||||
*/
|
||||
|
||||
const sdk = require('matrix-react-sdk');
|
||||
sdk.loadSkin(require('../src/component-index'));
|
||||
import * as sdk from "matrix-react-sdk";
|
||||
import * as skin from "../src/component-index";
|
||||
sdk.loadSkin(skin);
|
||||
|
||||
@@ -1,30 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Perform common actions before each test case, e.g. printing the test case
|
||||
* name to stdout.
|
||||
* @param {Mocha.Context} context The test context
|
||||
*/
|
||||
export function beforeEach(context) {
|
||||
const desc = context.currentTest.fullTitle();
|
||||
console.log();
|
||||
console.log(desc);
|
||||
console.log(new Array(1 + desc.length).join("="));
|
||||
|
||||
// some tests store things in localstorage. Improve independence of tests
|
||||
// by making sure that they don't inherit any old state.
|
||||
export function cleanLocalstorage() {
|
||||
window.localStorage.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* returns true if the current environment supports webrtc
|
||||
*/
|
||||
export function browserSupportsWebRTC() {
|
||||
const n = global.window.navigator;
|
||||
return n.getUserMedia || n.webkitGetUserMedia ||
|
||||
n.mozGetUserMedia;
|
||||
}
|
||||
|
||||
export function deleteIndexedDB(dbName) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (!window.indexedDB) {
|
||||
|
||||
19
tsconfig.json
Normal file
19
tsconfig.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2016",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false,
|
||||
"outDir": "./lib",
|
||||
"declaration": true,
|
||||
"types": [
|
||||
"node"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./src/**/*.ts"
|
||||
]
|
||||
}
|
||||
@@ -1,213 +1,353 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const ExtractTextPlugin = require('extract-text-webpack-plugin');
|
||||
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 webpack = require("webpack");
|
||||
|
||||
let og_image_url = process.env.RIOT_OG_IMAGE_URL;
|
||||
if (!og_image_url) og_image_url = 'https://riot.im/app/themes/riot/img/logos/riot-im-logo-black-text.png';
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
// Load babel-polyfill first to avoid issues where some imports (namely react)
|
||||
// are potentially loaded before babel-polyfill.
|
||||
"bundle": ["babel-polyfill", "./src/vector/index.js"],
|
||||
"indexeddb-worker": "./src/vector/indexeddb-worker.js",
|
||||
module.exports = (env, argv) => {
|
||||
if (process.env.CI_PACKAGE) {
|
||||
// Don't run minification for CI builds (this is only set for runs on develop)
|
||||
argv.mode = "development";
|
||||
}
|
||||
|
||||
"mobileguide": "./src/vector/mobile_guide/index.js",
|
||||
const development = {};
|
||||
if (argv.mode !== "production") {
|
||||
// This makes the sourcemaps human readable for developers. We use eval-source-map
|
||||
// because the plain source-map devtool ruins the alignment.
|
||||
development['devtool'] = 'eval-source-map';
|
||||
}
|
||||
|
||||
// CSS themes
|
||||
"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",
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{ enforce: 'pre', test: /\.js$/, use: "source-map-loader", exclude: /node_modules/, },
|
||||
{ test: /\.js$/, use: "babel-loader", include: path.resolve(__dirname, 'src') },
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
loader: "file-loader",
|
||||
type: "javascript/auto", // https://github.com/webpack/webpack/issues/6725
|
||||
options: {
|
||||
name: '[name].[hash:7].[ext]',
|
||||
outputPath: '.',
|
||||
// Resolve the directories for the react-sdk and js-sdk for later use. We resolve these early so we
|
||||
// don't have to call them over and over. We also resolve to the package.json instead of the src
|
||||
// directory so we don't have to rely on a index.js or similar file existing.
|
||||
const reactSdkSrcDir = path.resolve(require.resolve("matrix-react-sdk/package.json"), '..', 'src');
|
||||
const jsSdkSrcDir = path.resolve(require.resolve("matrix-js-sdk/package.json"), '..', 'src');
|
||||
|
||||
return {
|
||||
...development,
|
||||
|
||||
entry: {
|
||||
"bundle": "./src/vector/index.js",
|
||||
"indexeddb-worker": "./src/vector/indexeddb-worker.js",
|
||||
"mobileguide": "./src/vector/mobile_guide/index.js",
|
||||
|
||||
// CSS themes
|
||||
"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: {
|
||||
// Put all of our CSS into one useful place - this is needed for MiniCssExtractPlugin.
|
||||
// Previously we used a different extraction plugin that did this magic for us, but
|
||||
// now we need to consider that the CSS needs to be bundled up together.
|
||||
splitChunks: {
|
||||
cacheGroups: {
|
||||
styles: {
|
||||
name: 'styles',
|
||||
test: /\.css$/,
|
||||
enforce: true,
|
||||
// Do not add `chunks: 'all'` here because you'll break the app entry point.
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
// 1. postcss-loader turns the SCSS into normal CSS.
|
||||
// 2. css-loader turns the CSS into a JS module whose default
|
||||
// export is a string containing the CSS, while also adding
|
||||
// the images and fonts from CSS as Webpack inputs.
|
||||
// 3. ExtractTextPlugin turns that string into a separate asset.
|
||||
use: ExtractTextPlugin.extract({
|
||||
|
||||
// This fixes duplicate files showing up in chrome with sourcemaps enabled.
|
||||
// See https://github.com/webpack/webpack/issues/7128 for more info.
|
||||
namedModules: false,
|
||||
|
||||
// Minification is normally enabled by default for webpack in production mode, but
|
||||
// we use a CSS optimizer too and need to manage it ourselves.
|
||||
minimize: argv.mode === 'production',
|
||||
minimizer: argv.mode === 'production' ? [new TerserPlugin({}), new OptimizeCSSAssetsPlugin({})] : [],
|
||||
},
|
||||
|
||||
resolve: {
|
||||
// We define an alternative import path so we can safely use src/ across the react-sdk
|
||||
// and js-sdk. We already import from src/ where possible to ensure our source maps are
|
||||
// extremely accurate (and because we're capable of compiling the layers manually rather
|
||||
// than relying on partially-mangled output from babel), though we do need to fix the
|
||||
// package level import (stuff like `import {Thing} from "matrix-js-sdk"` for example).
|
||||
// We can't use the aliasing down below to point at src/ because that'll fail to resolve
|
||||
// the package.json for the dependency. Instead, we rely on the package.json of each
|
||||
// layer to have our custom alternate fields to load things in the right order. These are
|
||||
// the defaults of webpack prepended with `matrix_src_`.
|
||||
mainFields: ['matrix_src_browser', 'matrix_src_main', 'browser', 'main'],
|
||||
aliasFields: ['matrix_src_browser', 'browser'],
|
||||
|
||||
// We need to specify that TS can be resolved without an extension
|
||||
extensions: ['.js', '.json', '.ts'],
|
||||
alias: {
|
||||
// alias any requires to the react module to the one in our path,
|
||||
// otherwise we tend to get the react source included twice when
|
||||
// using `npm link` / `yarn link`.
|
||||
"react": path.resolve(__dirname, 'node_modules/react'),
|
||||
"react-dom": path.resolve(__dirname, 'node_modules/react-dom'),
|
||||
|
||||
// same goes for js-sdk - we don't need two copies.
|
||||
"matrix-js-sdk": path.resolve(__dirname, 'node_modules/matrix-js-sdk'),
|
||||
|
||||
// Define a variable so the i18n stuff can load
|
||||
"$webapp": path.resolve(__dirname, 'webapp'),
|
||||
},
|
||||
},
|
||||
|
||||
module: {
|
||||
noParse: [
|
||||
// for cross platform compatibility use [\\\/] as the path separator
|
||||
// this ensures that the regex trips on both Windows and *nix
|
||||
|
||||
// don't parse the languages within highlight.js. They cause stack
|
||||
// overflows (https://github.com/webpack/webpack/issues/1721), and
|
||||
// there is no need for webpack to parse them - they can just be
|
||||
// included as-is.
|
||||
/highlight\.js[\\\/]lib[\\\/]languages/,
|
||||
|
||||
// olm takes ages for webpack to process, and it's already heavily
|
||||
// optimised, so there is little to gain by us uglifying it.
|
||||
/olm[\\\/](javascript[\\\/])?olm\.js$/,
|
||||
],
|
||||
rules: [
|
||||
{
|
||||
test: /\.(ts|js)x?$/,
|
||||
include: (f) => {
|
||||
// our own source needs babel-ing
|
||||
if (f.startsWith(path.resolve(__dirname, 'src'))) return true;
|
||||
|
||||
// we use the original source files of react-sdk and js-sdk, so we need to
|
||||
// run them through babel. Because the path tested is the resolved, absolute
|
||||
// path, these could be anywhere thanks to yarn link. We must also not
|
||||
// include node modules inside these modules, so we add 'src'.
|
||||
if (f.startsWith(reactSdkSrcDir)) return true;
|
||||
if (f.startsWith(jsSdkSrcDir)) return true;
|
||||
|
||||
// but we can't run all of our dependencies through babel (many of them still
|
||||
// use module.exports which breaks if babel injects an 'include' for its
|
||||
// polyfills: probably fixable but babeling all our dependencies is probably
|
||||
// not necessary anyway). So, for anything else, don't babel.
|
||||
return false;
|
||||
},
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true
|
||||
}
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
"css-loader",
|
||||
MiniCssExtractPlugin.loader,
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
ident: 'postcss',
|
||||
options: {
|
||||
config: {
|
||||
path: './postcss.config.js',
|
||||
sourceMap: true,
|
||||
plugins: () => [
|
||||
// Note that we use significantly fewer plugins on the plain
|
||||
// CSS parser. If we start to parse plain CSS, we end with all
|
||||
// kinds of nasty problems (like stylesheets not loading).
|
||||
//
|
||||
// You might have noticed that we're also sending regular CSS
|
||||
// through PostCSS. This looks weird, and in fact is probably
|
||||
// not what you'd expect, however in order for our CSS build
|
||||
// to work nicely we have to do this. Because down the line
|
||||
// our SCSS stylesheets reference plain CSS we have to load
|
||||
// the plain CSS through PostCSS so it can find it safely. This
|
||||
// also acts like a babel-for-css by transpiling our (S)CSS
|
||||
// down/up to the right browser support (prefixes, etc).
|
||||
// Further, if we don't do this then PostCSS assumes that our
|
||||
// plain CSS is SCSS and it really doesn't like that, even
|
||||
// though plain CSS should be compatible. The chunking options
|
||||
// at the top of this webpack config help group the SCSS and
|
||||
// plain CSS together for the bundler.
|
||||
|
||||
require("postcss-simple-vars")(),
|
||||
require("postcss-strip-inline-comments")(),
|
||||
|
||||
// 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'}),
|
||||
],
|
||||
parser: "postcss-scss",
|
||||
"local-plugins": true,
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.scss$/,
|
||||
use: [
|
||||
MiniCssExtractPlugin.loader,
|
||||
{
|
||||
loader: 'css-loader',
|
||||
options: {
|
||||
importLoaders: 1,
|
||||
sourceMap: true,
|
||||
}
|
||||
},
|
||||
{
|
||||
loader: 'postcss-loader',
|
||||
ident: 'postcss',
|
||||
options: {
|
||||
sourceMap: true,
|
||||
plugins: () => [
|
||||
// Note that we use slightly different plugins for SCSS.
|
||||
|
||||
require('postcss-import')(),
|
||||
require("postcss-simple-vars")(),
|
||||
require("postcss-extend")(),
|
||||
require("postcss-nested")(),
|
||||
require("postcss-mixins")(),
|
||||
require("postcss-easings")(),
|
||||
require("postcss-strip-inline-comments")(),
|
||||
|
||||
// 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'}),
|
||||
],
|
||||
parser: "postcss-scss",
|
||||
"local-plugins": true,
|
||||
},
|
||||
},
|
||||
]
|
||||
},
|
||||
{
|
||||
test: /\.wasm$/,
|
||||
loader: "file-loader",
|
||||
type: "javascript/auto", // https://github.com/webpack/webpack/issues/6725
|
||||
options: {
|
||||
name: '[name].[hash:7].[ext]',
|
||||
outputPath: '.',
|
||||
},
|
||||
},
|
||||
{
|
||||
// cache-bust languages.json file placed in
|
||||
// riot-web/webapp/i18n during build by copy-res.js
|
||||
test: /\.*languages.json$/,
|
||||
type: "javascript/auto",
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: 'i18n/[name].[hash:7].[ext]',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(gif|png|svg|ttf|woff|woff2|xml|ico)$/,
|
||||
// Use a content-based hash in the name so that we can set a long cache
|
||||
// lifetime for assets while still delivering changes quickly.
|
||||
oneOf: [
|
||||
{
|
||||
// Assets referenced in CSS files
|
||||
issuer: /\.(scss|css)$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
esModule: false,
|
||||
name: '[name].[hash:7].[ext]',
|
||||
outputPath: getImgOutputPath,
|
||||
publicPath: function(url, resourcePath) {
|
||||
// CSS image usages end up in the `bundles/[hash]` output
|
||||
// directory, so we adjust the final path to navigate up
|
||||
// twice.
|
||||
const outputPath = getImgOutputPath(url, resourcePath);
|
||||
return toPublicPath(path.join("../..", outputPath));
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Assets referenced in HTML and JS files
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
esModule: false,
|
||||
name: '[name].[hash:7].[ext]',
|
||||
outputPath: getImgOutputPath,
|
||||
publicPath: function(url, resourcePath) {
|
||||
const outputPath = getImgOutputPath(url, resourcePath);
|
||||
return toPublicPath(outputPath);
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
}),
|
||||
},
|
||||
{
|
||||
// this works similarly to the scss case, without postcss.
|
||||
test: /\.css$/,
|
||||
use: ExtractTextPlugin.extract({
|
||||
use: "css-loader",
|
||||
}),
|
||||
},
|
||||
{
|
||||
// cache-bust languages.json file placed in
|
||||
// riot-web/webapp/i18n during build by copy-res.js
|
||||
test: /\.*languages.json$/,
|
||||
type: "javascript/auto",
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: 'i18n/[name].[hash:7].[ext]',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.(gif|png|svg|ttf|woff|woff2|xml|ico)$/,
|
||||
// Use a content-based hash in the name so that we can set a long cache
|
||||
// lifetime for assets while still delivering changes quickly.
|
||||
oneOf: [
|
||||
{
|
||||
// Assets referenced in CSS files
|
||||
issuer: /\.(scss|css)$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[hash:7].[ext]',
|
||||
outputPath: getImgOutputPath,
|
||||
publicPath: function(url, resourcePath) {
|
||||
// CSS image usages end up in the `bundles/[hash]` output
|
||||
// directory, so we adjust the final path to navigate up
|
||||
// twice.
|
||||
const outputPath = getImgOutputPath(url, resourcePath);
|
||||
return toPublicPath(path.join("../..", outputPath));
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
// Assets referenced in HTML and JS files
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: '[name].[hash:7].[ext]',
|
||||
outputPath: getImgOutputPath,
|
||||
publicPath: function(url, resourcePath) {
|
||||
const outputPath = getImgOutputPath(url, resourcePath);
|
||||
return toPublicPath(outputPath);
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
},
|
||||
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
|
||||
},
|
||||
}),
|
||||
|
||||
// This exports our CSS using the splitChunks and loaders above.
|
||||
new MiniCssExtractPlugin({
|
||||
filename: 'bundles/[hash]/[name].css',
|
||||
ignoreOrder: false, // Enable to remove warnings about conflicting order
|
||||
}),
|
||||
|
||||
// This is the app's main entry point.
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/vector/index.html',
|
||||
|
||||
// we inject the links ourselves via the template, because
|
||||
// HtmlWebpackPlugin will screw up our formatting like the names
|
||||
// of the themes and which chunks we actually care about.
|
||||
inject: false,
|
||||
excludeChunks: ['mobileguide'],
|
||||
minify: argv.mode === 'production',
|
||||
vars: {
|
||||
og_image_url: og_image_url,
|
||||
},
|
||||
}),
|
||||
|
||||
// This is the mobile guide's entry point (separate for faster mobile loading)
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/vector/mobile_guide/index.html',
|
||||
filename: 'mobile_guide/index.html',
|
||||
minify: argv.mode === 'production',
|
||||
chunks: ['mobileguide'],
|
||||
}),
|
||||
],
|
||||
noParse: [
|
||||
// for cross platform compatibility use [\\\/] as the path separator
|
||||
// this ensures that the regex trips on both Windows and *nix
|
||||
|
||||
// don't parse the languages within highlight.js. They cause stack
|
||||
// overflows (https://github.com/webpack/webpack/issues/1721), and
|
||||
// there is no need for webpack to parse them - they can just be
|
||||
// included as-is.
|
||||
/highlight\.js[\\\/]lib[\\\/]languages/,
|
||||
output: {
|
||||
path: path.join(__dirname, "webapp"),
|
||||
|
||||
// olm takes ages for webpack to process, and it's already heavily
|
||||
// optimised, so there is little to gain by us uglifying it.
|
||||
/olm[\\\/](javascript[\\\/])?olm\.js$/,
|
||||
],
|
||||
},
|
||||
output: {
|
||||
path: path.join(__dirname, "webapp"),
|
||||
|
||||
// The generated JS (and CSS, from the ExtractTextPlugin) are put in a
|
||||
// unique subdirectory for the build. There will only be one such
|
||||
// 'bundle' directory in the generated tarball; however, hosting
|
||||
// servers can collect 'bundles' from multiple versions into one
|
||||
// directory and symlink it into place - this allows users who loaded
|
||||
// an older version of the application to continue to access webpack
|
||||
// chunks even after the app is redeployed.
|
||||
filename: "bundles/[hash]/[name].js",
|
||||
chunkFilename: "bundles/[hash]/[name].js",
|
||||
devtoolModuleFilenameTemplate: function(info) {
|
||||
// Reading input source maps gives only relative paths here for
|
||||
// everything. Until I figure out how to fix this, this is a
|
||||
// workaround.
|
||||
// We use the relative resource path with any '../'s on the front
|
||||
// removed which gives a tree with matrix-react-sdk and vector
|
||||
// trees smashed together, but this fixes everything being under
|
||||
// various levels of '.' and '..'
|
||||
// Also, sometimes the resource path is absolute.
|
||||
return path.relative(process.cwd(), info.resourcePath).replace(/^[\/\.]*/, '');
|
||||
},
|
||||
},
|
||||
resolve: {
|
||||
alias: {
|
||||
// alias any requires to the react module to the one in our path,
|
||||
// otherwise we tend to get the react source included twice when
|
||||
// using `npm link` / `yarn link`.
|
||||
"react": path.resolve('./node_modules/react'),
|
||||
"react-dom": path.resolve('./node_modules/react-dom'),
|
||||
|
||||
// same goes for js-sdk
|
||||
"matrix-js-sdk": path.resolve('./node_modules/matrix-js-sdk'),
|
||||
|
||||
"$webapp": path.resolve('./webapp'),
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': {
|
||||
NODE_ENV: JSON.stringify(process.env.NODE_ENV),
|
||||
},
|
||||
}),
|
||||
new ExtractTextPlugin("bundles/[hash]/[name].css", {
|
||||
allChunks: true,
|
||||
}),
|
||||
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/vector/index.html',
|
||||
|
||||
// we inject the links ourselves via the template, because
|
||||
// HtmlWebpackPlugin wants to put the script tags either at the
|
||||
// bottom of <head> or the bottom of <body>, and I'm a bit scared
|
||||
// about moving them.
|
||||
inject: false,
|
||||
excludeChunks: ['mobileguide'],
|
||||
vars: {
|
||||
og_image_url: og_image_url,
|
||||
},
|
||||
}),
|
||||
new HtmlWebpackPlugin({
|
||||
template: './src/vector/mobile_guide/index.html',
|
||||
filename: 'mobile_guide/index.html',
|
||||
chunks: ['mobileguide'],
|
||||
}),
|
||||
],
|
||||
devtool: 'source-map',
|
||||
|
||||
// configuration for the webpack-dev-server
|
||||
devServer: {
|
||||
// serve unwebpacked assets from webapp.
|
||||
contentBase: './webapp',
|
||||
|
||||
stats: {
|
||||
// don't fill the console up with a mahoosive list of modules
|
||||
chunks: false,
|
||||
// The generated JS (and CSS, from the extraction plugin) are put in a
|
||||
// unique subdirectory for the build. There will only be one such
|
||||
// 'bundle' directory in the generated tarball; however, hosting
|
||||
// servers can collect 'bundles' from multiple versions into one
|
||||
// directory and symlink it into place - this allows users who loaded
|
||||
// an older version of the application to continue to access webpack
|
||||
// chunks even after the app is redeployed.
|
||||
filename: "bundles/[hash]/[name].js",
|
||||
chunkFilename: "bundles/[hash]/[name].js",
|
||||
},
|
||||
|
||||
// hot mdule 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,
|
||||
},
|
||||
// configuration for the webpack-dev-server
|
||||
devServer: {
|
||||
// serve unwebpacked assets from webapp.
|
||||
contentBase: './webapp',
|
||||
|
||||
// Only output errors, warnings, or new compilations.
|
||||
// This hides the massive list of modules.
|
||||
stats: 'minimal',
|
||||
|
||||
// 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,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user