Merge remote-tracking branch 'origin/develop' into zip/11225-shields-distinguish-encrypt-from-verify

This commit is contained in:
Zoe 2020-01-16 11:23:57 +00:00
commit 9ac3cb6fd0
467 changed files with 4601 additions and 4332 deletions

View file

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

View file

@ -1,13 +1,60 @@
steps: steps:
- label: ":eslint: Lint" - label: ":eslint: JS Lint"
command: command:
- "echo '--- Install js-sdk'" - "echo '--- Install js-sdk'"
- "./scripts/ci/install-deps.sh" - "./scripts/ci/install-deps.sh"
- "yarn lintwithexclusions" - "yarn lint:js"
- "yarn stylelint"
plugins: plugins:
- docker#v3.0.1: - docker#v3.0.1:
image: "node:10" image: "node:12"
- 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:
- "echo '--- Install js-sdk'"
- "./scripts/ci/install-deps.sh"
- "yarn lint:types"
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:
- "echo '--- Install js-sdk'"
# TODO: Remove hacky chmod for BuildKite
- "chmod +x ./scripts/ci/*.sh"
- "chmod +x ./scripts/*"
- "echo '--- Installing Dependencies'"
- "./scripts/ci/install-deps.sh"
- "echo '--- Running initial build steps'"
- "yarn build"
- "echo '+++ Running Tests'"
- "yarn test"
plugins:
- docker#v3.0.1:
image: "node:12"
- label: "🛠 Build"
command:
- "echo '--- Install js-sdk'"
- "./scripts/ci/install-deps.sh"
- "echo '+++ Building Project'"
- "yarn build"
plugins:
- docker#v3.0.1:
image: "node:12"
- label: ":chains: End-to-End Tests" - label: ":chains: End-to-End Tests"
agents: agents:
@ -21,39 +68,15 @@ steps:
- "chmod +x ./scripts/*" - "chmod +x ./scripts/*"
- "echo '--- Install js-sdk'" - "echo '--- Install js-sdk'"
- "./scripts/ci/install-deps.sh" - "./scripts/ci/install-deps.sh"
- "echo '--- Running initial build steps'"
- "yarn build"
- "echo '+++ Running Tests'"
- "./scripts/ci/end-to-end-tests.sh" - "./scripts/ci/end-to-end-tests.sh"
plugins: plugins:
- docker#v3.0.1: - docker#v3.0.1:
image: "matrixdotorg/riotweb-ci-e2etests-env:latest" image: "matrixdotorg/riotweb-ci-e2etests-env:latest"
propagate-environment: true propagate-environment: true
- label: ":karma: 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
# TODO: Remove hacky chmod for BuildKite
- "chmod +x ./scripts/ci/*.sh"
- "chmod +x ./scripts/*"
- "echo '--- Installing Dependencies'"
- "./scripts/ci/install-deps.sh"
- "echo '+++ Running Tests'"
- "./scripts/ci/unit-tests.sh"
env:
CHROME_BIN: "/usr/bin/google-chrome-stable"
plugins:
- docker#v3.0.1:
image: "node:10"
propagate-environment: true
- label: "🔧 Riot Tests" - label: "🔧 Riot Tests"
agents: agents:
# We use a medium sized instance instead of the normal small ones because # We use a medium sized instance instead of the normal small ones because
@ -66,12 +89,13 @@ steps:
- "sh -c 'echo \"deb [arch=amd64] http://dl.google.com/linux/chrome/deb/ stable main\" >> /etc/apt/sources.list.d/google.list'" - "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 update"
- "apt-get install -y google-chrome-stable" - "apt-get install -y google-chrome-stable"
# Run tests
# TODO: Remove hacky chmod for BuildKite # TODO: Remove hacky chmod for BuildKite
- "chmod +x ./scripts/ci/*.sh" - "chmod +x ./scripts/ci/*.sh"
- "chmod +x ./scripts/*" - "chmod +x ./scripts/*"
- "echo '--- Installing Dependencies'" - "echo '--- Installing Dependencies'"
- "./scripts/ci/install-deps.sh" - "./scripts/ci/install-deps.sh"
- "echo '--- Running initial build steps'"
- "yarn build"
- "echo '+++ Running Tests'" - "echo '+++ Running Tests'"
- "./scripts/ci/riot-unit-tests.sh" - "./scripts/ci/riot-unit-tests.sh"
env: env:

View file

@ -5,7 +5,10 @@ const path = require('path');
// but only if they come from a module that starts with eslint-config- // but only if they come from a module that starts with eslint-config-
// So we load the filename directly (and it could be in node_modules/ // So we load the filename directly (and it could be in node_modules/
// or or ../node_modules/ etc) // or or ../node_modules/ etc)
const matrixJsSdkPath = path.dirname(require.resolve('matrix-js-sdk')); //
// We add a `..` to the end because the js-sdk lives out of lib/, but the eslint
// config is at the project root.
const matrixJsSdkPath = path.join(path.dirname(require.resolve('matrix-js-sdk')), '..');
module.exports = { module.exports = {
parser: "babel-eslint", parser: "babel-eslint",
@ -25,6 +28,7 @@ module.exports = {
parserOptions: { parserOptions: {
ecmaFeatures: { ecmaFeatures: {
jsx: true, jsx: true,
legacyDecorators: true,
} }
}, },
rules: { rules: {

View file

@ -67,6 +67,7 @@ practices that anyone working with the SDK needs to be be aware of and uphold:
* After creating a new component you must run `yarn reskindex` to regenerate * After creating a new component you must run `yarn reskindex` to regenerate
the `component-index.js` for the SDK (used in future for skinning) the `component-index.js` for the SDK (used in future for skinning)
<!-- TODO: Remove this once this approach to skinning is replaced -->
* The view's CSS file MUST have the same name (e.g. view/rooms/MessageTile.css). * The view's CSS file MUST have the same name (e.g. view/rooms/MessageTile.css).
CSS for matrix-react-sdk currently resides in CSS for matrix-react-sdk currently resides in

View file

@ -0,0 +1,16 @@
const en = require("../src/i18n/strings/en_EN");
module.exports = jest.fn((opts, cb) => {
if (opts.url.endsWith("languages.json")) {
cb(undefined, {status: 200}, JSON.stringify({
"en": {
"fileName": "en_EN.json",
"label": "English",
},
}));
} else if (opts.url.endsWith("en_EN.json")) {
cb(undefined, {status: 200}, JSON.stringify(en));
} else {
cb(undefined, {status: 404}, "");
}
});

1
__mocks__/imageMock.js Normal file
View file

@ -0,0 +1 @@
module.exports = "image-file-stub";

10
__mocks__/languages.json Normal file
View file

@ -0,0 +1,10 @@
{
"en": {
"fileName": "en_EN.json",
"label": "English"
},
"en-us": {
"fileName": "en_US.json",
"label": "English (US)"
}
}

26
babel.config.js Normal file
View file

@ -0,0 +1,26 @@
module.exports = {
"sourceMaps": "inline",
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": [
"last 2 versions"
]
},
"modules": "commonjs"
}],
"@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"
]
};

71
docs/skinning.md Normal file
View file

@ -0,0 +1,71 @@
# Skinning
The react-sdk can be skinned to replace presentation components, CSS, or
other relevant parts of the SDK. Typically consumers will replace entire
components and get the ability for custom CSS as a result.
This doc isn't exhaustive on how skinning works, though it should cover
some of the more complicated parts such as component replacement.
## Loading a skin
1. Generate a `component-index.js` (preferably using the tools that the react-sdk
exposes). This can typically be done with a npm script like `"reskindex -h src/header"`.
2. In your app's entry point, add something like this code:
```javascript
import {loadSkin} from "matrix-react-sdk";
loadSkin(import("component-index").components);
// The rest of your imports go under this.
```
3. Import the remainder of the SDK and bootstrap your app.
It is extremely important that you **do not** import anything else from the
SDK prior to loading your skin as otherwise the skin might not work. Loading
the skin should be one of the first things your app does, if not the very
first thing.
Additionally, **do not** provide `loadSkin` with the react-sdk components
themselves otherwise the app might explode. The SDK is already aware of its
components and doesn't need to be told.
## Replacing components
Components that replace the react-sdk ones MUST have a `replaces` static
key on the component's class to describe which component it overrides. For
example, if your `VectorAuthPage` component is meant to replace the react-sdk
`AuthPage` component then you'd add `static replaces = 'views.auth.AuthPage';`
to the `VectorAuthPage` class.
Other than that, the skin just needs to be loaded normally as mentioned above.
Consumers of the SDK likely will not be interested in the rest of this section.
### SDK developer notes
Components in the react-sdk MUST be decorated with the `@replaceableComponent`
function. For components that can't use the decorator, they must use a
variation that provides similar functionality. The decorator gives consumers
an opportunity to load skinned components by abusing import ordering and
behaviour.
Decorators are executed at import time which is why we can abuse the import
ordering behaviour: importing `loadSkin` doesn't trigger any components to
be imported, allowing the consumer to specify a skin. When the consumer does
import a component (for example, `MatrixChat`), it starts to pull in all the
components via `import` statements. When the components get pulled in the
decorator checks with the skinned components to see if it should be replacing
the component being imported. The decorator then effectively replaces the
components when needed by specifying the skinned component as an override for
the SDK's component, which should in theory override critical functions like
`render()` and lifecycle event handlers.
The decorator also means that older usage of `getComponent()` is no longer
required because components should be replaced by the decorator. Eventually
the react-sdk should only have one usage of `getComponent()`: the decorator.
The decorator assumes that if `getComponent()` returns null that there is
no skinned version of the component and continues on using the SDK's component.
In previous versions of the SDK, the function would throw an error instead
because it also expected the skin to list the SDK's components as well, however
that is no longer possible due to the above.
In short, components should always be `import`ed.

View file

@ -1,39 +0,0 @@
#!/bin/bash
set -e
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm use 10
set -x
scripts/fetchdep.sh matrix-org matrix-js-sdk
pushd matrix-js-sdk
yarn link
yarn install
popd
yarn link matrix-js-sdk
# install the other dependencies
yarn install
# run the mocha tests
yarn test --no-colors
# run eslint
yarn lintall -f checkstyle -o eslint.xml || true
# re-run the linter, excluding any files known to have errors or warnings.
yarn lintwithexclusions
# lint styles
yarn stylelint
# delete the old tarball, if it exists
rm -f matrix-react-sdk-*.tgz
# build our tarball
yarn pack

View file

@ -1,228 +0,0 @@
// karma.conf.js - the config file for karma, which runs our tests.
var path = require('path');
var fs = require('fs');
/*
* 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.
//
// TODO: this could be a pattern, and karma would run each file, with a
// separate webpack bundle for each file. But then we get a separate instance
// of the sdk, and each of the dependencies, for each test file, and everything
// gets very confused. Can we persuade webpack to put all of the dependencies
// in a 'common' bundle?
//
var testFile = process.env.KARMA_TEST_FILE || 'test/all-tests.js';
process.env.PHANTOMJS_BIN = 'node_modules/.bin/phantomjs';
function fileExists(name) {
try {
fs.statSync(name);
return true;
} catch (e) {
return false;
}
}
// try find the gemini-scrollbar css in an version-agnostic way
var gsCss = 'node_modules/gemini-scrollbar/gemini-scrollbar.css';
if (!fileExists(gsCss)) {
gsCss = 'node_modules/react-gemini-scrollbar/'+gsCss;
}
module.exports = function (config) {
config.set({
// frameworks to use
// available frameworks: https://npmjs.org/browse/keyword/karma-adapter
frameworks: ['mocha'],
// list of files / patterns to load in the browser
files: [
testFile,
gsCss,
// some images to reduce noise from the tests
{pattern: 'test/img/*', watched: false, included: false,
served: true, nocache: false},
// translation files
{pattern: 'src/i18n/strings/*', watcheed: false, included: false, served: true},
{pattern: 'test/i18n/*', watched: false, included: false, served: true},
],
proxies: {
// redirect img links to the karma server
"/img/": "/base/test/img/",
// special languages.json file for the tests
"/i18n/languages.json": "/base/test/i18n/languages.json",
// and redirect i18n requests
"/i18n/": "/base/src/i18n/strings/",
},
// list of files to exclude
//
// This doesn't work. It turns out that it's webpack which does the
// watching of the /test directory (karma only watches `testFile`
// itself). Webpack watches the directory so that it can spot
// new tests, which is fair enough; unfortunately it triggers a rebuild
// every time a lockfile is created in that directory, and there
// doesn't seem to be any way to tell webpack to ignore particular
// files in a watched directory.
//
// exclude: [
// '**/.#*'
// ],
// preprocess matching files before serving them to the browser
// available preprocessors:
// https://npmjs.org/browse/keyword/karma-preprocessor
preprocessors: {
'test/**/*.js': ['webpack', 'sourcemap']
},
// test results reporter to use
// possible values: 'dots', 'progress'
// 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
//
// This is strictly for logs that would be generated by the browser itself and we
// don't want to log about missing images, which are emitted on LOG_WARN.
logLevel: config.LOG_ERROR,
// 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: {
module: {
rules: [
{
test: /\.js$/, loader: "babel-loader",
include: [path.resolve('./src'),
path.resolve('./test'),
]
},
{
test: /\.(gif|png|svg|ttf|woff2)$/,
loader: 'file-loader',
},
],
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$/,
// also disable parsing for sinon, because it
// tries to do voodoo with 'require' which upsets
// webpack (https://github.com/webpack/webpack/issues/304)
/sinon[\\\/]pkg[\\\/]sinon\.js$/,
],
},
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'),
'matrix-react-sdk': path.resolve('test/skinned-sdk.js'),
'sinon': 'sinon/pkg/sinon.js',
},
modules: [
path.resolve('./test'),
"node_modules"
],
},
devtool: 'inline-source-map',
externals: {
// Don't try to bundle electron: leave it as a commonjs dependency
// (the 'commonjs' here means it will output a 'require')
"electron": "commonjs electron",
},
// make sure we're flagged as development to avoid wasting time optimising
mode: 'development',
},
webpackMiddleware: {
stats: {
// don't fill the console up with a mahoosive list of modules
chunks: false,
},
},
browserNoActivityTimeout: 15000,
});
};

View file

@ -8,57 +8,51 @@
"url": "https://github.com/matrix-org/matrix-react-sdk" "url": "https://github.com/matrix-org/matrix-react-sdk"
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "lib/index.js",
"files": [ "files": [
".babelrc", "lib",
".eslintrc.js", "res",
"src",
"scripts",
"git-revision.txt",
"docs",
"header",
"CHANGELOG.md", "CHANGELOG.md",
"CONTRIBUTING.rst", "CONTRIBUTING.rst",
"LICENSE", "LICENSE",
"README.md", "README.md",
"code_style.md", "package.json"
"git-revision.txt",
"header",
"jenkins.sh",
"karma.conf.js",
"lib",
"package.json",
"release.sh",
"scripts",
"src",
"test",
"res"
], ],
"bin": { "bin": {
"reskindex": "scripts/reskindex.js", "reskindex": "scripts/reskindex.js",
"matrix-gen-i18n": "scripts/gen-i18n.js", "matrix-gen-i18n": "scripts/gen-i18n.js",
"matrix-prune-i18n": "scripts/prune-i18n.js" "matrix-prune-i18n": "scripts/prune-i18n.js"
}, },
"main": "./lib/index.js",
"typings": "./lib/index.d.ts",
"matrix_src_main": "./src/index.js",
"scripts": { "scripts": {
"reskindex": "node scripts/reskindex.js -h header",
"reskindex:watch": "node scripts/reskindex.js -h header -w",
"rethemendex": "res/css/rethemendex.sh",
"i18n": "matrix-gen-i18n", "i18n": "matrix-gen-i18n",
"prunei18n": "matrix-prune-i18n", "prunei18n": "matrix-prune-i18n",
"diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && ./scripts/gen-i18n.js && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json", "diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && ./scripts/gen-i18n.js && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
"build": "yarn reskindex && yarn start:init", "reskindex": "node scripts/reskindex.js -h header",
"build:watch": "babel src -w --skip-initial-build -d lib --source-maps --copy-files", "reskindex:watch": "node scripts/reskindex.js -h header -w",
"start": "yarn start:init && yarn start:all", "rethemendex": "res/css/rethemendex.sh",
"start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn build:watch\" \"yarn reskindex:watch\"",
"start:init": "babel src -d lib --source-maps --copy-files",
"lint": "eslint src/",
"lintall": "eslint src/ test/",
"lintwithexclusions": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test",
"stylelint": "stylelint 'res/css/**/*.scss'",
"clean": "rimraf lib", "clean": "rimraf lib",
"prepare": "yarn clean && yarn build && git rev-parse HEAD > git-revision.txt", "build": "yarn clean && git rev-parse HEAD > git-revision.txt && yarn build:compile && yarn build:types",
"test": "karma start --single-run=true --browsers VectorChromeHeadless", "build:compile": "yarn reskindex && babel -d lib --verbose --extensions \".ts,.js\" src",
"test-multi": "karma start", "build:types": "tsc --emitDeclarationOnly",
"e2etests": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080" "start": "echo THIS IS FOR LEGACY PURPOSES ONLY. && yarn start:all",
"start:all": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n build,reskindex \"yarn start:build\" \"yarn reskindex:watch\"",
"start:build": "babel src -w -s -d lib --verbose --extensions \".ts,.js\"",
"lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style",
"lint:js": "eslint --max-warnings 0 --ignore-path .eslintignore.errorfiles src test",
"lint:ts": "tslint --project ./tsconfig.json -t stylish",
"lint:types": "tsc --noEmit",
"lint:style": "stylelint 'res/css/**/*.scss'",
"test": "jest",
"test:e2e": "./test/end-to-end-tests/run.sh --riot-url http://localhost:8080"
}, },
"dependencies": { "dependencies": {
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-runtime": "^6.26.0",
"blueimp-canvas-to-blob": "^3.5.0", "blueimp-canvas-to-blob": "^3.5.0",
"browser-encrypt-attachment": "^0.3.0", "browser-encrypt-attachment": "^0.3.0",
"browser-request": "^0.3.3", "browser-request": "^0.3.3",
@ -82,7 +76,6 @@
"glob-to-regexp": "^0.4.1", "glob-to-regexp": "^0.4.1",
"highlight.js": "^9.15.8", "highlight.js": "^9.15.8",
"html-entities": "^1.2.1", "html-entities": "^1.2.1",
"humanize": "^0.0.9",
"is-ip": "^2.0.0", "is-ip": "^2.0.0",
"isomorphic-fetch": "^2.2.1", "isomorphic-fetch": "^2.2.1",
"linkifyjs": "^2.1.6", "linkifyjs": "^2.1.6",
@ -112,20 +105,24 @@
"zxcvbn": "^4.4.2" "zxcvbn": "^4.4.2"
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.26.0", "@babel/cli": "^7.7.5",
"babel-core": "^6.26.3", "@babel/core": "^7.7.5",
"babel-eslint": "^10.0.1", "@babel/plugin-proposal-class-properties": "^7.7.4",
"babel-loader": "^7.1.5", "@babel/plugin-proposal-decorators": "^7.7.4",
"babel-plugin-add-module-exports": "^0.2.1", "@babel/plugin-proposal-export-default-from": "^7.7.4",
"babel-plugin-transform-builtin-extend": "^1.1.2", "@babel/plugin-proposal-numeric-separator": "^7.7.4",
"babel-plugin-transform-class-properties": "^6.24.1", "@babel/plugin-proposal-object-rest-spread": "^7.7.4",
"babel-plugin-transform-object-rest-spread": "^6.26.0", "@babel/plugin-transform-flow-comments": "^7.7.4",
"babel-plugin-transform-runtime": "^6.23.0", "@babel/plugin-transform-runtime": "^7.7.6",
"babel-polyfill": "^6.26.0", "@babel/preset-env": "^7.7.6",
"babel-preset-es2015": "^6.24.1", "@babel/preset-flow": "^7.7.4",
"babel-preset-es2016": "^6.24.1", "@babel/preset-react": "^7.7.4",
"babel-preset-es2017": "^6.24.1", "@babel/preset-typescript": "^7.7.4",
"babel-preset-react": "^6.24.1", "@babel/register": "^7.7.4",
"@babel/runtime": "^7.7.6",
"@peculiar/webcrypto": "^1.0.22",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.9.0",
"chokidar": "^2.1.2", "chokidar": "^2.1.2",
"concurrently": "^4.0.1", "concurrently": "^4.0.1",
"enzyme": "^3.10.0", "enzyme": "^3.10.0",
@ -138,32 +135,35 @@
"eslint-plugin-react": "^7.7.0", "eslint-plugin-react": "^7.7.0",
"eslint-plugin-react-hooks": "^2.0.1", "eslint-plugin-react-hooks": "^2.0.1",
"estree-walker": "^0.5.0", "estree-walker": "^0.5.0",
"expect": "^24.1.0",
"file-loader": "^3.0.1", "file-loader": "^3.0.1",
"flow-parser": "^0.57.3", "flow-parser": "^0.57.3",
"jest-mock": "^23.2.0", "jest": "^24.9.0",
"karma": "^4.0.1",
"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",
"matrix-mock-request": "^1.2.3", "matrix-mock-request": "^1.2.3",
"matrix-react-test-utils": "^0.2.2", "matrix-react-test-utils": "^0.2.2",
"mocha": "^5.0.5",
"react-test-renderer": "^16.9.0", "react-test-renderer": "^16.9.0",
"require-json": "0.0.1", "require-json": "0.0.1",
"rimraf": "^2.4.3", "rimraf": "^2.4.3",
"sinon": "^5.0.7",
"source-map-loader": "^0.2.3", "source-map-loader": "^0.2.3",
"stylelint": "^9.10.1", "stylelint": "^9.10.1",
"stylelint-config-standard": "^18.2.0", "stylelint-config-standard": "^18.2.0",
"stylelint-scss": "^3.9.0", "stylelint-scss": "^3.9.0",
"tslint": "^5.20.1",
"typescript": "^3.7.3",
"walk": "^2.3.9", "walk": "^2.3.9",
"webpack": "^4.20.2", "webpack": "^4.20.2",
"webpack-cli": "^3.1.1" "webpack-cli": "^3.1.1"
},
"jest": {
"testMatch": [
"<rootDir>/test/**/*-test.js"
],
"setupTestFrameworkScriptFile": "<rootDir>/test/setupTests.js",
"moduleNameMapper": {
"\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/__mocks__/imageMock.js",
"\\$webapp/i18n/languages.json": "<rootDir>/__mocks__/languages.json"
},
"transformIgnorePatterns": [
"/node_modules/(?!matrix-js-sdk).+$"
]
} }
} }

View file

@ -61,5 +61,5 @@ input.mx_StatusMessageContextMenu_message {
} }
.mx_StatusMessageContextMenu_actionContainer .mx_Spinner { .mx_StatusMessageContextMenu_actionContainer .mx_Spinner {
justify-content: start; justify-content: flex-start;
} }

View file

@ -30,7 +30,7 @@ limitations under the License.
> div { > div {
display: flex; display: flex;
align-items: start; align-items: flex-start;
margin: 5px 0; margin: 5px 0;
input[type=checkbox] { input[type=checkbox] {

View file

@ -32,7 +32,7 @@ limitations under the License.
.mx_CreateKeyBackupDialog_passPhraseContainer { .mx_CreateKeyBackupDialog_passPhraseContainer {
display: flex; display: flex;
align-items: start; align-items: flex-start;
} }
.mx_CreateKeyBackupDialog_passPhraseHelp { .mx_CreateKeyBackupDialog_passPhraseHelp {

View file

@ -33,7 +33,7 @@ limitations under the License.
.mx_CreateSecretStorageDialog_passPhraseContainer { .mx_CreateSecretStorageDialog_passPhraseContainer {
display: flex; display: flex;
align-items: start; align-items: flex-start;
} }
.mx_CreateSecretStorageDialog_passPhraseHelp { .mx_CreateSecretStorageDialog_passPhraseHelp {

View file

@ -17,7 +17,7 @@ limitations under the License.
.mx_MemberDeviceInfo { .mx_MemberDeviceInfo {
display: flex; display: flex;
padding-bottom: 10px; padding-bottom: 10px;
align-items: start; align-items: flex-start;
} }
.mx_MemberDeviceInfo_icon { .mx_MemberDeviceInfo_icon {

View file

@ -101,7 +101,7 @@ limitations under the License.
display: flex; display: flex;
flex-direction: column; flex-direction: column;
min-height: 60px; min-height: 60px;
justify-content: start; justify-content: flex-start;
align-items: flex-start; align-items: flex-start;
font-size: 14px; font-size: 14px;
margin-right: 6px; margin-right: 6px;

View file

@ -263,3 +263,24 @@ limitations under the License.
.mx_RoomHeader_pinsIndicatorUnread { .mx_RoomHeader_pinsIndicatorUnread {
background-color: $pinned-unread-color; background-color: $pinned-unread-color;
} }
.mx_RoomHeader_PrivateIcon.mx_RoomHeader_isPrivate {
width: 12px;
height: 12px;
position: relative;
display: block !important;
&::before {
background-color: $roomtile-name-color;
mask-image: url('$(res)/img/feather-customised/lock-solid.svg');
mask-position: center;
mask-repeat: no-repeat;
mask-size: contain;
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
}

View file

@ -7,6 +7,7 @@ scripts/fetchdep.sh matrix-org matrix-js-sdk
pushd matrix-js-sdk pushd matrix-js-sdk
yarn link yarn link
yarn install yarn install
yarn build
popd popd
yarn link matrix-js-sdk yarn link matrix-js-sdk

View file

@ -1,10 +0,0 @@
#!/bin/bash
#
# script which is run by the CI build (after `yarn test`).
#
# clones riot-web develop and runs the tests against our version of react-sdk.
set -ev
scripts/ci/build.sh
yarn test

View file

@ -19,7 +19,6 @@ function reskindex() {
prevFiles = files; prevFiles = files;
var header = args.h || args.header; var header = args.h || args.header;
var packageJson = JSON.parse(fs.readFileSync('./package.json'));
var strm = fs.createWriteStream(componentIndexTmp); var strm = fs.createWriteStream(componentIndexTmp);
@ -34,19 +33,7 @@ function reskindex() {
strm.write(" * so you'd just be trying to swim upstream like a salmon.\n"); strm.write(" * so you'd just be trying to swim upstream like a salmon.\n");
strm.write(" * You are not a salmon.\n"); strm.write(" * You are not a salmon.\n");
strm.write(" */\n\n"); strm.write(" */\n\n");
if (packageJson['matrix-react-parent']) {
const parentIndex = packageJson['matrix-react-parent'] +
'/lib/component-index';
strm.write(
`let components = require('${parentIndex}').components;
if (!components) {
throw new Error("'${parentIndex}' didn't export components");
}
`);
} else {
strm.write("let components = {};\n"); strm.write("let components = {};\n");
}
for (var i = 0; i < files.length; ++i) { for (var i = 0; i < files.length; ++i) {
var file = files[i].replace('.js', ''); var file = files[i].replace('.js', '');

View file

@ -16,8 +16,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import sdk from './index'; import * as sdk from './index';
import Modal from './Modal'; import Modal from './Modal';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import IdentityAuthClient from './IdentityAuthClient'; import IdentityAuthClient from './IdentityAuthClient';

View file

@ -18,7 +18,7 @@ import { getCurrentLanguage, _t, _td } from './languageHandler';
import PlatformPeg from './PlatformPeg'; import PlatformPeg from './PlatformPeg';
import SdkConfig from './SdkConfig'; import SdkConfig from './SdkConfig';
import Modal from './Modal'; import Modal from './Modal';
import sdk from './index'; import * as sdk from './index';
const hashRegex = /#\/(groups?|room|user|settings|register|login|forgot_password|home|directory)/; const hashRegex = /#\/(groups?|room|user|settings|register|login|forgot_password|home|directory)/;
const hashVarRegex = /#\/(group|room|user)\/.*$/; const hashVarRegex = /#\/(group|room|user)\/.*$/;
@ -306,4 +306,4 @@ class Analytics {
if (!global.mxAnalytics) { if (!global.mxAnalytics) {
global.mxAnalytics = new Analytics(); global.mxAnalytics = new Analytics();
} }
module.exports = global.mxAnalytics; export default global.mxAnalytics;

View file

@ -15,12 +15,11 @@ limitations under the License.
*/ */
'use strict'; 'use strict';
import {ContentRepo} from 'matrix-js-sdk'; import {MatrixClientPeg} from './MatrixClientPeg';
import MatrixClientPeg from './MatrixClientPeg';
import DMRoomMap from './utils/DMRoomMap'; import DMRoomMap from './utils/DMRoomMap';
import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
module.exports = { export function avatarUrlForMember(member, width, height, resizeMethod) {
avatarUrlForMember: function(member, width, height, resizeMethod) {
let url; let url;
if (member && member.getAvatarUrl) { if (member && member.getAvatarUrl) {
url = member.getAvatarUrl( url = member.getAvatarUrl(
@ -36,13 +35,13 @@ module.exports = {
// member can be null here currently since on invites, the JS SDK // member can be null here currently since on invites, the JS SDK
// does not have enough info to build a RoomMember object for // does not have enough info to build a RoomMember object for
// the inviter. // the inviter.
url = this.defaultAvatarUrlForString(member ? member.userId : ''); url = defaultAvatarUrlForString(member ? member.userId : '');
} }
return url; return url;
}, }
avatarUrlForUser: function(user, width, height, resizeMethod) { export function avatarUrlForUser(user, width, height, resizeMethod) {
const url = ContentRepo.getHttpUriForMxc( const url = getHttpUriForMxc(
MatrixClientPeg.get().getHomeserverUrl(), user.avatarUrl, MatrixClientPeg.get().getHomeserverUrl(), user.avatarUrl,
Math.floor(width * window.devicePixelRatio), Math.floor(width * window.devicePixelRatio),
Math.floor(height * window.devicePixelRatio), Math.floor(height * window.devicePixelRatio),
@ -52,16 +51,16 @@ module.exports = {
return null; return null;
} }
return url; return url;
}, }
defaultAvatarUrlForString: function(s) { export function defaultAvatarUrlForString(s) {
const images = ['03b381', '368bd6', 'ac3ba8']; const images = ['03b381', '368bd6', 'ac3ba8'];
let total = 0; let total = 0;
for (let i = 0; i < s.length; ++i) { for (let i = 0; i < s.length; ++i) {
total += s.charCodeAt(i); total += s.charCodeAt(i);
} }
return require('../res/img/' + images[total % images.length] + '.png'); return require('../res/img/' + images[total % images.length] + '.png');
}, }
/** /**
* returns the first (non-sigil) character of 'name', * returns the first (non-sigil) character of 'name',
@ -69,7 +68,7 @@ module.exports = {
* @param {string} name * @param {string} name
* @return {string} the first letter * @return {string} the first letter
*/ */
getInitialLetter(name) { export function getInitialLetter(name) {
if (!name) { if (!name) {
// XXX: We should find out what causes the name to sometimes be falsy. // XXX: We should find out what causes the name to sometimes be falsy.
console.trace("`name` argument to `getInitialLetter` not supplied"); console.trace("`name` argument to `getInitialLetter` not supplied");
@ -100,9 +99,9 @@ module.exports = {
const firstChar = name.substring(idx, idx+chars); const firstChar = name.substring(idx, idx+chars);
return firstChar.toUpperCase(); return firstChar.toUpperCase();
}, }
avatarUrlForRoom(room, width, height, resizeMethod) { export function avatarUrlForRoom(room, width, height, resizeMethod) {
const explicitRoomAvatar = room.getAvatarUrl( const explicitRoomAvatar = room.getAvatarUrl(
MatrixClientPeg.get().getHomeserverUrl(), MatrixClientPeg.get().getHomeserverUrl(),
width, width,
@ -133,5 +132,4 @@ module.exports = {
); );
} }
return null; return null;
}, }
};

View file

@ -53,10 +53,10 @@ limitations under the License.
* } * }
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import PlatformPeg from './PlatformPeg'; import PlatformPeg from './PlatformPeg';
import Modal from './Modal'; import Modal from './Modal';
import sdk from './index'; import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import Matrix from 'matrix-js-sdk'; import Matrix from 'matrix-js-sdk';
import dis from './dispatcher'; import dis from './dispatcher';
@ -302,7 +302,7 @@ function _onAction(payload) {
switch (payload.action) { switch (payload.action) {
case 'place_call': case 'place_call':
{ {
if (module.exports.getAnyActiveCall()) { if (callHandler.getAnyActiveCall()) {
const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog"); const ErrorDialog = sdk.getComponent("dialogs.ErrorDialog");
Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, { Modal.createTrackedDialog('Call Handler', 'Existing Call', ErrorDialog, {
title: _t('Existing Call'), title: _t('Existing Call'),
@ -355,7 +355,7 @@ function _onAction(payload) {
break; break;
case 'incoming_call': case 'incoming_call':
{ {
if (module.exports.getAnyActiveCall()) { if (callHandler.getAnyActiveCall()) {
// ignore multiple incoming calls. in future, we may want a line-1/line-2 setup. // ignore multiple incoming calls. in future, we may want a line-1/line-2 setup.
// we avoid rejecting with "busy" in case the user wants to answer it on a different device. // we avoid rejecting with "busy" in case the user wants to answer it on a different device.
// in future we could signal a "local busy" as a warning to the caller. // in future we could signal a "local busy" as a warning to the caller.
@ -523,7 +523,7 @@ if (!global.mxCallHandler) {
const callHandler = { const callHandler = {
getCallForRoom: function(roomId) { getCallForRoom: function(roomId) {
let call = module.exports.getCall(roomId); let call = callHandler.getCall(roomId);
if (call) return call; if (call) return call;
if (ConferenceHandler) { if (ConferenceHandler) {
@ -583,4 +583,4 @@ if (global.mxCallHandler === undefined) {
global.mxCallHandler = callHandler; global.mxCallHandler = callHandler;
} }
module.exports = global.mxCallHandler; export default global.mxCallHandler;

View file

@ -19,8 +19,8 @@ limitations under the License.
import extend from './extend'; import extend from './extend';
import dis from './dispatcher'; import dis from './dispatcher';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import sdk from './index'; import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import Modal from './Modal'; import Modal from './Modal';
import RoomViewStore from './stores/RoomViewStore'; import RoomViewStore from './stores/RoomViewStore';

View file

@ -15,10 +15,10 @@ limitations under the License.
*/ */
import Modal from './Modal'; import Modal from './Modal';
import sdk from './index'; import * as sdk from './index';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import { deriveKey } from 'matrix-js-sdk/lib/crypto/key_passphrase'; import { deriveKey } from 'matrix-js-sdk/src/crypto/key_passphrase';
import { decodeRecoveryKey } from 'matrix-js-sdk/lib/crypto/recoverykey'; import { decodeRecoveryKey } from 'matrix-js-sdk/src/crypto/recoverykey';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
// This stores the secret storage private keys in memory for the JS SDK. This is // This stores the secret storage private keys in memory for the JS SDK. This is

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import sdk from './index'; import * as sdk from './index';
function isMatch(query, name, uid) { function isMatch(query, name, uid) {
query = query.toLowerCase(); query = query.toLowerCase();
@ -105,26 +105,24 @@ class UserEntity extends Entity {
} }
} }
export function newEntity(jsx, matchFn) {
module.exports = {
newEntity: function(jsx, matchFn) {
const entity = new Entity(); const entity = new Entity();
entity.getJsx = function() { entity.getJsx = function() {
return jsx; return jsx;
}; };
entity.matches = matchFn; entity.matches = matchFn;
return entity; return entity;
}, }
/** /**
* @param {RoomMember[]} members * @param {RoomMember[]} members
* @return {Entity[]} * @return {Entity[]}
*/ */
fromRoomMembers: function(members) { export function fromRoomMembers(members) {
return members.map(function(m) { return members.map(function(m) {
return new MemberEntity(m); return new MemberEntity(m);
}); });
}, }
/** /**
* @param {User[]} users * @param {User[]} users
@ -132,9 +130,8 @@ module.exports = {
* @param {Function} inviteFn Called with the user ID. * @param {Function} inviteFn Called with the user ID.
* @return {Entity[]} * @return {Entity[]}
*/ */
fromUsers: function(users, showInviteButton, inviteFn) { export function fromUsers(users, showInviteButton, inviteFn) {
return users.map(function(u) { return users.map(function(u) {
return new UserEntity(u, showInviteButton, inviteFn); return new UserEntity(u, showInviteButton, inviteFn);
}); });
}, }
};

View file

@ -20,7 +20,7 @@ import URL from 'url';
import dis from './dispatcher'; import dis from './dispatcher';
import WidgetMessagingEndpoint from './WidgetMessagingEndpoint'; import WidgetMessagingEndpoint from './WidgetMessagingEndpoint';
import ActiveWidgetStore from './stores/ActiveWidgetStore'; import ActiveWidgetStore from './stores/ActiveWidgetStore';
import MatrixClientPeg from "./MatrixClientPeg"; import {MatrixClientPeg} from "./MatrixClientPeg";
import RoomViewStore from "./stores/RoomViewStore"; import RoomViewStore from "./stores/RoomViewStore";
import {IntegrationManagers} from "./integrations/IntegrationManagers"; import {IntegrationManagers} from "./integrations/IntegrationManagers";
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";

View file

@ -16,10 +16,10 @@ limitations under the License.
import React from 'react'; import React from 'react';
import Modal from './Modal'; import Modal from './Modal';
import sdk from './'; import * as sdk from './';
import MultiInviter from './utils/MultiInviter'; import MultiInviter from './utils/MultiInviter';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import GroupStore from './stores/GroupStore'; import GroupStore from './stores/GroupStore';
import {allSettled} from "./utils/promise"; import {allSettled} from "./utils/promise";

View file

@ -29,7 +29,7 @@ import linkifyMatrix from './linkify-matrix';
import _linkifyElement from 'linkifyjs/element'; import _linkifyElement from 'linkifyjs/element';
import _linkifyString from 'linkifyjs/string'; import _linkifyString from 'linkifyjs/string';
import classNames from 'classnames'; import classNames from 'classnames';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import url from 'url'; import url from 'url';
import EMOJIBASE_REGEX from 'emojibase-regex'; import EMOJIBASE_REGEX from 'emojibase-regex';

View file

@ -16,9 +16,9 @@ limitations under the License.
import { createClient, SERVICE_TYPES } from 'matrix-js-sdk'; import { createClient, SERVICE_TYPES } from 'matrix-js-sdk';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import Modal from './Modal'; import Modal from './Modal';
import sdk from './index'; import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import { Service, startTermsFlow, TermsNotSignedError } from './Terms'; import { Service, startTermsFlow, TermsNotSignedError } from './Terms';
import { import {

View file

@ -16,8 +16,6 @@ limitations under the License.
'use strict'; 'use strict';
module.exports = {
/** /**
* Returns the actual height that an image of dimensions (fullWidth, fullHeight) * Returns the actual height that an image of dimensions (fullWidth, fullHeight)
* will occupy if resized to fit inside a thumbnail bounding box of size * will occupy if resized to fit inside a thumbnail bounding box of size
@ -32,7 +30,7 @@ module.exports = {
* consume in the timeline, when performing scroll offset calcuations * consume in the timeline, when performing scroll offset calcuations
* (e.g. scroll locking) * (e.g. scroll locking)
*/ */
thumbHeight: function(fullWidth, fullHeight, thumbWidth, thumbHeight) { export function thumbHeight(fullWidth, fullHeight, thumbWidth, thumbHeight) {
if (!fullWidth || !fullHeight) { if (!fullWidth || !fullHeight) {
// Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even // Cannot calculate thumbnail height for image: missing w/h in metadata. We can't even
// log this because it's spammy // log this because it's spammy
@ -51,6 +49,5 @@ module.exports = {
// height is the dominant dimension so scaling will be fixed on that // height is the dominant dimension so scaling will be fixed on that
return Math.floor(heightMulti * fullHeight); return Math.floor(heightMulti * fullHeight);
} }
}, }
};

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import sdk from './index'; import * as sdk from './index';
import Modal from './Modal'; import Modal from './Modal';
export default class KeyRequestHandler { export default class KeyRequestHandler {

View file

@ -18,7 +18,7 @@ limitations under the License.
import Matrix from 'matrix-js-sdk'; import Matrix from 'matrix-js-sdk';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import EventIndexPeg from './indexing/EventIndexPeg'; import EventIndexPeg from './indexing/EventIndexPeg';
import createMatrixClient from './utils/createMatrixClient'; import createMatrixClient from './utils/createMatrixClient';
import Analytics from './Analytics'; import Analytics from './Analytics';
@ -28,7 +28,7 @@ import Presence from './Presence';
import dis from './dispatcher'; import dis from './dispatcher';
import DMRoomMap from './utils/DMRoomMap'; import DMRoomMap from './utils/DMRoomMap';
import Modal from './Modal'; import Modal from './Modal';
import sdk from './index'; import * as sdk from './index';
import ActiveWidgetStore from './stores/ActiveWidgetStore'; import ActiveWidgetStore from './stores/ActiveWidgetStore';
import PlatformPeg from "./PlatformPeg"; import PlatformPeg from "./PlatformPeg";
import { sendLoginRequest } from "./Login"; import { sendLoginRequest } from "./Login";

View file

@ -19,15 +19,15 @@ limitations under the License.
import {MatrixClient, MemoryStore} from 'matrix-js-sdk'; import {MatrixClient, MemoryStore} from 'matrix-js-sdk';
import utils from 'matrix-js-sdk/lib/utils'; import * as utils from 'matrix-js-sdk/src/utils';
import EventTimeline from 'matrix-js-sdk/lib/models/event-timeline'; import {EventTimeline} from 'matrix-js-sdk/src/models/event-timeline';
import EventTimelineSet from 'matrix-js-sdk/lib/models/event-timeline-set'; import {EventTimelineSet} from 'matrix-js-sdk/src/models/event-timeline-set';
import sdk from './index'; import * as sdk from './index';
import createMatrixClient from './utils/createMatrixClient'; import createMatrixClient from './utils/createMatrixClient';
import SettingsStore from './settings/SettingsStore'; import SettingsStore from './settings/SettingsStore';
import MatrixActionCreators from './actions/MatrixActionCreators'; import MatrixActionCreators from './actions/MatrixActionCreators';
import Modal from './Modal'; import Modal from './Modal';
import {verificationMethods} from 'matrix-js-sdk/lib/crypto'; import {verificationMethods} from 'matrix-js-sdk/src/crypto';
import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientBackedSettingsHandler"; import MatrixClientBackedSettingsHandler from "./settings/handlers/MatrixClientBackedSettingsHandler";
import * as StorageManager from './utils/StorageManager'; import * as StorageManager from './utils/StorageManager';
import IdentityAuthClient from './IdentityAuthClient'; import IdentityAuthClient from './IdentityAuthClient';
@ -48,7 +48,7 @@ interface MatrixClientCreds {
* This module provides a singleton instance of this class so the 'current' * This module provides a singleton instance of this class so the 'current'
* Matrix Client object is available easily. * Matrix Client object is available easily.
*/ */
class MatrixClientPeg { class _MatrixClientPeg {
constructor() { constructor() {
this.matrixClient = null; this.matrixClient = null;
this._justRegisteredUserId = null; this._justRegisteredUserId = null;
@ -245,6 +245,7 @@ class MatrixClientPeg {
} }
if (!global.mxMatrixClientPeg) { if (!global.mxMatrixClientPeg) {
global.mxMatrixClientPeg = new MatrixClientPeg(); global.mxMatrixClientPeg = new _MatrixClientPeg();
} }
export default global.mxMatrixClientPeg;
export const MatrixClientPeg = global.mxMatrixClientPeg;

View file

@ -20,7 +20,7 @@ import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import Analytics from './Analytics'; import Analytics from './Analytics';
import sdk from './index'; import * as sdk from './index';
import dis from './dispatcher'; import dis from './dispatcher';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import {defer} from "./utils/promise"; import {defer} from "./utils/promise";

View file

@ -16,13 +16,13 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import PlatformPeg from './PlatformPeg'; import PlatformPeg from './PlatformPeg';
import TextForEvent from './TextForEvent'; import * as TextForEvent from './TextForEvent';
import Analytics from './Analytics'; import Analytics from './Analytics';
import Avatar from './Avatar'; import * as Avatar from './Avatar';
import dis from './dispatcher'; import dis from './dispatcher';
import sdk from './index'; import * as sdk from './index';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import Modal from './Modal'; import Modal from './Modal';
import SettingsStore, {SettingLevel} from "./settings/SettingsStore"; import SettingsStore, {SettingLevel} from "./settings/SettingsStore";
@ -364,4 +364,4 @@ if (!global.mxNotifier) {
global.mxNotifier = Notifier; global.mxNotifier = Notifier;
} }
module.exports = global.mxNotifier; export default global.mxNotifier;

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -22,7 +23,7 @@ limitations under the License.
* @return {Object[]} An array of objects with the form: * @return {Object[]} An array of objects with the form:
* { key: $KEY, val: $VALUE, place: "add|del" } * { key: $KEY, val: $VALUE, place: "add|del" }
*/ */
module.exports.getKeyValueArrayDiffs = function(before, after) { export function getKeyValueArrayDiffs(before, after) {
const results = []; const results = [];
const delta = {}; const delta = {};
Object.keys(before).forEach(function(beforeKey) { Object.keys(before).forEach(function(beforeKey) {
@ -76,7 +77,7 @@ module.exports.getKeyValueArrayDiffs = function(before, after) {
}); });
return results; return results;
}; }
/** /**
* Shallow-compare two objects for equality: each key and value must be identical * Shallow-compare two objects for equality: each key and value must be identical
@ -84,7 +85,7 @@ module.exports.getKeyValueArrayDiffs = function(before, after) {
* @param {Object} objB Second object to compare against the first * @param {Object} objB Second object to compare against the first
* @return {boolean} whether the two objects have same key=values * @return {boolean} whether the two objects have same key=values
*/ */
module.exports.shallowEqual = function(objA, objB) { export function shallowEqual(objA, objB) {
if (objA === objB) { if (objA === objB) {
return true; return true;
} }
@ -109,4 +110,4 @@ module.exports.shallowEqual = function(objA, objB) {
} }
return true; return true;
}; }

View file

@ -25,7 +25,7 @@ import { _t } from './languageHandler';
* the client owns the given email address, which is then passed to the password * the client owns the given email address, which is then passed to the password
* API on the homeserver in question with the new password. * API on the homeserver in question with the new password.
*/ */
class PasswordReset { export default class PasswordReset {
/** /**
* Configure the endpoints for password resetting. * Configure the endpoints for password resetting.
* @param {string} homeserverUrl The URL to the HS which has the account to reset. * @param {string} homeserverUrl The URL to the HS which has the account to reset.
@ -101,4 +101,3 @@ class PasswordReset {
} }
} }
module.exports = PasswordReset;

View file

@ -47,4 +47,4 @@ class PlatformPeg {
if (!global.mxPlatformPeg) { if (!global.mxPlatformPeg) {
global.mxPlatformPeg = new PlatformPeg(); global.mxPlatformPeg = new PlatformPeg();
} }
module.exports = global.mxPlatformPeg; export default global.mxPlatformPeg;

View file

@ -1,6 +1,7 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2018 New Vector Ltd Copyright 2018 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -15,7 +16,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from "./MatrixClientPeg"; import {MatrixClientPeg} from "./MatrixClientPeg";
import dis from "./dispatcher"; import dis from "./dispatcher";
import Timer from './utils/Timer'; import Timer from './utils/Timer';
@ -104,4 +105,4 @@ class Presence {
} }
} }
module.exports = new Presence(); export default new Presence();

View file

@ -21,10 +21,10 @@ limitations under the License.
*/ */
import dis from './dispatcher'; import dis from './dispatcher';
import sdk from './index'; import * as sdk from './index';
import Modal from './Modal'; import Modal from './Modal';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
// import MatrixClientPeg from './MatrixClientPeg'; // import {MatrixClientPeg} from './MatrixClientPeg';
// Regex for what a "safe" or "Matrix-looking" localpart would be. // Regex for what a "safe" or "Matrix-looking" localpart would be.
// TODO: Update as needed for https://github.com/matrix-org/matrix-doc/issues/1514 // TODO: Update as needed for https://github.com/matrix-org/matrix-doc/issues/1514

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,26 +15,28 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import dis from './dispatcher'; import dis from './dispatcher';
import { EventStatus } from 'matrix-js-sdk'; import { EventStatus } from 'matrix-js-sdk';
module.exports = { export default class Resend {
resendUnsentEvents: function(room) { static resendUnsentEvents(room) {
room.getPendingEvents().filter(function(ev) { room.getPendingEvents().filter(function(ev) {
return ev.status === EventStatus.NOT_SENT; return ev.status === EventStatus.NOT_SENT;
}).forEach(function(event) { }).forEach(function(event) {
module.exports.resend(event); Resend.resend(event);
}); });
}, }
cancelUnsentEvents: function(room) {
static cancelUnsentEvents(room) {
room.getPendingEvents().filter(function(ev) { room.getPendingEvents().filter(function(ev) {
return ev.status === EventStatus.NOT_SENT; return ev.status === EventStatus.NOT_SENT;
}).forEach(function(event) { }).forEach(function(event) {
module.exports.removeFromQueue(event); Resend.removeFromQueue(event);
}); });
}, }
resend: function(event) {
static resend(event) {
const room = MatrixClientPeg.get().getRoom(event.getRoomId()); const room = MatrixClientPeg.get().getRoom(event.getRoomId());
MatrixClientPeg.get().resendEvent(event, room).then(function(res) { MatrixClientPeg.get().resendEvent(event, room).then(function(res) {
dis.dispatch({ dis.dispatch({
@ -50,8 +53,9 @@ module.exports = {
event: event, event: event,
}); });
}); });
}, }
removeFromQueue: function(event) {
static removeFromQueue(event) {
MatrixClientPeg.get().cancelPendingEvent(event); MatrixClientPeg.get().cancelPendingEvent(event);
}, }
}; }

View file

@ -16,12 +16,12 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import MultiInviter from './utils/MultiInviter'; import MultiInviter from './utils/MultiInviter';
import Modal from './Modal'; import Modal from './Modal';
import { getAddressType } from './UserAddress'; import { getAddressType } from './UserAddress';
import createRoom from './createRoom'; import createRoom from './createRoom';
import sdk from './'; import * as sdk from './';
import dis from './dispatcher'; import dis from './dispatcher';
import DMRoomMap from './utils/DMRoomMap'; import DMRoomMap from './utils/DMRoomMap';
import { _t } from './languageHandler'; import { _t } from './languageHandler';

View file

@ -24,12 +24,8 @@ function tsOfNewestEvent(room) {
} }
} }
function mostRecentActivityFirst(roomList) { export function mostRecentActivityFirst(roomList) {
return roomList.sort(function(a, b) { return roomList.sort(function(a, b) {
return tsOfNewestEvent(b) - tsOfNewestEvent(a); return tsOfNewestEvent(b) - tsOfNewestEvent(a);
}); });
} }
module.exports = {
mostRecentActivityFirst,
};

View file

@ -15,8 +15,8 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import PushProcessor from 'matrix-js-sdk/lib/pushprocessor'; import {PushProcessor} from 'matrix-js-sdk/src/pushprocessor';
export const ALL_MESSAGES_LOUD = 'all_messages_loud'; export const ALL_MESSAGES_LOUD = 'all_messages_loud';
export const ALL_MESSAGES = 'all_messages'; export const ALL_MESSAGES = 'all_messages';

View file

@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
/** /**
* Given a room object, return the alias we should use for it, * Given a room object, return the alias we should use for it,

View file

@ -18,12 +18,11 @@ limitations under the License.
import url from 'url'; import url from 'url';
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import { Service, startTermsFlow, TermsNotSignedError } from './Terms'; import { Service, startTermsFlow, TermsNotSignedError } from './Terms';
const request = require('browser-request'); import {MatrixClientPeg} from "./MatrixClientPeg";
import request from "browser-request";
const SdkConfig = require('./SdkConfig');
const MatrixClientPeg = require('./MatrixClientPeg');
import * as Matrix from 'matrix-js-sdk'; import * as Matrix from 'matrix-js-sdk';
import SdkConfig from "./SdkConfig";
// The version of the integration manager API we're intending to work with // The version of the integration manager API we're intending to work with
const imApiVersion = "1.1"; const imApiVersion = "1.1";

View file

@ -232,7 +232,7 @@ Example:
} }
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import { MatrixEvent } from 'matrix-js-sdk'; import { MatrixEvent } from 'matrix-js-sdk';
import dis from './dispatcher'; import dis from './dispatcher';
import WidgetUtils from './utils/WidgetUtils'; import WidgetUtils from './utils/WidgetUtils';
@ -658,15 +658,15 @@ const onMessage = function(event) {
let listenerCount = 0; let listenerCount = 0;
let openManagerUrl = null; let openManagerUrl = null;
module.exports = {
startListening: function() { export function startListening() {
if (listenerCount === 0) { if (listenerCount === 0) {
window.addEventListener("message", onMessage, false); window.addEventListener("message", onMessage, false);
} }
listenerCount += 1; listenerCount += 1;
}, }
stopListening: function() { export function stopListening() {
listenerCount -= 1; listenerCount -= 1;
if (listenerCount === 0) { if (listenerCount === 0) {
window.removeEventListener("message", onMessage); window.removeEventListener("message", onMessage);
@ -679,9 +679,8 @@ module.exports = {
); );
console.error(e); console.error(e);
} }
}, }
setOpenManagerUrl: function(url) { export function setOpenManagerUrl(url) {
openManagerUrl = url; openManagerUrl = url;
}, }
};

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,7 +15,11 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
export const DEFAULTS = { export interface ConfigOptions {
[key: string]: any;
}
export const DEFAULTS: ConfigOptions = {
// URL to a page we show in an iframe to configure integrations // URL to a page we show in an iframe to configure integrations
integrations_ui_url: "https://scalar.vector.im/", integrations_ui_url: "https://scalar.vector.im/",
// Base URL to the REST interface of the integrations server // Base URL to the REST interface of the integrations server
@ -23,30 +28,37 @@ export const DEFAULTS = {
bug_report_endpoint_url: null, bug_report_endpoint_url: null,
}; };
class SdkConfig { export default class SdkConfig {
static get() { private static instance: ConfigOptions;
return global.mxReactSdkConfig || {};
private static setInstance(i: ConfigOptions) {
SdkConfig.instance = i;
// For debugging purposes
(<any>window).mxReactSdkConfig = i;
} }
static put(cfg) { static get() {
return SdkConfig.instance || {};
}
static put(cfg: ConfigOptions) {
const defaultKeys = Object.keys(DEFAULTS); const defaultKeys = Object.keys(DEFAULTS);
for (let i = 0; i < defaultKeys.length; ++i) { for (let i = 0; i < defaultKeys.length; ++i) {
if (cfg[defaultKeys[i]] === undefined) { if (cfg[defaultKeys[i]] === undefined) {
cfg[defaultKeys[i]] = DEFAULTS[defaultKeys[i]]; cfg[defaultKeys[i]] = DEFAULTS[defaultKeys[i]];
} }
} }
global.mxReactSdkConfig = cfg; SdkConfig.setInstance(cfg);
} }
static unset() { static unset() {
global.mxReactSdkConfig = undefined; SdkConfig.setInstance({});
} }
static add(cfg) { static add(cfg: ConfigOptions) {
const liveConfig = SdkConfig.get(); const liveConfig = SdkConfig.get();
const newConfig = Object.assign({}, liveConfig, cfg); const newConfig = Object.assign({}, liveConfig, cfg);
SdkConfig.put(newConfig); SdkConfig.put(newConfig);
} }
} }
module.exports = SdkConfig;

View file

@ -15,7 +15,7 @@ limitations under the License.
*/ */
import EventIndexPeg from "./indexing/EventIndexPeg"; import EventIndexPeg from "./indexing/EventIndexPeg";
import MatrixClientPeg from "./MatrixClientPeg"; import {MatrixClientPeg} from "./MatrixClientPeg";
function serverSideSearch(term, roomId = undefined) { function serverSideSearch(term, roomId = undefined) {
let filter; let filter;

View file

@ -28,21 +28,37 @@ class Skinner {
" b) A component has called getComponent at the root level", " b) A component has called getComponent at the root level",
); );
} }
let comp = this.components[name];
const doLookup = (components) => {
if (!components) return null;
let comp = components[name];
// XXX: Temporarily also try 'views.' as we're currently // XXX: Temporarily also try 'views.' as we're currently
// leaving the 'views.' off views. // leaving the 'views.' off views.
if (!comp) { if (!comp) {
comp = this.components['views.'+name]; comp = components['views.' + name];
}
return comp;
};
// Check the skin first
let comp = doLookup(this.components);
// If that failed, check against our own components
if (!comp) {
// Lazily load our own components because they might end up calling .getComponent()
comp = doLookup(require("./component-index").components);
} }
// Just return nothing instead of erroring - the consumer should be smart enough to
// handle this at this point.
if (!comp) { if (!comp) {
throw new Error("No such component: "+name); return null;
} }
// components have to be functions. // components have to be functions.
const validType = typeof comp === 'function'; const validType = typeof comp === 'function';
if (!validType) { if (!validType) {
throw new Error(`Not a valid component: ${name}.`); throw new Error(`Not a valid component: ${name} (type = ${typeof(comp)}).`);
} }
return comp; return comp;
} }
@ -90,5 +106,5 @@ class Skinner {
if (global.mxSkinner === undefined) { if (global.mxSkinner === undefined) {
global.mxSkinner = new Skinner(); global.mxSkinner = new Skinner();
} }
module.exports = global.mxSkinner; export default global.mxSkinner;

View file

@ -18,9 +18,9 @@ limitations under the License.
import React from 'react'; import React from 'react';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import dis from './dispatcher'; import dis from './dispatcher';
import sdk from './index'; import * as sdk from './index';
import {_t, _td} from './languageHandler'; import {_t, _td} from './languageHandler';
import Modal from './Modal'; import Modal from './Modal';
import MultiInviter from './utils/MultiInviter'; import MultiInviter from './utils/MultiInviter';

View file

@ -16,8 +16,8 @@ limitations under the License.
import classNames from 'classnames'; import classNames from 'classnames';
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import sdk from './'; import * as sdk from './';
import Modal from './Modal'; import Modal from './Modal';
export class TermsNotSignedError extends Error {} export class TermsNotSignedError extends Error {}

View file

@ -13,7 +13,7 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from './MatrixClientPeg'; import {MatrixClientPeg} from './MatrixClientPeg';
import CallHandler from './CallHandler'; import CallHandler from './CallHandler';
import { _t } from './languageHandler'; import { _t } from './languageHandler';
import * as Roles from './Roles'; import * as Roles from './Roles';
@ -620,10 +620,8 @@ for (const evType of ALL_RULE_TYPES) {
stateHandlers[evType] = textForMjolnirEvent; stateHandlers[evType] = textForMjolnirEvent;
} }
module.exports = { export function textForEvent(ev) {
textForEvent: function(ev) {
const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()]; const handler = (ev.isState() ? stateHandlers : handlers)[ev.getType()];
if (handler) return handler(ev); if (handler) return handler(ev);
return ''; return '';
}, }
};

View file

@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
const MatrixClientPeg = require('./MatrixClientPeg'); import {MatrixClientPeg} from "./MatrixClientPeg";
import shouldHideEvent from './shouldHideEvent'; import shouldHideEvent from './shouldHideEvent';
const sdk = require('./index'); import * as sdk from "./index";
import {haveTileForEvent} from "./components/views/rooms/EventTile";
module.exports = {
/** /**
* Returns true iff this event arriving in a room should affect the room's * Returns true iff this event arriving in a room should affect the room's
* count of unread messages * count of unread messages
*/ */
eventTriggersUnreadCount: function(ev) { export function eventTriggersUnreadCount(ev) {
if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) { if (ev.sender && ev.sender.userId == MatrixClientPeg.get().credentials.userId) {
return false; return false;
} else if (ev.getType() == 'm.room.member') { } else if (ev.getType() == 'm.room.member') {
@ -39,11 +39,10 @@ module.exports = {
} else if (ev.getType() == 'm.room.server_acl') { } else if (ev.getType() == 'm.room.server_acl') {
return false; return false;
} }
const EventTile = sdk.getComponent('rooms.EventTile'); return haveTileForEvent(ev);
return EventTile.haveTileForEvent(ev); }
},
doesRoomHaveUnreadMessages: function(room) { export function doesRoomHaveUnreadMessages(room) {
const myUserId = MatrixClientPeg.get().credentials.userId; const myUserId = MatrixClientPeg.get().credentials.userId;
// get the most recent read receipt sent by our account. // get the most recent read receipt sent by our account.
@ -78,7 +77,7 @@ module.exports = {
// that counts and we can stop looking because the user's read // that counts and we can stop looking because the user's read
// this and everything before. // this and everything before.
return false; return false;
} else if (!shouldHideEvent(ev) && this.eventTriggersUnreadCount(ev)) { } else if (!shouldHideEvent(ev) && eventTriggersUnreadCount(ev)) {
// We've found a message that counts before we hit // We've found a message that counts before we hit
// the user's read receipt, so this room is definitely unread. // the user's read receipt, so this room is definitely unread.
return true; return true;
@ -89,5 +88,4 @@ module.exports = {
// unread on the theory that false positives are better than false // unread on the theory that false positives are better than false
// negatives here. // negatives here.
return true; return true;
}, }
};

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -14,9 +15,9 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {createNewMatrixCall, Room} from "matrix-js-sdk"; import {createNewMatrixCall as jsCreateNewMatrixCall, Room} from "matrix-js-sdk";
import CallHandler from './CallHandler'; import CallHandler from './CallHandler';
import MatrixClientPeg from "./MatrixClientPeg"; import {MatrixClientPeg} from "./MatrixClientPeg";
// FIXME: this is Riot (Vector) specific code, but will be removed shortly when // FIXME: this is Riot (Vector) specific code, but will be removed shortly when
// we switch over to jitsi entirely for video conferencing. // we switch over to jitsi entirely for video conferencing.
@ -28,10 +29,10 @@ import MatrixClientPeg from "./MatrixClientPeg";
const USER_PREFIX = "fs_"; const USER_PREFIX = "fs_";
const DOMAIN = "matrix.org"; const DOMAIN = "matrix.org";
function ConferenceCall(matrixClient, groupChatRoomId) { export function ConferenceCall(matrixClient, groupChatRoomId) {
this.client = matrixClient; this.client = matrixClient;
this.groupRoomId = groupChatRoomId; this.groupRoomId = groupChatRoomId;
this.confUserId = module.exports.getConferenceUserIdForRoom(this.groupRoomId); this.confUserId = getConferenceUserIdForRoom(this.groupRoomId);
} }
ConferenceCall.prototype.setup = function() { ConferenceCall.prototype.setup = function() {
@ -42,7 +43,7 @@ ConferenceCall.prototype.setup = function() {
// return a call for *this* room to be placed. We also tack on // return a call for *this* room to be placed. We also tack on
// confUserId to speed up lookups (else we'd need to loop every room // confUserId to speed up lookups (else we'd need to loop every room
// looking for a 1:1 room with this conf user ID!) // looking for a 1:1 room with this conf user ID!)
const call = createNewMatrixCall(self.client, room.roomId); const call = jsCreateNewMatrixCall(self.client, room.roomId);
call.confUserId = self.confUserId; call.confUserId = self.confUserId;
call.groupRoomId = self.groupRoomId; call.groupRoomId = self.groupRoomId;
return call; return call;
@ -90,7 +91,7 @@ ConferenceCall.prototype._getConferenceUserRoom = function() {
* @param {string} userId The user ID to check. * @param {string} userId The user ID to check.
* @return {boolean} True if it is a conference bot. * @return {boolean} True if it is a conference bot.
*/ */
module.exports.isConferenceUser = function(userId) { export function isConferenceUser(userId) {
if (userId.indexOf("@" + USER_PREFIX) !== 0) { if (userId.indexOf("@" + USER_PREFIX) !== 0) {
return false; return false;
} }
@ -101,26 +102,26 @@ module.exports.isConferenceUser = function(userId) {
return /^!.+:.+/.test(decoded); return /^!.+:.+/.test(decoded);
} }
return false; return false;
}; }
module.exports.getConferenceUserIdForRoom = function(roomId) { export function getConferenceUserIdForRoom(roomId) {
// abuse browserify's core node Buffer support (strip padding ='s) // abuse browserify's core node Buffer support (strip padding ='s)
const base64RoomId = new Buffer(roomId).toString("base64").replace(/=/g, ""); const base64RoomId = new Buffer(roomId).toString("base64").replace(/=/g, "");
return "@" + USER_PREFIX + base64RoomId + ":" + DOMAIN; return "@" + USER_PREFIX + base64RoomId + ":" + DOMAIN;
}; }
module.exports.createNewMatrixCall = function(client, roomId) { export function createNewMatrixCall(client, roomId) {
const confCall = new ConferenceCall( const confCall = new ConferenceCall(
client, roomId, client, roomId,
); );
return confCall.setup(); return confCall.setup();
}; }
module.exports.getConferenceCallForRoom = function(roomId) { export function getConferenceCallForRoom(roomId) {
// search for a conference 1:1 call for this group chat room ID // search for a conference 1:1 call for this group chat room ID
const activeCall = CallHandler.getAnyActiveCall(); const activeCall = CallHandler.getAnyActiveCall();
if (activeCall && activeCall.confUserId) { if (activeCall && activeCall.confUserId) {
const thisRoomConfUserId = module.exports.getConferenceUserIdForRoom( const thisRoomConfUserId = getConferenceUserIdForRoom(
roomId, roomId,
); );
if (thisRoomConfUserId === activeCall.confUserId) { if (thisRoomConfUserId === activeCall.confUserId) {
@ -128,8 +129,7 @@ module.exports.getConferenceCallForRoom = function(roomId) {
} }
} }
return null; return null;
}; }
module.exports.ConferenceCall = ConferenceCall; // TODO: Document this.
export const slot = 'conference';
module.exports.slot = 'conference';

View file

@ -1,7 +1,7 @@
const React = require('react'); import React from "react";
const ReactDom = require('react-dom'); import ReactDom from "react-dom";
import Velocity from "velocity-animate";
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
const Velocity = require('velocity-animate');
/** /**
* The Velociraptor contains components and animates transitions with velocity. * The Velociraptor contains components and animates transitions with velocity.

View file

@ -1,4 +1,4 @@
const Velocity = require('velocity-animate'); import Velocity from "velocity-animate";
// courtesy of https://github.com/julianshapiro/velocity/issues/283 // courtesy of https://github.com/julianshapiro/velocity/issues/283
// We only use easeOutBounce (easeInBounce is just sort of nonsensical) // We only use easeOutBounce (easeInBounce is just sort of nonsensical)

View file

@ -14,21 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import MatrixClientPeg from "./MatrixClientPeg"; import {MatrixClientPeg} from "./MatrixClientPeg";
import { _t } from './languageHandler'; import { _t } from './languageHandler';
module.exports = { export function usersTypingApartFromMeAndIgnored(room) {
usersTypingApartFromMeAndIgnored: function(room) { return usersTyping(
return this.usersTyping(
room, [MatrixClientPeg.get().credentials.userId].concat(MatrixClientPeg.get().getIgnoredUsers()), room, [MatrixClientPeg.get().credentials.userId].concat(MatrixClientPeg.get().getIgnoredUsers()),
); );
}, }
usersTypingApartFromMe: function(room) { export function usersTypingApartFromMe(room) {
return this.usersTyping( return usersTyping(
room, [MatrixClientPeg.get().credentials.userId], room, [MatrixClientPeg.get().credentials.userId],
); );
}, }
/** /**
* Given a Room object and, optionally, a list of userID strings * Given a Room object and, optionally, a list of userID strings
@ -37,7 +36,7 @@ module.exports = {
* @param {string[]} exclude: list of user mxids to exclude. * @param {string[]} exclude: list of user mxids to exclude.
* @returns {string[]} list of user objects who are typing. * @returns {string[]} list of user objects who are typing.
*/ */
usersTyping: function(room, exclude) { export function usersTyping(room, exclude) {
const whoIsTyping = []; const whoIsTyping = [];
if (exclude === undefined) { if (exclude === undefined) {
@ -56,9 +55,9 @@ module.exports = {
} }
return whoIsTyping; return whoIsTyping;
}, }
whoIsTypingString: function(whoIsTyping, limit) { export function whoIsTypingString(whoIsTyping, limit) {
let othersCount = 0; let othersCount = 0;
if (whoIsTyping.length > limit) { if (whoIsTyping.length > limit) {
othersCount = whoIsTyping.length - limit + 1; othersCount = whoIsTyping.length - limit + 1;
@ -80,5 +79,4 @@ module.exports = {
const lastPerson = names.pop(); const lastPerson = names.pop();
return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson}); return _t('%(names)s and %(lastPerson)s are typing …', {names: names.join(', '), lastPerson: lastPerson});
} }
}, }
};

View file

@ -23,7 +23,7 @@ limitations under the License.
import FromWidgetPostMessageApi from './FromWidgetPostMessageApi'; import FromWidgetPostMessageApi from './FromWidgetPostMessageApi';
import ToWidgetPostMessageApi from './ToWidgetPostMessageApi'; import ToWidgetPostMessageApi from './ToWidgetPostMessageApi';
import Modal from "./Modal"; import Modal from "./Modal";
import MatrixClientPeg from "./MatrixClientPeg"; import {MatrixClientPeg} from "./MatrixClientPeg";
import SettingsStore from "./settings/SettingsStore"; import SettingsStore from "./settings/SettingsStore";
import WidgetOpenIDPermissionsDialog from "./components/views/dialogs/WidgetOpenIDPermissionsDialog"; import WidgetOpenIDPermissionsDialog from "./components/views/dialogs/WidgetOpenIDPermissionsDialog";
import WidgetUtils from "./utils/WidgetUtils"; import WidgetUtils from "./utils/WidgetUtils";

View file

@ -16,11 +16,10 @@ limitations under the License.
import { asyncAction } from './actionCreators'; import { asyncAction } from './actionCreators';
import RoomListStore from '../stores/RoomListStore'; import RoomListStore from '../stores/RoomListStore';
import Modal from '../Modal'; import Modal from '../Modal';
import * as Rooms from '../Rooms'; import * as Rooms from '../Rooms';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import sdk from '../index'; import * as sdk from '../index';
const RoomListActions = {}; const RoomListActions = {};

View file

@ -14,19 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import {Key} from "../../../Keyboard"; import React from "react";
const React = require("react");
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
const sdk = require('../../../index'); import {MatrixClientPeg} from "../../../MatrixClientPeg";
const MatrixClientPeg = require("../../../MatrixClientPeg"); import {Key} from "../../../Keyboard";
import * as sdk from "../../../index";
// XXX: This component is not cross-signing aware. // XXX: This component is not cross-signing aware.
// https://github.com/vector-im/riot-web/issues/11752 tracks either updating this // https://github.com/vector-im/riot-web/issues/11752 tracks either updating this
// component or taking it out to pasture. // component or taking it out to pasture.
module.exports = createReactClass({ export default createReactClass({
displayName: 'EncryptedEventDialog', displayName: 'EncryptedEventDialog',
propTypes: { propTypes: {

View file

@ -22,7 +22,7 @@ import { _t } from '../../../languageHandler';
import { MatrixClient } from 'matrix-js-sdk'; import { MatrixClient } from 'matrix-js-sdk';
import * as MegolmExportEncryption from '../../../utils/MegolmExportEncryption'; import * as MegolmExportEncryption from '../../../utils/MegolmExportEncryption';
import sdk from '../../../index'; import * as sdk from '../../../index';
const PHASE_EDIT = 1; const PHASE_EDIT = 1;
const PHASE_EXPORTING = 2; const PHASE_EXPORTING = 2;

View file

@ -20,7 +20,7 @@ import createReactClass from 'create-react-class';
import { MatrixClient } from 'matrix-js-sdk'; import { MatrixClient } from 'matrix-js-sdk';
import * as MegolmExportEncryption from '../../../utils/MegolmExportEncryption'; import * as MegolmExportEncryption from '../../../utils/MegolmExportEncryption';
import sdk from '../../../index'; import * as sdk from '../../../index';
import { _t } from '../../../languageHandler'; import { _t } from '../../../languageHandler';
function readFileAsArrayBuffer(file) { function readFileAsArrayBuffer(file) {

View file

@ -17,10 +17,9 @@ limitations under the License.
import React from 'react'; import React from 'react';
import FileSaver from 'file-saver'; import FileSaver from 'file-saver';
import * as sdk from '../../../../index';
import {MatrixClientPeg} from '../../../../MatrixClientPeg';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import sdk from '../../../../index';
import MatrixClientPeg from '../../../../MatrixClientPeg';
import { scorePassword } from '../../../../utils/PasswordScorer'; import { scorePassword } from '../../../../utils/PasswordScorer';
import { _t } from '../../../../languageHandler'; import { _t } from '../../../../languageHandler';
import { accessSecretStorage } from '../../../../CrossSigningManager'; import { accessSecretStorage } from '../../../../CrossSigningManager';

View file

@ -16,7 +16,7 @@ limitations under the License.
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import sdk from "../../../../index"; import * as sdk from "../../../../index";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
export default class IgnoreRecoveryReminderDialog extends React.PureComponent { export default class IgnoreRecoveryReminderDialog extends React.PureComponent {

View file

@ -17,8 +17,8 @@ limitations under the License.
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import sdk from "../../../../index"; import * as sdk from "../../../../index";
import MatrixClientPeg from '../../../../MatrixClientPeg'; import {MatrixClientPeg} from '../../../../MatrixClientPeg';
import dis from "../../../../dispatcher"; import dis from "../../../../dispatcher";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import Modal from "../../../../Modal"; import Modal from "../../../../Modal";

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from "react"; import React from "react";
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import sdk from "../../../../index"; import * as sdk from "../../../../index";
import dis from "../../../../dispatcher"; import dis from "../../../../dispatcher";
import { _t } from "../../../../languageHandler"; import { _t } from "../../../../languageHandler";
import Modal from "../../../../Modal"; import Modal from "../../../../Modal";

View file

@ -16,22 +16,23 @@ limitations under the License.
*/ */
import React from 'react'; import React from 'react';
import sdk from '../../../../index'; import * as sdk from '../../../../index';
import MatrixClientPeg from '../../../../MatrixClientPeg'; import {MatrixClientPeg} from '../../../../MatrixClientPeg';
import { scorePassword } from '../../../../utils/PasswordScorer'; import { scorePassword } from '../../../../utils/PasswordScorer';
import FileSaver from 'file-saver'; import FileSaver from 'file-saver';
import { _t } from '../../../../languageHandler'; import { _t } from '../../../../languageHandler';
import Modal from '../../../../Modal'; import Modal from '../../../../Modal';
const PHASE_LOADING = 0; const PHASE_LOADING = 0;
const PHASE_MIGRATE = 1; const PHASE_RESTORE_KEY_BACKUP = 1;
const PHASE_PASSPHRASE = 2; const PHASE_MIGRATE = 2;
const PHASE_PASSPHRASE_CONFIRM = 3; const PHASE_PASSPHRASE = 3;
const PHASE_SHOWKEY = 4; const PHASE_PASSPHRASE_CONFIRM = 4;
const PHASE_KEEPITSAFE = 5; const PHASE_SHOWKEY = 5;
const PHASE_STORING = 6; const PHASE_KEEPITSAFE = 6;
const PHASE_DONE = 7; const PHASE_STORING = 7;
const PHASE_OPTOUT_CONFIRM = 8; const PHASE_DONE = 8;
const PHASE_OPTOUT_CONFIRM = 9;
const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc. const PASSWORD_MIN_SCORE = 4; // So secure, many characters, much complex, wow, etc, etc.
const PASSPHRASE_FEEDBACK_DELAY = 500; // How long after keystroke to offer passphrase feedback, ms. const PASSPHRASE_FEEDBACK_DELAY = 500; // How long after keystroke to offer passphrase feedback, ms.
@ -67,6 +68,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
downloaded: false, downloaded: false,
zxcvbnResult: null, zxcvbnResult: null,
setPassPhrase: false, setPassPhrase: false,
backupInfo: null,
backupSigStatus: null,
}; };
this._fetchBackupInfo(); this._fetchBackupInfo();
@ -80,10 +83,16 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
async _fetchBackupInfo() { async _fetchBackupInfo() {
const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion(); const backupInfo = await MatrixClientPeg.get().getKeyBackupVersion();
const backupSigStatus = await MatrixClientPeg.get().isKeyBackupTrusted(backupInfo);
const phase = backupInfo ?
(backupSigStatus.usable ? PHASE_MIGRATE : PHASE_RESTORE_KEY_BACKUP) :
PHASE_PASSPHRASE;
this.setState({ this.setState({
phase: backupInfo ? PHASE_MIGRATE: PHASE_PASSPHRASE, phase,
backupInfo, backupInfo,
backupSigStatus,
}); });
} }
@ -161,6 +170,14 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
this.props.onFinished(true); this.props.onFinished(true);
} }
_onRestoreKeyBackupClick = () => {
const RestoreKeyBackupDialog = sdk.getComponent('dialogs.keybackup.RestoreKeyBackupDialog');
Modal.createTrackedDialog(
'Restore Backup', '', RestoreKeyBackupDialog, null, null,
/* priority = */ false, /* static = */ true,
);
}
_onOptOutClick = () => { _onOptOutClick = () => {
this.setState({phase: PHASE_OPTOUT_CONFIRM}); this.setState({phase: PHASE_OPTOUT_CONFIRM});
} }
@ -268,6 +285,23 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
return this.state.zxcvbnResult && this.state.zxcvbnResult.score >= PASSWORD_MIN_SCORE; return this.state.zxcvbnResult && this.state.zxcvbnResult.score >= PASSWORD_MIN_SCORE;
} }
_renderPhaseRestoreKeyBackup() {
const DialogButtons = sdk.getComponent('views.elements.DialogButtons');
return <div>
<p>{_t(
"Key Backup is enabled on your account but has not been set " +
"up from this session. To set up secret storage, " +
"restore your key backup.",
)}</p>
<DialogButtons primaryButton={_t('Restore')}
onPrimaryButtonClick={this._onRestoreKeyBackupClick}
onCancel={this._onCancel}
hasCancel={true}
>
</DialogButtons>
</div>;
}
_renderPhaseMigrate() { _renderPhaseMigrate() {
// TODO: This is a temporary screen so people who have the labs flag turned on and // TODO: This is a temporary screen so people who have the labs flag turned on and
// click the button are aware they're making a change to their account. // click the button are aware they're making a change to their account.
@ -527,6 +561,8 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
_titleForPhase(phase) { _titleForPhase(phase) {
switch (phase) { switch (phase) {
case PHASE_RESTORE_KEY_BACKUP:
return _t('Restore your Key Backup');
case PHASE_MIGRATE: case PHASE_MIGRATE:
return _t('Migrate from Key Backup'); return _t('Migrate from Key Backup');
case PHASE_PASSPHRASE: case PHASE_PASSPHRASE:
@ -569,6 +605,9 @@ export default class CreateSecretStorageDialog extends React.PureComponent {
case PHASE_LOADING: case PHASE_LOADING:
content = this._renderBusyPhase(); content = this._renderBusyPhase();
break; break;
case PHASE_RESTORE_KEY_BACKUP:
content = this._renderPhaseRestoreKeyBackup();
break;
case PHASE_MIGRATE: case PHASE_MIGRATE:
content = this._renderPhaseMigrate(); content = this._renderPhaseMigrate();
break; break;

View file

@ -18,10 +18,10 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import MatrixClientPeg from '../MatrixClientPeg'; import {MatrixClientPeg} from '../MatrixClientPeg';
import QueryMatcher from './QueryMatcher'; import QueryMatcher from './QueryMatcher';
import {PillCompletion} from './Components'; import {PillCompletion} from './Components';
import sdk from '../index'; import * as sdk from '../index';
import _sortBy from 'lodash/sortBy'; import _sortBy from 'lodash/sortBy';
import {makeGroupPermalink} from "../utils/permalinks/Permalinks"; import {makeGroupPermalink} from "../utils/permalinks/Permalinks";
import type {Completion, SelectionRange} from "./Autocompleter"; import type {Completion, SelectionRange} from "./Autocompleter";
@ -46,7 +46,7 @@ export default class CommunityProvider extends AutocompleteProvider {
}); });
} }
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> { async getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar'); const BaseAvatar = sdk.getComponent('views.avatars.BaseAvatar');
// Disable autocompletions when composing commands because of various issues // Disable autocompletions when composing commands because of various issues

View file

@ -37,7 +37,7 @@ export default class DuckDuckGoProvider extends AutocompleteProvider {
+ `&format=json&no_redirect=1&no_html=1&t=${encodeURIComponent(REFERRER)}`; + `&format=json&no_redirect=1&no_html=1&t=${encodeURIComponent(REFERRER)}`;
} }
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false) { async getCompletions(query: string, selection: SelectionRange, force: boolean = false) {
const {command, range} = this.getCurrentCommand(query, selection); const {command, range} = this.getCurrentCommand(query, selection);
if (!query || !command) { if (!query || !command) {
return []; return [];

View file

@ -17,9 +17,9 @@ limitations under the License.
import React from 'react'; import React from 'react';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import MatrixClientPeg from '../MatrixClientPeg'; import {MatrixClientPeg} from '../MatrixClientPeg';
import {PillCompletion} from './Components'; import {PillCompletion} from './Components';
import sdk from '../index'; import * as sdk from '../index';
import type {Completion, SelectionRange} from "./Autocompleter"; import type {Completion, SelectionRange} from "./Autocompleter";
const AT_ROOM_REGEX = /@\S*/g; const AT_ROOM_REGEX = /@\S*/g;
@ -30,7 +30,7 @@ export default class NotifProvider extends AutocompleteProvider {
this.room = room; this.room = room;
} }
async getCompletions(query: string, selection: SelectionRange, force?:boolean = false): Array<Completion> { async getCompletions(query: string, selection: SelectionRange, force:boolean = false): Array<Completion> {
const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar'); const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();

View file

@ -20,11 +20,11 @@ limitations under the License.
import React from 'react'; import React from 'react';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import MatrixClientPeg from '../MatrixClientPeg'; import {MatrixClientPeg} from '../MatrixClientPeg';
import QueryMatcher from './QueryMatcher'; import QueryMatcher from './QueryMatcher';
import {PillCompletion} from './Components'; import {PillCompletion} from './Components';
import {getDisplayAliasForRoom} from '../Rooms'; import {getDisplayAliasForRoom} from '../Rooms';
import sdk from '../index'; import * as sdk from '../index';
import _sortBy from 'lodash/sortBy'; import _sortBy from 'lodash/sortBy';
import {makeRoomPermalink} from "../utils/permalinks/Permalinks"; import {makeRoomPermalink} from "../utils/permalinks/Permalinks";
import type {Completion, SelectionRange} from "./Autocompleter"; import type {Completion, SelectionRange} from "./Autocompleter";
@ -48,7 +48,7 @@ export default class RoomProvider extends AutocompleteProvider {
}); });
} }
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> { async getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar'); const RoomAvatar = sdk.getComponent('views.avatars.RoomAvatar');
const client = MatrixClientPeg.get(); const client = MatrixClientPeg.get();

View file

@ -22,10 +22,10 @@ import React from 'react';
import { _t } from '../languageHandler'; import { _t } from '../languageHandler';
import AutocompleteProvider from './AutocompleteProvider'; import AutocompleteProvider from './AutocompleteProvider';
import {PillCompletion} from './Components'; import {PillCompletion} from './Components';
import sdk from '../index'; import * as sdk from '../index';
import QueryMatcher from './QueryMatcher'; import QueryMatcher from './QueryMatcher';
import _sortBy from 'lodash/sortBy'; import _sortBy from 'lodash/sortBy';
import MatrixClientPeg from '../MatrixClientPeg'; import {MatrixClientPeg} from '../MatrixClientPeg';
import type {MatrixEvent, Room, RoomMember, RoomState} from 'matrix-js-sdk'; import type {MatrixEvent, Room, RoomMember, RoomState} from 'matrix-js-sdk';
import {makeUserPermalink} from "../utils/permalinks/Permalinks"; import {makeUserPermalink} from "../utils/permalinks/Permalinks";
@ -91,7 +91,7 @@ export default class UserProvider extends AutocompleteProvider {
this.users = null; this.users = null;
} }
async getCompletions(query: string, selection: SelectionRange, force?: boolean = false): Array<Completion> { async getCompletions(query: string, selection: SelectionRange, force: boolean = false): Array<Completion> {
const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar'); const MemberAvatar = sdk.getComponent('views.avatars.MemberAvatar');
// lazy-load user list into matcher // lazy-load user list into matcher

View file

@ -1,6 +1,7 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2019 Michael Telatynski <7t3chguy@gmail.com> Copyright 2019 Michael Telatynski <7t3chguy@gmail.com>
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,7 +21,7 @@ import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
module.exports = createReactClass({ export default createReactClass({
displayName: 'CompatibilityPage', displayName: 'CompatibilityPage',
propTypes: { propTypes: {
onAccept: PropTypes.func, onAccept: PropTypes.func,

View file

@ -21,7 +21,7 @@ import ReactDOM from 'react-dom';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import {Key} from "../../Keyboard"; import {Key} from "../../Keyboard";
import sdk from "../../index"; import * as sdk from "../../index";
import AccessibleButton from "../views/elements/AccessibleButton"; import AccessibleButton from "../views/elements/AccessibleButton";
// Shamelessly ripped off Modal.js. There's probably a better way // Shamelessly ripped off Modal.js. There's probably a better way

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import CustomRoomTagStore from '../../stores/CustomRoomTagStore'; import CustomRoomTagStore from '../../stores/CustomRoomTagStore';
import AutoHideScrollbar from './AutoHideScrollbar'; import AutoHideScrollbar from './AutoHideScrollbar';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import classNames from 'classnames'; import classNames from 'classnames';
import * as FormattingUtils from '../../utils/FormattingUtils'; import * as FormattingUtils from '../../utils/FormattingUtils';

View file

@ -23,9 +23,9 @@ import PropTypes from 'prop-types';
import request from 'browser-request'; import request from 'browser-request';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import sanitizeHtml from 'sanitize-html'; import sanitizeHtml from 'sanitize-html';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import MatrixClientPeg from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import classnames from 'classnames'; import classnames from 'classnames';
import MatrixClientContext from "../../contexts/MatrixClientContext"; import MatrixClientContext from "../../contexts/MatrixClientContext";

View file

@ -1,5 +1,6 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -19,8 +20,8 @@ import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Matrix from 'matrix-js-sdk'; import Matrix from 'matrix-js-sdk';
import sdk from '../../index'; import * as sdk from '../../index';
import MatrixClientPeg from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
/* /*
@ -126,4 +127,4 @@ const FilePanel = createReactClass({
}, },
}); });
module.exports = FilePanel; export default FilePanel;

View file

@ -19,8 +19,8 @@ limitations under the License.
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import MatrixClientPeg from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import { getHostingLink } from '../../utils/HostingLink'; import { getHostingLink } from '../../utils/HostingLink';
import { sanitizedHtmlNode } from '../../HtmlUtils'; import { sanitizedHtmlNode } from '../../HtmlUtils';

View file

@ -15,16 +15,14 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
import Matrix from 'matrix-js-sdk'; import {InteractiveAuth} from "matrix-js-sdk";
const InteractiveAuth = Matrix.InteractiveAuth;
import React, {createRef} from 'react'; import React, {createRef} from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import {getEntryComponentForLoginType} from '../views/auth/InteractiveAuthEntryComponents'; import {getEntryComponentForLoginType} from '../views/auth/InteractiveAuthEntryComponents';
import sdk from '../../index'; import * as sdk from '../../index';
export default createReactClass({ export default createReactClass({
displayName: 'InteractiveAuth', displayName: 'InteractiveAuth',

View file

@ -20,9 +20,9 @@ import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import { Key } from '../../Keyboard'; import { Key } from '../../Keyboard';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import VectorConferenceHandler from '../../VectorConferenceHandler'; import * as VectorConferenceHandler from '../../VectorConferenceHandler';
import SettingsStore from '../../settings/SettingsStore'; import SettingsStore from '../../settings/SettingsStore';
import {_t} from "../../languageHandler"; import {_t} from "../../languageHandler";
import Analytics from "../../Analytics"; import Analytics from "../../Analytics";
@ -301,4 +301,4 @@ const LeftPanel = createReactClass({
}, },
}); });
module.exports = LeftPanel; export default LeftPanel;

View file

@ -26,10 +26,10 @@ import { Key, isOnlyCtrlOrCmdKeyEvent } from '../../Keyboard';
import PageTypes from '../../PageTypes'; import PageTypes from '../../PageTypes';
import CallMediaHandler from '../../CallMediaHandler'; import CallMediaHandler from '../../CallMediaHandler';
import { fixupColorFonts } from '../../utils/FontManager'; import { fixupColorFonts } from '../../utils/FontManager';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import sessionStore from '../../stores/SessionStore'; import sessionStore from '../../stores/SessionStore';
import MatrixClientPeg from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import SettingsStore from "../../settings/SettingsStore"; import SettingsStore from "../../settings/SettingsStore";
import RoomListStore from "../../stores/RoomListStore"; import RoomListStore from "../../stores/RoomListStore";
import { getHomePageUrl } from '../../utils/pages'; import { getHomePageUrl } from '../../utils/pages';

View file

@ -20,7 +20,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Matrix from "matrix-js-sdk"; import * as Matrix from "matrix-js-sdk";
// focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss // focus-visible is a Polyfill for the :focus-visible CSS pseudo-attribute used by _AccessibleButton.scss
import 'focus-visible'; import 'focus-visible';
@ -29,7 +29,7 @@ import 'what-input';
import Analytics from "../../Analytics"; import Analytics from "../../Analytics";
import { DecryptionFailureTracker } from "../../DecryptionFailureTracker"; import { DecryptionFailureTracker } from "../../DecryptionFailureTracker";
import MatrixClientPeg from "../../MatrixClientPeg"; import {MatrixClientPeg} from "../../MatrixClientPeg";
import PlatformPeg from "../../PlatformPeg"; import PlatformPeg from "../../PlatformPeg";
import SdkConfig from "../../SdkConfig"; import SdkConfig from "../../SdkConfig";
import * as RoomListSorter from "../../RoomListSorter"; import * as RoomListSorter from "../../RoomListSorter";
@ -38,7 +38,7 @@ import Notifier from '../../Notifier';
import Modal from "../../Modal"; import Modal from "../../Modal";
import Tinter from "../../Tinter"; import Tinter from "../../Tinter";
import sdk from '../../index'; import * as sdk from '../../index';
import { showStartChatInviteDialog, showRoomInviteDialog } from '../../RoomInvite'; import { showStartChatInviteDialog, showRoomInviteDialog } from '../../RoomInvite';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
import linkifyMatrix from "../../linkify-matrix"; import linkifyMatrix from "../../linkify-matrix";
@ -65,7 +65,7 @@ import { defer } from "../../utils/promise";
import KeyVerificationStateObserver from '../../utils/KeyVerificationStateObserver'; import KeyVerificationStateObserver from '../../utils/KeyVerificationStateObserver';
/** constants for MatrixChat.state.view */ /** constants for MatrixChat.state.view */
const VIEWS = { export const VIEWS = {
// a special initial state which is only used at startup, while we are // a special initial state which is only used at startup, while we are
// trying to re-animate a matrix client or register as a guest. // trying to re-animate a matrix client or register as a guest.
LOADING: 0, LOADING: 0,
@ -1505,6 +1505,15 @@ export default createReactClass({
"blacklistUnverifiedDevices", "blacklistUnverifiedDevices",
); );
cli.setGlobalBlacklistUnverifiedDevices(blacklistEnabled); cli.setGlobalBlacklistUnverifiedDevices(blacklistEnabled);
// With cross-signing enabled, we send to unknown devices
// without prompting. Any bad-device status the user should
// be aware of will be signalled through the room shield
// changing colour. More advanced behaviour will come once
// we implement more settings.
cli.setGlobalErrorOnUnknownDevices(
!SettingsStore.isFeatureEnabled("feature_cross_signing"),
);
} }
}, },

View file

@ -22,11 +22,12 @@ import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import shouldHideEvent from '../../shouldHideEvent'; import shouldHideEvent from '../../shouldHideEvent';
import {wantsDateSeparator} from '../../DateUtils'; import {wantsDateSeparator} from '../../DateUtils';
import sdk from '../../index'; import * as sdk from '../../index';
import MatrixClientPeg from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import SettingsStore from '../../settings/SettingsStore'; import SettingsStore from '../../settings/SettingsStore';
import {_t} from "../../languageHandler"; import {_t} from "../../languageHandler";
import {haveTileForEvent} from "../views/rooms/EventTile";
const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes const CONTINUATION_MAX_INTERVAL = 5 * 60 * 1000; // 5 minutes
const continuedTypes = ['m.sticker', 'm.room.message']; const continuedTypes = ['m.sticker', 'm.room.message'];
@ -318,8 +319,7 @@ export default class MessagePanel extends React.Component {
return true; return true;
} }
const EventTile = sdk.getComponent('rooms.EventTile'); if (!haveTileForEvent(mxEv)) {
if (!EventTile.haveTileForEvent(mxEv)) {
return false; // no tile = no show return false; // no tile = no show
} }

View file

@ -17,7 +17,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import sdk from '../../index'; import * as sdk from '../../index';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import AccessibleButton from '../views/elements/AccessibleButton'; import AccessibleButton from '../views/elements/AccessibleButton';

View file

@ -1,6 +1,7 @@
/* /*
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2019 New Vector Ltd Copyright 2019 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -18,8 +19,8 @@ limitations under the License.
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
const sdk = require('../../index'); import {MatrixClientPeg} from "../../MatrixClientPeg";
const MatrixClientPeg = require("../../MatrixClientPeg"); import * as sdk from "../../index";
/* /*
* Component which shows the global notification list using a TimelinePanel * Component which shows the global notification list using a TimelinePanel
@ -60,4 +61,4 @@ const NotificationPanel = createReactClass({
}, },
}); });
module.exports = NotificationPanel; export default NotificationPanel;

View file

@ -21,7 +21,7 @@ limitations under the License.
import React from 'react'; import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import classNames from 'classnames'; import classNames from 'classnames';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import RateLimitedFunc from '../../ratelimitedfunc'; import RateLimitedFunc from '../../ratelimitedfunc';
import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker'; import { showGroupInviteDialog, showGroupAddRoomDialog } from '../../GroupAddressPicker';

View file

@ -18,19 +18,16 @@ limitations under the License.
import React from 'react'; import React from 'react';
import createReactClass from 'create-react-class'; import createReactClass from 'create-react-class';
import {MatrixClientPeg} from "../../MatrixClientPeg";
const MatrixClientPeg = require('../../MatrixClientPeg'); import * as sdk from "../../index";
const ContentRepo = require("matrix-js-sdk").ContentRepo; import dis from "../../dispatcher";
const Modal = require('../../Modal'); import Modal from "../../Modal";
const sdk = require('../../index');
const dis = require('../../dispatcher');
import { linkifyAndSanitizeHtml } from '../../HtmlUtils'; import { linkifyAndSanitizeHtml } from '../../HtmlUtils';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils'; import { instanceForInstanceId, protocolNameForInstanceId } from '../../utils/DirectoryUtils';
import Analytics from '../../Analytics'; import Analytics from '../../Analytics';
import MatrixClientContext from "../../contexts/MatrixClientContext"; import {getHttpUriForMxc} from "matrix-js-sdk/src/content-repo";
const MAX_NAME_LENGTH = 80; const MAX_NAME_LENGTH = 80;
const MAX_TOPIC_LENGTH = 160; const MAX_TOPIC_LENGTH = 160;
@ -39,7 +36,7 @@ function track(action) {
Analytics.trackEvent('RoomDirectory', action); Analytics.trackEvent('RoomDirectory', action);
} }
module.exports = createReactClass({ export default createReactClass({
displayName: 'RoomDirectory', displayName: 'RoomDirectory',
propTypes: { propTypes: {
@ -457,7 +454,7 @@ module.exports = createReactClass({
topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`; topic = `${topic.substring(0, MAX_TOPIC_LENGTH)}...`;
} }
topic = linkifyAndSanitizeHtml(topic); topic = linkifyAndSanitizeHtml(topic);
const avatarUrl = ContentRepo.getHttpUriForMxc( const avatarUrl = getHttpUriForMxc(
MatrixClientPeg.get().getHomeserverUrl(), MatrixClientPeg.get().getHomeserverUrl(),
room.avatar_url, 32, 32, "crop", room.avatar_url, 32, 32, "crop",
); );

View file

@ -1,6 +1,7 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2015, 2016 OpenMarket Ltd
Copyright 2017, 2018 New Vector Ltd Copyright 2017, 2018 New Vector Ltd
Copyright 2019 The Matrix.org Foundation C.I.C.
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
@ -20,8 +21,8 @@ import createReactClass from 'create-react-class';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import Matrix from 'matrix-js-sdk'; import Matrix from 'matrix-js-sdk';
import { _t, _td } from '../../languageHandler'; import { _t, _td } from '../../languageHandler';
import sdk from '../../index'; import * as sdk from '../../index';
import MatrixClientPeg from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import Resend from '../../Resend'; import Resend from '../../Resend';
import * as cryptodevices from '../../cryptodevices'; import * as cryptodevices from '../../cryptodevices';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
@ -38,7 +39,7 @@ function getUnsentMessages(room) {
}); });
} }
module.exports = createReactClass({ export default createReactClass({
displayName: 'RoomStatusBar', displayName: 'RoomStatusBar',
propTypes: { propTypes: {

View file

@ -19,9 +19,9 @@ limitations under the License.
import React, {createRef} from 'react'; import React, {createRef} from 'react';
import classNames from 'classnames'; import classNames from 'classnames';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import Unread from '../../Unread'; import * as Unread from '../../Unread';
import * as RoomNotifs from '../../RoomNotifs'; import * as RoomNotifs from '../../RoomNotifs';
import * as FormattingUtils from '../../utils/FormattingUtils'; import * as FormattingUtils from '../../utils/FormattingUtils';
import IndicatorScrollbar from './IndicatorScrollbar'; import IndicatorScrollbar from './IndicatorScrollbar';

View file

@ -30,15 +30,15 @@ import classNames from 'classnames';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';
import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks'; import {RoomPermalinkCreator} from '../../utils/permalinks/Permalinks';
import MatrixClientPeg from '../../MatrixClientPeg'; import {MatrixClientPeg} from '../../MatrixClientPeg';
import ContentMessages from '../../ContentMessages'; import ContentMessages from '../../ContentMessages';
import Modal from '../../Modal'; import Modal from '../../Modal';
import sdk from '../../index'; import * as sdk from '../../index';
import CallHandler from '../../CallHandler'; import CallHandler from '../../CallHandler';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import Tinter from '../../Tinter'; import Tinter from '../../Tinter';
import rate_limited_func from '../../ratelimitedfunc'; import rate_limited_func from '../../ratelimitedfunc';
import ObjectUtils from '../../ObjectUtils'; import * as ObjectUtils from '../../ObjectUtils';
import * as Rooms from '../../Rooms'; import * as Rooms from '../../Rooms';
import eventSearch from '../../Searching'; import eventSearch from '../../Searching';
@ -53,6 +53,7 @@ import SettingsStore, {SettingLevel} from "../../settings/SettingsStore";
import WidgetUtils from '../../utils/WidgetUtils'; import WidgetUtils from '../../utils/WidgetUtils';
import AccessibleButton from "../views/elements/AccessibleButton"; import AccessibleButton from "../views/elements/AccessibleButton";
import RightPanelStore from "../../stores/RightPanelStore"; import RightPanelStore from "../../stores/RightPanelStore";
import {haveTileForEvent} from "../views/rooms/EventTile";
import RoomContext from "../../contexts/RoomContext"; import RoomContext from "../../contexts/RoomContext";
const DEBUG = false; const DEBUG = false;
@ -65,7 +66,7 @@ if (DEBUG) {
debuglog = console.log.bind(console); debuglog = console.log.bind(console);
} }
module.exports = createReactClass({ export default createReactClass({
displayName: 'RoomView', displayName: 'RoomView',
propTypes: { propTypes: {
ConferenceHandler: PropTypes.any, ConferenceHandler: PropTypes.any,
@ -923,7 +924,7 @@ module.exports = createReactClass({
// rate limited because a power level change will emit an event for every // rate limited because a power level change will emit an event for every
// member in the room. // member in the room.
_updateRoomMembers: new rate_limited_func(function(dueToMember) { _updateRoomMembers: rate_limited_func(function(dueToMember) {
// a member state changed in this room // a member state changed in this room
// refresh the conf call notification state // refresh the conf call notification state
this._updateConfCallNotification(); this._updateConfCallNotification();
@ -1281,7 +1282,7 @@ module.exports = createReactClass({
const roomId = mxEv.getRoomId(); const roomId = mxEv.getRoomId();
const room = cli.getRoom(roomId); const room = cli.getRoom(roomId);
if (!EventTile.haveTileForEvent(mxEv)) { if (!haveTileForEvent(mxEv)) {
// XXX: can this ever happen? It will make the result count // XXX: can this ever happen? It will make the result count
// not match the displayed count. // not match the displayed count.
continue; continue;
@ -2029,5 +2030,3 @@ module.exports = createReactClass({
); );
}, },
}); });
module.exports.RoomContext = RoomContext;

View file

@ -84,7 +84,7 @@ if (DEBUG_SCROLL) {
* offset as normal. * offset as normal.
*/ */
module.exports = createReactClass({ export default createReactClass({
displayName: 'ScrollPanel', displayName: 'ScrollPanel',
propTypes: { propTypes: {

View file

@ -24,7 +24,7 @@ import { throttle } from 'lodash';
import AccessibleButton from '../../components/views/elements/AccessibleButton'; import AccessibleButton from '../../components/views/elements/AccessibleButton';
import classNames from 'classnames'; import classNames from 'classnames';
module.exports = createReactClass({ export default createReactClass({
displayName: 'SearchBox', displayName: 'SearchBox',
propTypes: { propTypes: {

View file

@ -19,7 +19,7 @@ limitations under the License.
import * as React from "react"; import * as React from "react";
import {_t} from '../../languageHandler'; import {_t} from '../../languageHandler';
import PropTypes from "prop-types"; import PropTypes from "prop-types";
import sdk from "../../index"; import * as sdk from "../../index";
/** /**
* Represents a tab for the TabbedView. * Represents a tab for the TabbedView.
@ -38,7 +38,7 @@ export class Tab {
} }
} }
export class TabbedView extends React.Component { export default class TabbedView extends React.Component {
static propTypes = { static propTypes = {
// The tabs to show // The tabs to show
tabs: PropTypes.arrayOf(PropTypes.instanceOf(Tab)).isRequired, tabs: PropTypes.arrayOf(PropTypes.instanceOf(Tab)).isRequired,

View file

@ -20,7 +20,7 @@ import TagOrderStore from '../../stores/TagOrderStore';
import GroupActions from '../../actions/GroupActions'; import GroupActions from '../../actions/GroupActions';
import sdk from '../../index'; import * as sdk from '../../index';
import dis from '../../dispatcher'; import dis from '../../dispatcher';
import { _t } from '../../languageHandler'; import { _t } from '../../languageHandler';

View file

@ -0,0 +1,59 @@
/*
Copyright 2019 New Vector Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
import React from 'react';
import createReactClass from 'create-react-class';
import * as sdk from '../../index';
import dis from '../../dispatcher';
import Modal from '../../Modal';
import { _t } from '../../languageHandler';
const TagPanelButtons = createReactClass({
displayName: 'TagPanelButtons',
componentDidMount: function() {
this._dispatcherRef = dis.register(this._onAction);
},
componentWillUnmount() {
if (this._dispatcherRef) {
dis.unregister(this._dispatcherRef);
this._dispatcherRef = null;
}
},
_onAction(payload) {
if (payload.action === "show_redesign_feedback_dialog") {
const RedesignFeedbackDialog =
sdk.getComponent("views.dialogs.RedesignFeedbackDialog");
Modal.createTrackedDialog('Report bugs & give feedback', '', RedesignFeedbackDialog);
}
},
render() {
const GroupsButton = sdk.getComponent('elements.GroupsButton');
const ActionButton = sdk.getComponent("elements.ActionButton");
return (<div className="mx_TagPanelButtons">
<GroupsButton />
<ActionButton
className="mx_TagPanelButtons_report" action="show_redesign_feedback_dialog"
label={_t("Report bugs & give feedback")} tooltip={true} />
</div>);
},
});
export default TagPanelButtons;

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