Merge branch 'develop' into patch-3

This commit is contained in:
Matthew Hodgson 2019-10-20 11:44:38 +01:00 committed by GitHub
commit 4e619b1693
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
881 changed files with 18298 additions and 40505 deletions

View file

@ -1,4 +1,21 @@
{ {
"presets": ["react", "es2015", "es2016"], "presets": [
"plugins": ["transform-class-properties", "transform-object-rest-spread", "transform-async-to-bluebird", "transform-runtime", "add-module-exports"] "react",
"es2015",
"es2016"
],
"plugins": [
[
"transform-builtin-extend",
{
"globals": ["Error"]
}
],
"transform-class-properties",
"transform-object-rest-spread",
"transform-async-to-bluebird",
"transform-runtime",
"add-module-exports",
"syntax-dynamic-import"
]
} }

57
.buildkite/pipeline.yaml Normal file
View file

@ -0,0 +1,57 @@
steps:
- label: ":eslint: Lint"
command:
- "yarn install"
- "yarn lint"
plugins:
- docker#v3.0.1:
image: "node:10"
- 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
- "echo '--- Fetching Dependencies'"
- "./scripts/fetch-develop.deps.sh --depth 1"
- "yarn install"
- "echo '+++ Running Tests'"
- "yarn test"
env:
CHROME_BIN: "/usr/bin/google-chrome-stable"
plugins:
- docker#v3.0.1:
image: "node:10"
propagate-environment: true
- label: ":hammer: Package"
command:
- "echo '--- Fetching Dependencies'"
- "./scripts/fetch-develop.deps.sh --depth 1"
- "yarn install"
- "echo '+++ Packaging'"
- "./scripts/ci_package.sh"
branches: "develop"
artifact_paths: "dist/riot-*.tar.gz"
plugins:
- docker#v3.0.1:
image: "node:10"
- label: "🌐 i18n"
command:
- "echo '--- Fetching Dependencies'"
- "./scripts/fetch-develop.deps.sh --depth 1"
- "yarn install"
- "echo '+++ Testing i18n output'"
- "yarn diff-i18n"
plugins:
- docker#v3.0.1:
image: "node:10"

11
.dockerignore Normal file
View file

@ -0,0 +1,11 @@
# Exclude a bunch of stuff which can make the build context a larger than it needs to be
.git/
test/
webapp/
lib/
node_modules/
electron_app/
karma-reports/
.idea/
.tmp/
config.json*

2
.github/FUNDING.yml vendored Normal file
View file

@ -0,0 +1,2 @@
patreon: matrixdotorg
liberapay: matrixdotorg

View file

@ -43,4 +43,4 @@ For the web app:
For the desktop app: For the desktop app:
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc? - **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
- **Version**: 0.x.y <!-- check the user settings panel if unsure --> - **Version**: 1.x.y <!-- check the user settings panel if unsure -->

56
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View file

@ -0,0 +1,56 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: bug
assignees: ''
---
<!-- Please report security issues by email to security@matrix.org -->
<!-- This is a bug report template. By following the instructions below and
filling out the sections with your information, you will help the us to get all
the necessary data to fix your issue.
You can also preview your report before submitting it. You may remove sections
that aren't relevant to your particular case.
Text between <!-- and --> marks will be invisible in the report.
-->
### Description
Describe here the problem that you are experiencing, or the feature you are requesting.
### Steps to reproduce
- For bugs, list the steps
- that reproduce the bug
- using hyphens as bullet points
Describe how what happens differs from what you expected.
<!-- Please send us logs for your bug report. They're very important for bugs
which are hard to reproduce. To do this, create this issue then go to your
account settings and click 'Submit Debug Logs' from the Help & About tab -->
Logs being sent: yes/no
<!-- Include screenshots if possible: you can drag and drop images below. -->
### Version information
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
- **Platform**: web (in-browser) or desktop?
For the web app:
- **Browser**: Chrome, Safari, Firefox? which version?
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
- **URL**: riot.im/develop / riot.im/app / somewhere else? If a private server, what version of riot-web?
For the desktop app:
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
- **Version**: 1.x.y <!-- check the user settings panel if unsure -->

View file

@ -0,0 +1,20 @@
---
name: Suggestion or Feature request
about: Suggest an idea for this project
title: ''
labels: suggestion
assignees: ''
---
**Is your suggestion related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

View file

@ -0,0 +1,58 @@
---
name: User Interface or Usability Bug report
about: Please include screenshots in UI/UX bug reports
title: ''
labels: bug, ui/ux
assignees: ''
---
<!-- A picture's worth a thousand words: PLEASE INCLUDE A SCREENSHOT :P -->
<!-- Please report security issues by email to security@matrix.org -->
<!-- This is a bug report template. By following the instructions below and
filling out the sections with your information, you will help the us to get all
the necessary data to fix your issue.
You can also preview your report before submitting it. You may remove sections
that aren't relevant to your particular case.
Text between <!-- and --> marks will be invisible in the report.
-->
### Description
Describe here the problem that you are experiencing, or the feature you are requesting.
### Steps to reproduce
- For bugs, list the steps
- that reproduce the bug
- using hyphens as bullet points
Describe how what happens differs from what you expected.
<!-- Please send us logs for your bug report. They're very important for bugs
which are hard to reproduce. To do this, create this issue then go to your
account settings and click 'Submit Debug Logs' from the Help & About tab -->
Logs being sent: yes/no
<!-- Include screenshots if possible: you can drag and drop images below. -->
### Version information
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
- **Platform**: web (in-browser) or desktop?
For the web app:
- **Browser**: Chrome, Safari, Firefox? which version?
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
- **URL**: riot.im/develop / riot.im/app / somewhere else? If a private server, what version of riot-web?
For the desktop app:
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
- **Version**: 1.x.y <!-- check the user settings panel if unsure -->

8
.gitignore vendored
View file

@ -1,19 +1,23 @@
/build /build
/cert.pem /cert.pem
/dist /dist
/karma-reports
/key.pem /key.pem
/lib /lib
/node_modules /node_modules
/electron_app/node_modules /electron_app/node_modules
/electron_app/dist /electron_app/dist
/electron_app/pub
/packages/ /packages/
/webapp /webapp
/.npmrc /.npmrc
/*.log
package-lock.json
.DS_Store .DS_Store
npm-debug.log
electron/dist electron/dist
electron/pub electron/pub
**/.idea **/.idea
/config.json /config.json
/config.json.*
/config.local*.json
/src/component-index.js /src/component-index.js
/.tmp

View file

@ -1,35 +0,0 @@
# we need trusty for the chrome addon
dist: trusty
# we don't need sudo, so can run in a container, which makes startup much
# quicker.
#
# unfortunately we do temporarily require sudo as a workaround for
# https://github.com/travis-ci/travis-ci/issues/8836
sudo: required
language: node_js
node_js:
# make sure we work with a range of node versions.
# As of the time of writing:
# - 4.x is still in LTS (until April 2018), but some of our deps (notably
# extract-zip) don't work with it
# - 5.x has been EOLed for nearly a year.
# - 6.x is the active 'LTS' version
# - 7.x is no longer supported
# - 8.x is the current 'current' version (until October 2017)
#
# see: https://github.com/nodejs/LTS/
#
# anything before 6.3 ships with npm 3.9 or earlier, which had problems
# with symlinks in node_modules (see
# https://github.com/npm/npm/releases/tag/v3.10.0 'FIXES AND REFACTORING').
- 6.3
- 6
- 7
addons:
chrome: stable
install:
# clone the deps with depth 1: we know we will only ever need that one
# commit.
- scripts/fetch-develop.deps.sh --depth 1 && npm install

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
Contributing code to Riot Contributing code to Riot
========================= =========================
Riot follows the same pattern as https://github.com/matrix-org/synapse/blob/master/CONTRIBUTING.rst. Riot follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.rst.

31
Dockerfile Normal file
View file

@ -0,0 +1,31 @@
# Builder
FROM node:10-alpine as builder
# Support custom branches of the react-sdk and js-sdk. This also helps us build
# images of riot-web develop.
ARG USE_CUSTOM_SDKS=false
ARG REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git"
ARG REACT_SDK_BRANCH="master"
ARG JS_SDK_REPO="https://github.com/matrix-org/matrix-js-sdk.git"
ARG JS_SDK_BRANCH="master"
RUN apk add --no-cache git dos2unix
WORKDIR /src
COPY . /src
RUN dos2unix /src/scripts/docker-link-repos.sh && sh /src/scripts/docker-link-repos.sh
RUN yarn --network-timeout=100000 install
RUN yarn build
# Copy the config now so that we don't create another layer in the app image
RUN cp /src/config.sample.json /src/webapp/config.json
# App
FROM nginx:alpine
COPY --from=builder /src/webapp /app
RUN rm -rf /usr/share/nginx/html \
&& ln -s /app /usr/share/nginx/html

351
README.md
View file

@ -1,40 +1,41 @@
Riot Riot
==== ====
Riot (formerly known as Vector) is a Matrix web client built using the Matrix Riot (formerly known as Vector) is a Matrix web client built using the [Matrix React SDK](https://github.com/matrix-org/matrix-react-sdk).
React SDK (https://github.com/matrix-org/matrix-react-sdk).
Riot is officially supported on the web in modern versions of Chrome, Firefox, and Safari. Other browsers may work, however
official support is not provided. For accessing Riot on an Android or iOS device, check out [riot-android](https://github.com/vector-im/riot-android)
and [riot-ios](https://github.com/vector-im/riot-ios) - riot-web does not support mobile devices.
Getting Started Getting Started
=============== ===============
The easiest way to test Riot is to just use the hosted copy at The easiest way to test Riot is to just use the hosted copy at https://riot.im/app.
https://riot.im/app. The develop branch is continuously deployed by Jenkins at The `develop` branch is continuously deployed by Jenkins at https://riot.im/develop
https://riot.im/develop for those who like living dangerously. for those who like living dangerously.
To host your own copy of Riot, the quickest bet is to use a pre-built To host your own copy of Riot, the quickest bet is to use a pre-built
released version of Riot: released version of Riot:
1. Download the latest version from https://github.com/vector-im/riot-web/releases 1. Download the latest version from https://github.com/vector-im/riot-web/releases
1. Untar the tarball on your web server 1. Untar the tarball on your web server
1. Move (or symlink) the riot-x.x.x directory to an appropriate name 1. Move (or symlink) the `riot-x.x.x` directory to an appropriate name
1. If desired, copy `config.sample.json` to `config.json` and edit it 1. If desired, copy `config.sample.json` to `config.json` and edit it
as desired. See below for details. as desired. See the [configuration docs](docs/config.md) for details.
1. Enter the URL into your browser and log into Riot! 1. Enter the URL into your browser and log into Riot!
Releases are signed by PGP, and can be checked against the public key Releases are signed using gpg and the OpenPGP standard, and can be checked against the public key located
at https://riot.im/packages/keys/riot.asc at https://packages.riot.im/riot-release-key.asc.
Note that Chrome does not allow microphone or webcam access for sites served Note that for the security of your chats will need to serve Riot
over http (except localhost), so for working VoIP you will need to serve Riot over HTTPS. Major browsers also do not allow you to use VoIP/video
over https. chats over HTTP, as WebRTC is only usable over HTTPS.
There are some exceptions like when using localhost, which is
considered a [secure context](https://developer.mozilla.org/docs/Web/Security/Secure_Contexts)
and thus allowed.
### Installation Steps for Debian Stretch To install Riot as a desktop application, see [Running as a desktop
1. Add the repository to your sources.list using either of the following two options: app](#running-as-a-desktop-app) below.
- Directly to sources.list: `echo "deb https://riot.im/packages/debian/ stretch main" | sudo tee -a /etc/apt/sources.list`
- As a separate entry in sources.list.d: `echo "deb https://riot.im/packages/debian/ stretch main" | sudo tee /etc/apt/sources.list.d/riot.list`
2. Add the gpg signing key for the riot repository: `curl -s https://riot.im/packages/debian/repo-key.asc | sudo apt-key add -`
3. Update your package lists: `sudo apt-get update`
4. Install Riot: `sudo apt-get install riot-web`
Important Security Note Important Security Note
======================= =======================
@ -49,115 +50,81 @@ We have put some coarse mitigations into place to try to protect against this
situation, but it's still not good practice to do it in the first place. See situation, but it's still not good practice to do it in the first place. See
https://github.com/vector-im/riot-web/issues/1977 for more details. https://github.com/vector-im/riot-web/issues/1977 for more details.
The same applies for end-to-end encrypted content, but since this is decrypted
on the client, Riot needs a way to supply the decrypted content from a separate
origin to the one Riot is hosted on. This currently done with a 'cross origin
renderer' which is a small piece of javascript hosted on a different domain.
To avoid all Riot installs needing one of these to be set up, riot.im hosts
one on usercontent.riot.im which is used by default.
https://github.com/vector-im/riot-web/issues/6173 tracks progress on replacing
this with something better.
Building From Source Building From Source
==================== ====================
Riot is a modular webapp built with modern ES6 and requires a npm build system Riot is a modular webapp built with modern ES6 and uses a Node.js build system.
to build. Ensure you have the latest LTS version of Node.js installed.
1. Install or update `node.js` so that your `node` is at least v6.3.0 (and `npm` Using `yarn` instead of `npm` is recommended. Please see the Yarn [install
is at least v3.10.x). guide](https://yarnpkg.com/docs/install/) if you do not have it already.
1. Install or update `node.js` so that your `node` is at least v10.x.
1. Install `yarn` if not present already.
1. Clone the repo: `git clone https://github.com/vector-im/riot-web.git`. 1. Clone the repo: `git clone https://github.com/vector-im/riot-web.git`.
1. Switch to the riot-web directory: `cd riot-web`. 1. Switch to the riot-web directory: `cd riot-web`.
1. If you're using the `develop` branch, install the develop versions of the 1. Install the prerequisites: `yarn install`.
dependencies, as the released ones will be too old: 1. If you're using the `develop` branch then it is recommended to set up a proper
``` development environment ("Setting up a dev environment" below) however one can
install the develop versions of the dependencies instead:
```bash
scripts/fetch-develop.deps.sh scripts/fetch-develop.deps.sh
``` ```
Whenever you git pull on riot-web you will also probably need to force an update Whenever you git pull on `riot-web` you will also probably need to force an update
to these dependencies - the simplest way is to re-run the script, but you can also to these dependencies - the simplest way is to re-run the script, but you can also
manually update and rebuild them: manually update and rebuild them:
``` ```bash
cd matrix-js-sdk cd matrix-js-sdk
git pull git pull
npm install # re-run to pull in any new dependencies yarn install # re-run to pull in any new dependencies
# Depending on your version of npm, npm run build may happen as part of
# the npm install above (https://docs.npmjs.com/misc/scripts#prepublish-and-prepare)
# If in doubt, run it anyway:
npm run build
cd ../matrix-react-sdk cd ../matrix-react-sdk
git pull git pull
npm install yarn install
npm run build
``` ```
However, we recommend setting up a proper development environment (see "Setting Or just use https://riot.im/develop - the continuous integration release of the
up a dev environment" below) if you want to run your own copy of the develop branch. (Note that we don't reference the develop versions in git directly
`develop` branch, as it makes it much easier to keep these dependencies due to https://github.com/npm/npm/issues/3055.)
up-to-date. Or just use https://riot.im/develop - the continuous integration
release of the develop branch.
(Note that we don't reference the develop versions in git directly due to
https://github.com/npm/npm/issues/3055.)
1. Install the prerequisites: `npm install`.
1. Configure the app by copying `config.sample.json` to `config.json` and 1. Configure the app by copying `config.sample.json` to `config.json` and
modifying it (see below for details). modifying it. See the [configuration docs](docs/config.md) for details.
1. `npm run dist` to build a tarball to deploy. Untaring this file will give 1. `yarn dist` to build a tarball to deploy. Untaring this file will give
a version-specific directory containing all the files that need to go on your a version-specific directory containing all the files that need to go on your
web server. web server.
Note that `npm run dist` is not supported on Windows, so Windows users can run `npm Note that `yarn dist` is not supported on Windows, so Windows users can run `yarn build`,
run build`, which will build all the necessary files into the `webapp` which will build all the necessary files into the `webapp` directory. The version of Riot
directory. The version of Riot will not appear in Settings without will not appear in Settings without using the dist script. You can then mount the
using the dist script. You can then mount the `webapp` directory on your `webapp` directory on your webserver to actually serve up the app, which is entirely static content.
webserver to actually serve up the app, which is entirely static content.
config.json
===========
You can configure the app by copying `config.sample.json` to
`config.json` and customising it:
1. `default_hs_url` is the default home server url.
1. `default_is_url` is the default identity server url (this is the server used
for verifying third party identifiers like email addresses). If this is blank,
registering with an email address, adding an email address to your account,
or inviting users via email address will not work. Matrix identity servers are
very simple web services which map third party identifiers (currently only email
addresses) to matrix IDs: see http://matrix.org/docs/spec/identity_service/unstable.html
for more details. Currently the only public matrix identity servers are https://matrix.org
and https://vector.im. In future identity servers will be decentralised.
1. `integrations_ui_url`: URL to the web interface for the integrations server. The integrations
server is not Riot and normally not your Home Server either. The integration server settings
may be left blank to disable integrations.
1. `integrations_rest_url`: URL to the REST interface for the integrations server.
1. `roomDirectory`: config for the public room directory. This section is optional.
1. `roomDirectory.servers`: List of other Home Servers' directories to include in the drop
down list. Optional.
1. `update_base_url` (electron app only): HTTPS URL to a web server to download
updates from. This should be the path to the directory containing `macos`
and `win32` (for update packages, not installer packages).
1. `cross_origin_renderer_url`: URL to a static HTML page hosting code to help display
encrypted file attachments. This MUST be hosted on a completely separate domain to
anything else since it is used to isolate the privileges of file attachments to this
domain. Default: `https://usercontent.riot.im/v1.html`. This needs to contain v1.html from
https://github.com/matrix-org/usercontent/blob/master/v1.html
1. `piwik`: an object containing the following properties:
1. `url`: The URL of the Piwik instance to use for collecting Analytics
1. `whitelistedHSUrls`: a list of HS URLs to not redact from the Analytics
1. `whitelistedISUrls`: a list of IS URLs to not redact from the Analytics
1. `siteId`: The Piwik Site ID to use when sending Analytics to the Piwik server configured above
Running as a Desktop app Running as a Desktop app
======================== ========================
Riot can also be run as a desktop app, wrapped in electron. You can download a Riot can also be run as a desktop app, wrapped in Electron. You can download a
pre-built version from https://riot.im/desktop.html or, if you prefer, pre-built version from https://riot.im/download/desktop/ or, if you prefer,
build it yourself. Requires Electron >=1.6.0 build it yourself.
To run as a desktop app: To build it yourself, follow the instructions below.
1. Follow the instructions in 'Building From Source' above, but run 1. Follow the instructions in 'Building From Source' above, but run
`npm run build` instead of `npm run dist` (since we don't need the tarball). `yarn build` instead of `yarn dist` (since we don't need the tarball).
2. Install electron and run it: 2. Install Electron and run it:
``` ```bash
npm install electron yarn electron
npm run electron
``` ```
To build packages, use electron-builder. This is configured to output: To build packages, use `electron-builder`. This is configured to output:
* dmg + zip for macOS * `dmg` + `zip` for macOS
* exe + nupkg for Windows * `exe` + `nupkg` for Windows
* deb for Linux * `deb` for Linux
But this can be customised by editing the `build` section of package.json But this can be customised by editing the `build` section of package.json
as per https://github.com/electron-userland/electron-builder/wiki/Options as per https://github.com/electron-userland/electron-builder/wiki/Options
@ -165,59 +132,99 @@ See https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Bu
for dependencies required for building packages for various platforms. for dependencies required for building packages for various platforms.
The only platform that can build packages for all three platforms is macOS: The only platform that can build packages for all three platforms is macOS:
``` ```bash
brew install wine --without-x11
brew install mono brew install mono
brew install gnu-tar yarn install
npm install yarn build:electron
npm run build:electron
``` ```
For other packages, use electron-builder manually. For example, to build a package For other packages, use `electron-builder` manually. For example, to build a
for 64 bit Linux: package for 64 bit Linux:
1. Follow the instructions in 'Building From Source' above 1. Follow the instructions in 'Building From Source' above
2. `node_modules/.bin/build -l --x64` 2. `node_modules/.bin/build -l --x64`
All electron packages go into `electron/dist/` All Electron packages go into `electron_app/dist/`
Many thanks to @aviraldg for the initial work on the electron integration. Many thanks to @aviraldg for the initial work on the Electron integration.
Other options for running as a desktop app: Other options for running as a desktop app:
* https://github.com/krisak/vector-electron-desktop
* @asdf:matrix.org points out that you can use nativefier and it just works(tm) * @asdf:matrix.org points out that you can use nativefier and it just works(tm)
``` ```bash
sudo npm install nativefier -g yarn global add nativefier
nativefier https://riot.im/app/ nativefier https://riot.im/app/
``` ```
The [configuration docs](docs/config.md#desktop-app-configuration) show how to
override the desktop app's default settings if desired.
Running from Docker
===================
The Docker image can be used to serve riot-web as a web server. The easiest way to use
it is to use the prebuilt image:
```bash
docker run -p 80:80 vectorim/riot-web
```
To supply your own custom `config.json`, map a volume to `/app/config.json`. For example,
if your custom config was located at `/etc/riot-web/config.json` then your Docker command
would be:
```bash
docker run -p 80:80 -v /etc/riot-web/config.json:/app/config.json vectorim/riot-web
```
To build the image yourself:
```bash
git clone https://github.com/vector-im/riot-web.git riot-web
cd riot-web
git checkout master
docker build -t vectorim/riot-web .
```
If you're building a custom branch, or want to use the develop branch, check out the appropriate
riot-web branch and then run:
```bash
docker build -t vectorim/riot-web:develop \
--build-arg USE_CUSTOM_SDKS=true \
--build-arg REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git" \
--build-arg REACT_SDK_BRANCH="develop" \
--build-arg JS_SDK_REPO="https://github.com/matrix-org/matrix-js-sdk.git" \
--build-arg JS_SDK_BRANCH="develop" \
.
```
config.json
===========
Riot supports a variety of settings to configure default servers, behaviour, themes, etc.
See the [configuration docs](docs/config.md) for more details.
Labs Features
=============
Some features of Riot may be enabled by flags in the `Labs` section of the settings.
Some of these features are described in [labs.md](https://github.com/vector-im/riot-web/blob/develop/docs/labs.md).
Development Development
=========== ===========
Before attempting to develop on Riot you **must** read the developer guide Before attempting to develop on Riot you **must** read the [developer guide
for `matrix-react-sdk` at https://github.com/matrix-org/matrix-react-sdk, which for `matrix-react-sdk`](https://github.com/matrix-org/matrix-react-sdk), which
also defines the design, architecture and style for Riot too. also defines the design, architecture and style for Riot too.
You should also familiarise yourself with the ["Here be Dragons" guide
](https://docs.google.com/document/d/12jYzvkidrp1h7liEuLIe6BMdU0NUjndUYI971O06ooM)
to the tame & not-so-tame dragons (gotchas) which exist in the codebase.
The idea of Riot is to be a relatively lightweight "skin" of customisations on The idea of Riot is to be a relatively lightweight "skin" of customisations on
top of the underlying `matrix-react-sdk`. `matrix-react-sdk` provides both the top of the underlying `matrix-react-sdk`. `matrix-react-sdk` provides both the
higher and lower level React components useful for building Matrix communication higher and lower level React components useful for building Matrix communication
apps using React. apps using React.
After creating a new component you must run `npm run reskindex` to regenerate After creating a new component you must run `yarn reskindex` to regenerate
the `component-index.js` for the app (used in future for skinning) the `component-index.js` for the app (used in future for skinning).
**However, as of July 2016 this layering abstraction is broken due to rapid
development on Riot forcing `matrix-react-sdk` to move fast at the expense of
maintaining a clear abstraction between the two.** Hacking on Riot inevitably
means hacking equally on `matrix-react-sdk`, and there are bits of
`matrix-react-sdk` behaviour incorrectly residing in the `riot-web` project
(e.g. matrix-react-sdk specific CSS), and a bunch of Riot specific behaviour
in the `matrix-react-sdk` (grep for `vector` / `riot`). This separation problem will be
solved asap once development on Riot (and thus matrix-react-sdk) has
stabilised. Until then, the two projects should basically be considered as a
single unit. In particular, `matrix-react-sdk` issues are currently filed
against `riot-web` in github.
Please note that Riot is intended to run correctly without access to the public Please note that Riot is intended to run correctly without access to the public
internet. So please don't depend on resources (JS libs, CSS, images, fonts) internet. So please don't depend on resources (JS libs, CSS, images, fonts)
@ -234,55 +241,67 @@ having to manually rebuild each time.
First clone and build `matrix-js-sdk`: First clone and build `matrix-js-sdk`:
1. `git clone git@github.com:matrix-org/matrix-js-sdk.git` ``` bash
1. `pushd matrix-js-sdk` git clone https://github.com/matrix-org/matrix-js-sdk.git
1. `git checkout develop` pushd matrix-js-sdk
1. `npm install` git checkout develop
1. `npm install source-map-loader` # because webpack is made of fail (https://github.com/webpack/webpack/issues/1472) yarn link
1. `popd` yarn install
popd
```
Then similarly with `matrix-react-sdk`: Then similarly with `matrix-react-sdk`:
1. `git clone git@github.com:matrix-org/matrix-react-sdk.git` ```bash
1. `pushd matrix-react-sdk` git clone https://github.com/matrix-org/matrix-react-sdk.git
1. `git checkout develop` pushd matrix-react-sdk
1. `npm install` git checkout develop
1. `rm -r node_modules/matrix-js-sdk; ln -s ../../matrix-js-sdk node_modules/` yarn link
1. `popd` yarn link matrix-js-sdk
yarn install
popd
```
Finally, build and start Riot itself: Finally, build and start Riot itself:
1. `git clone git@github.com:vector-im/riot-web.git` ```bash
1. `cd riot-web` git clone https://github.com/vector-im/riot-web.git
1. `git checkout develop` cd riot-web
1. `npm install` git checkout develop
1. `rm -r node_modules/matrix-js-sdk; ln -s ../../matrix-js-sdk node_modules/` yarn link matrix-js-sdk
1. `rm -r node_modules/matrix-react-sdk; ln -s ../../matrix-react-sdk node_modules/` yarn link matrix-react-sdk
1. `npm start` yarn install
1. Wait a few seconds for the initial build to finish; you should see something like: yarn start
``` ```
Hash: b0af76309dd56d7275c8
Version: webpack 1.12.14 Wait a few seconds for the initial build to finish; you should see something like:
Time: 14533ms ```
Asset Size Chunks Chunk Names Hash: b0af76309dd56d7275c8
bundle.js 4.2 MB 0 [emitted] main Version: webpack 1.12.14
bundle.css 91.5 kB 0 [emitted] main Time: 14533ms
bundle.js.map 5.29 MB 0 [emitted] main Asset Size Chunks Chunk Names
bundle.css.map 116 kB 0 [emitted] main bundle.js 4.2 MB 0 [emitted] main
+ 1013 hidden modules bundle.css 91.5 kB 0 [emitted] main
``` bundle.js.map 5.29 MB 0 [emitted] main
bundle.css.map 116 kB 0 [emitted] main
+ 1013 hidden modules
```
Remember, the command will not terminate since it runs the web server Remember, the command will not terminate since it runs the web server
and rebuilds source files when they change. This development server also and rebuilds source files when they change. This development server also
disables caching, so do NOT use it in production. disables caching, so do NOT use it in production.
1. Open http://127.0.0.1:8080/ in your browser to see your newly built Riot.
When you make changes to `matrix-react-sdk` or `matrix-js-sdk`, you will need Configure the app by copying `config.sample.json` to `config.json` and
to run `npm run build` in the relevant directory. You can do this automatically modifying it. See the [configuration docs](docs/config.md) for details.
by instead running `npm start` in the directory, to start a development builder
which will watch for changes to the files and rebuild automatically. Open http://127.0.0.1:8080/ in your browser to see your newly built Riot.
___
When you make changes to `matrix-react-sdk` or `matrix-js-sdk` they should be
automatically picked up by webpack and built.
If you add or remove any components from the Riot skin, you will need to rebuild If you add or remove any components from the Riot skin, you will need to rebuild
the skin's index by running, `npm run reskindex`. the skin's index by running, `yarn reskindex`.
If any of these steps error with, `file table overflow`, you are probably on a mac If any of these steps error with, `file table overflow`, you are probably on a mac
which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again. which has a very low limit on max open files. Run `ulimit -Sn 1024` and try again.
@ -298,12 +317,12 @@ are designed to run in a browser instance under the control of
* Make sure you have Chrome installed (a recent version, like 59) * Make sure you have Chrome installed (a recent version, like 59)
* Make sure you have `matrix-js-sdk` and `matrix-react-sdk` installed and * Make sure you have `matrix-js-sdk` and `matrix-react-sdk` installed and
built, as above built, as above
* `npm run test` * `yarn test`
The above will run the tests under Chrome in a `headless` mode. The above will run the tests under Chrome in a `headless` mode.
You can also tell karma to run the tests in a loop (every time the source You can also tell karma to run the tests in a loop (every time the source
changes), in an instance of Chrome on your desktop, with `npm run changes), in an instance of Chrome on your desktop, with `yarn
test-multi`. This also gives you the option of running the tests in 'debug' test-multi`. This also gives you the option of running the tests in 'debug'
mode, which is useful for stepping through the tests in the developer tools. mode, which is useful for stepping through the tests in the developer tools.

View file

@ -1,6 +1,13 @@
{ {
"default_hs_url": "https://matrix.org", "default_server_config": {
"default_is_url": "https://vector.im", "m.homeserver": {
"base_url": "https://matrix.org",
"server_name": "matrix.org"
},
"m.identity_server": {
"base_url": "https://vector.im"
}
},
"disable_custom_urls": false, "disable_custom_urls": false,
"disable_guests": false, "disable_guests": false,
"disable_login_language_selector": false, "disable_login_language_selector": false,
@ -8,13 +15,24 @@
"brand": "Riot", "brand": "Riot",
"integrations_ui_url": "https://scalar.vector.im/", "integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api", "integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [
"https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"integrations_jitsi_widget_url": "https://scalar.vector.im/api/widgets/jitsi.html",
"bug_report_endpoint_url": "https://riot.im/bugreports/submit", "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
"defaultCountryCode": "GB",
"showLabsSettings": false,
"features": { "features": {
"feature_groups": "labs", "feature_pinning": "labs",
"feature_pinning": "labs" "feature_custom_status": "labs",
"feature_custom_tags": "labs",
"feature_state_counters": "labs"
}, },
"default_federate": true, "default_federate": true,
"welcomePageUrl": "home.html",
"default_theme": "light", "default_theme": "light",
"roomDirectory": { "roomDirectory": {
"servers": [ "servers": [
@ -27,5 +45,11 @@
"whitelistedHSUrls": ["https://matrix.org"], "whitelistedHSUrls": ["https://matrix.org"],
"whitelistedISUrls": ["https://vector.im", "https://matrix.org"], "whitelistedISUrls": ["https://vector.im", "https://matrix.org"],
"siteId": 1 "siteId": 1
},
"enable_presence_by_hs_url": {
"https://matrix.org": false
},
"settingDefaults": {
"breadcrumbs": true
} }
} }

119
docs/config.md Normal file
View file

@ -0,0 +1,119 @@
Configuration
=============
You can configure the app by copying `config.sample.json` to
`config.json` and customising it:
For a good example, see https://riot.im/develop/config.json.
1. `default_server_config` sets the default homeserver and identity server URL for
Riot to use. The object is the same as returned by [https://<server_name>/.well-known/matrix/client](https://matrix.org/docs/spec/client_server/latest.html#get-well-known-matrix-client),
with added support for a `server_name` under the `m.homeserver` section to display
a custom homeserver name. Alternatively, the config can contain a `default_server_name`
instead which is where Riot will go to get that same object, although this option is
deprecated - see the `.well-known` link above for more information on using this option.
Note that the `default_server_name` is used to get a complete server configuration
whereas the `server_name` in the `default_server_config` is for display purposes only.
* *Note*: The URLs can also be individually specified as `default_hs_url` and
`default_is_url`, however these are deprecated. They are maintained for backwards
compatibility with older configurations. `default_is_url` is respected only
if `default_hs_url` is used.
* The identity server is used for verifying third party identifiers like emails
and phone numbers. It is not used to store your password or account information.
If not provided, the identity server defaults to vector.im. Currently the only
two public identity servers are https://matrix.org and https://vector.im, however
in future identity servers will be decentralised. In the future it will be possible
to disable the identity server functionality.
* Riot will fail to load if a mix of `default_server_config`, `default_server_name`, or
`default_hs_url` is specified. When multiple sources are specified, it is unclear
which should take priority and therefore the application cannot continue.
1. `features`: Lookup of optional features that may be `enable`d, `disable`d, or exposed to the user
in the `labs` section of settings. The available optional experimental features vary from
release to release. The available features are described in [labs.md](labs.md).
1. `showLabsSettings`: Shows the "labs" tab of user settings even when no `features` are enabled
or present. Useful for getting at settings which may be otherwise hidden.
1. `brand`: String to pass to your homeserver when configuring email notifications, to let the
homeserver know what email template to use when talking to you.
1. `branding`: Configures various branding and logo details, such as:
1. `welcomeBackgroundUrl`: An image to use as a wallpaper outside the app
during authentication flows
1. `authHeaderLogoUrl`: An logo image that is shown in the header during
authentication flows
1. `authFooterLinks`: a list of links to show in the authentication page footer:
`[{"text": "Link text", "url": "https://link.target"}, {"text": "Other link", ...}]`
1. `integrations_ui_url`: URL to the web interface for the integrations server. The integrations
server is not Riot and normally not your homeserver either. The integration server settings
may be left blank to disable integrations.
1. `integrations_rest_url`: URL to the REST interface for the integrations server.
1. `integrations_widgets_urls`: list of URLs to the REST interface for the widget integrations server.
1. `bug_report_endpoint_url`: endpoint to send bug reports to (must be running a
https://github.com/matrix-org/rageshake server). Bug reports are sent when a user clicks
"Send Logs" within the application. Bug reports can be disabled by leaving the
`bug_report_endpoint_url` out of your config file.
1. `roomDirectory`: config for the public room directory. This section is optional.
1. `roomDirectory.servers`: List of other homeservers' directories to include in the drop
down list. Optional.
1. `default_theme`: name of theme to use by default (e.g. 'light')
1. `update_base_url` (electron app only): HTTPS URL to a web server to download
updates from. This should be the path to the directory containing `macos`
and `win32` (for update packages, not installer packages).
1. `cross_origin_renderer_url`: URL to a static HTML page hosting code to help display
encrypted file attachments. This MUST be hosted on a completely separate domain to
anything else since it is used to isolate the privileges of file attachments to this
domain. Default: `https://usercontent.riot.im/v1.html`. This needs to contain v1.html from
https://github.com/matrix-org/usercontent/blob/master/v1.html
1. `piwik`: Analytics can be disabled by setting `piwik: false` or by leaving the piwik config
option out of your config file. If you want to enable analytics, set `piwik` to be an object
containing the following properties:
1. `url`: The URL of the Piwik instance to use for collecting analytics
1. `whitelistedHSUrls`: a list of HS URLs to not redact from the analytics
1. `whitelistedISUrls`: a list of IS URLs to not redact from the analytics
1. `siteId`: The Piwik Site ID to use when sending analytics to the Piwik server configured above
1. `welcomeUserId`: the user ID of a bot to invite whenever users register that can give them a tour
1. `embeddedPages`: Configures the pages displayed in portions of Riot that
embed static files, such as:
1. `welcomeUrl`: Initial content shown on the outside of the app when not
logged in. Defaults to `welcome.html` supplied with Riot.
1. `homeUrl`: Content shown on the inside of the app when a specific room is
not selected. By default, no home page is configured. If one is set, a
button to access it will be shown in the top left menu.
1. `defaultCountryCode`: The ISO 3166 alpha2 country code to use when showing
country selectors, like the phone number input on the registration page.
Defaults to `GB` if the given code is unknown or not provided.
1. `settingDefaults`: Defaults for settings that support the `config` level,
as an object mapping setting name to value (note that the "theme" setting
is special cased to the `default_theme` in the config file).
1. `disable_custom_urls`: disallow the user to change the
default homeserver when signing up or logging in.
1. `permalinkPrefix`: Used to change the URL that Riot generates permalinks with.
By default, this is "https://matrix.to" to generate matrix.to (spec) permalinks.
Set this to your Riot instance URL if you run an unfederated server (eg:
"https://riot.example.org").
Note that `index.html` also has an og:image meta tag that is set to an image
hosted on riot.im. This is the image used if links to your copy of Riot
appear in some websites like Facebook, and indeed Riot itself. This has to be
static in the HTML and an absolute URL (and HTTP rather than HTTPS), so it's
not possible for this to be an option in config.json. If you'd like to change
it, you can build Riot, but run
`RIOT_OG_IMAGE_URL="http://example.com/logo.png" yarn build`.
Alternatively, you can edit the `og:image` meta tag in `index.html` directly
each time you download a new version of Riot.
Desktop app configuration
=========================
To run multiple instances of the desktop app for different accounts, you can
launch the executable with the `--profile` argument followed by a unique
identifier, e.g `riot-web --profile Work` for it to run a separate profile and
not interfere with the default one.
Alternatively, a custom location for the profile data can be specified using the
`--profile-dir` flag followed by the desired path.
+ `%APPDATA%\$NAME\config.json` on Windows
+ `$XDG_CONFIG_HOME\$NAME\config.json` or `~/.config/$NAME/config.json` on Linux
+ `~Library/Application Support/$NAME/config.json` on macOS
In the paths above, `$NAME` is typically `Riot`, unless you use `--profile
$PROFILE` in which case it becomes `Riot-$PROFILE`.

51
docs/labs.md Normal file
View file

@ -0,0 +1,51 @@
# Labs features
Some notes on the features you can enable by going to `Settings->Labs`. Not exhaustive, chat in
[#riot-web:matrix.org](https://matrix.to/#/#riot-web:matrix.org) for more information.
**Be warned! Labs features are not finalised, they may be fragile, they may change, they may be
dropped. Ask in the room if you are unclear about any details here.**
## Message pinning (`feature_pinning`)
Allows you to pin messages in the room. To pin a message, use the 3 dots to the right of the message
and select "Pin".
## Custom status (`feature_custom_status`)
An experimental approach for supporting custom status messages across DMs. To set a status, click on
your avatar next to the message composer.
## Custom tags (`feature_custom_tags`)
An experimental approach for dealing with custom tags. Custom tags will appear in the bottom portion
of the community filter panel.
Setting custom tags is not supported by Riot.
## Render simple counters in room header (`feature_state_counters`)
Allows rendering of labelled counters above the message list.
Once enabled, send a custom state event to a room to set values:
1. In a room, type `/devtools` to bring up the devtools interface
2. Click "Send Custom Event"
3. Toggle from "Event" to "State Event"
4. Set the event type to: `re.jki.counter` and give it a unique key
5. Specify the content in the following format:
```
{
"link": "",
"severity": "normal",
"title": "my counter",
"value": 0
}
```
That's it. Now should see your new counter under the header.
## Multiple integration managers (`feature_many_integration_managers`)
Exposes a way to access all the integration managers known to Riot. This is an implementation of [MSC1957](https://github.com/matrix-org/matrix-doc/pull/1957).

View file

@ -0,0 +1,53 @@
## Memory leaks
Riot usually emits slow behaviour just before it is about to crash. Getting a
memory snapshot (below) just before that happens is ideal in figuring out what
is going wrong.
Common symptoms are clicking on a room and it feels like the tab froze and scrolling
becoming jumpy/staggered.
If you receive a white screen (electron) or the chrome crash page, it is likely
run out of memory and it is too late for a memory profile. Please do report when
this happens though so we can try and narrow down what might have gone wrong.
## Memory profiles/snapshots
When investigating memory leaks/problems it's usually important to compare snapshots
from different points in the Riot session lifecycle. Most importantly, a snapshot
to establish the baseline or "normal" memory usage is useful. Taking a snapshot
roughly 30-60 minutes after starting Riot is a good time to establish "normal"
memory usage for the app - anything after that is at risk of hiding the memory leak
and anything newer is still in the warmup stages of the app.
**Memory profiles can contain sensitive information.** If you are submitting a memory
profile to us for debugging purposes, please pick the appropriate Riot developer and
send them over an encrypted private message. *Do not share your memory profile in
public channels or with people you do not trust.*
### Taking a memory profile (Firefox)
1. Press CTRL+SHIFT+I (I as in eye).
2. Click the Memory tab.
3. Press the camera icon in the top left of the pane.
4. Wait a bit (coffee is a good option).
5. When the save button appears on the left side of the panel, click it to save the
profile locally.
6. Compress the file (gzip or regular zip) to make the file smaller.
7. Send the compressed file to whoever asked for it (if you trust them).
While the profile is in progress, the tab might be frozen or unresponsive.
### Taking a memory profile (Chrome/Desktop)
1. Press CTRL+SHIFT+I (I as in eye).
2. Click the Memory tab.
3. Select "Heap Snapshot" and the riot.im VM instance (not the indexeddb one).
4. Click "Take Snapshot".
5. Wait a bit (coffee is a good option).
6. When the save button appears on the left side of the panel, click it to save the
profile locally.
7. Compress the file (gzip or regular zip) to make the file smaller.
8. Send the compressed file to whoever asked for it (if you trust them).
While the profile is in progress, the tab might be frozen or unresponsive.

13
docs/shortcuts.md Normal file
View file

@ -0,0 +1,13 @@
# Keyboard Shortcuts
The modifier is <kbd>Ctrl</kbd> on Windows & Linux and <kbd></kbd> on Mac.
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>m</kbd> - toggle markdown
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>d</kbd> - toggle mic mute
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>e</kbd> - toggle video on/off
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>k</kbd> - jump to named room
- <kbd></kbd>/<kbd></kbd> - navigate old messages to edit when the composer is in focus
- <kbd></kbd>/<kbd></kbd> - next/prev room when focus in room list
- <kbd>Alt</kbd>+<kbd></kbd>/<kbd></kbd> - resend previous messages when the composer is in focus
- <kbd>PageUp</kbd>/<kbd>PageDown</kbd> - scroll timeline up/down
- <kbd>Ctrl</kbd>/<kbd></kbd>+<kbd>Home</kbd>/<kbd>End</kbd> - jump to timeline start/end

View file

@ -3,6 +3,8 @@
## Requirements ## Requirements
- A working [Development Setup](../../#setting-up-a-dev-environment) - A working [Development Setup](../../#setting-up-a-dev-environment)
- Including up-to-date versions of matrix-react-sdk and matrix-js-sdk
- Latest LTS version of Node.js installed
- Be able to understand English - Be able to understand English
- Be able to understand the language you want to translate riot-web into - Be able to understand the language you want to translate riot-web into
@ -30,9 +32,15 @@ function getColorName(hex) {
1. Check if the import ``import { _t } from 'matrix-react-sdk/lib/languageHandler';`` is present. If not add it to the other import statements. Also import `_td` if needed. 1. Check if the import ``import { _t } from 'matrix-react-sdk/lib/languageHandler';`` is present. If not add it to the other import statements. Also import `_td` if needed.
1. Add ``_t()`` to your string. (Don't forget curly braces when you assign an expression to JSX attributes in the render method). If the string is introduced at a point before the translation system has not yet been initialized, use `_td()` instead, and call `_t()` at the appropriate time. 1. Add ``_t()`` to your string. (Don't forget curly braces when you assign an expression to JSX attributes in the render method). If the string is introduced at a point before the translation system has not yet been initialized, use `_td()` instead, and call `_t()` at the appropriate time.
1. Run `npm run i18n` to update ``src/i18n/strings/en_EN.json`` (if it fails because it can't find the script, your dev environment predates the script, so reinstall/link react-sdk with `npm link ../matrix-react-sdk`). If it segfaults, you may be on Node 6, so try a newer version of node. 1. Run `yarn i18n` to update ``src/i18n/strings/en_EN.json``
1. If you added a string with a plural, you can add other English plural variants to ``src/i18n/strings/en_EN.json`` (remeber to edit the one in the same project as the source file containing your new translation). 1. If you added a string with a plural, you can add other English plural variants to ``src/i18n/strings/en_EN.json`` (remeber to edit the one in the same project as the source file containing your new translation).
## Editing existing strings
1. Edit every occurrence of the string inside `_t()` and `_td()` in the JSX files.
1. Run `yarn i18n` to update `src/i18n/strings/en_EN.json`. (Be sure to run this in the same project as the JSX files you just edited.)
1. Run `yarn prunei18n` to remove the old string from `src/i18n/strings/*.json`.
## Adding variables inside a string. ## Adding variables inside a string.
1. Extend your ``_t()`` call. Instead of ``_t(STRING)`` use ``_t(STRING, {})`` 1. Extend your ``_t()`` call. Instead of ``_t(STRING)`` use ``_t(STRING, {})``

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 673 B

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View file

@ -0,0 +1,14 @@
#!/bin/bash
# Link to the binary
ln -sf '/opt/${productFilename}/${executable}' '/usr/bin/${executable}'
# SUID chrome-sandbox for Electron 5+
# Remove this entire file (after-install.tpl) and remove the reference in
# package.json once this change has been upstreamed so we go back to the copy
# from upstream.
# https://github.com/electron-userland/electron-builder/pull/4163
chmod 4755 '/opt/${productFilename}/chrome-sandbox' || true
update-mime-database /usr/share/mime || true
update-desktop-database /usr/share/applications || true

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 13 KiB

View file

@ -2,11 +2,12 @@
"name": "riot-web", "name": "riot-web",
"productName": "Riot", "productName": "Riot",
"main": "src/electron-main.js", "main": "src/electron-main.js",
"version": "0.13.5", "version": "1.5.0",
"description": "A feature-rich client for Matrix.org", "description": "A feature-rich client for Matrix.org",
"author": "Vector Creations Ltd.", "author": "New Vector Ltd.",
"dependencies": { "dependencies": {
"auto-launch": "^5.0.1", "auto-launch": "^5.0.1",
"electron-store": "^2.0.0",
"electron-window-state": "^4.1.0", "electron-window-state": "^4.1.0",
"minimist": "^1.2.0", "minimist": "^1.2.0",
"png-to-ico": "^1.0.2" "png-to-ico": "^1.0.2"

View file

@ -1,4 +1,6 @@
This directory contains the config file for the official riot.im distribution This directory contains the config file for the official riot.im distribution
of Riot Desktop. You probably do not want to build with this config unless of Riot Desktop.
you're building the official riot.im distribution, or you'll find your builds
will replace themselves with the riot.im build. You probably do not want to build with this config unless you're building the
official riot.im distribution, or you'll find your builds will replace
themselves with the riot.im build.

View file

@ -1,14 +1,17 @@
{ {
"update_base_url": "https://riot.im/download/desktop/update/", "update_base_url": "https://packages.riot.im/desktop/update/",
"default_hs_url": "https://matrix.org", "default_server_name": "matrix.org",
"default_is_url": "https://vector.im",
"brand": "Riot", "brand": "Riot",
"integrations_ui_url": "https://scalar.vector.im/", "integrations_ui_url": "https://scalar.vector.im/",
"integrations_rest_url": "https://scalar.vector.im/api", "integrations_rest_url": "https://scalar.vector.im/api",
"integrations_widgets_urls": [ "integrations_widgets_urls": [
"https://scalar-staging.riot.im/scalar/api", "https://scalar.vector.im/_matrix/integrations/v1",
"https://scalar.vector.im/api" "https://scalar.vector.im/api",
"https://scalar-staging.vector.im/_matrix/integrations/v1",
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
], ],
"hosting_signup_link": "https://modular.im/?utm_source=riot-web&utm_medium=web",
"bug_report_endpoint_url": "https://riot.im/bugreports/submit", "bug_report_endpoint_url": "https://riot.im/bugreports/submit",
"welcomeUserId": "@riot-bot:matrix.org", "welcomeUserId": "@riot-bot:matrix.org",
"roomDirectory": { "roomDirectory": {
@ -18,6 +21,19 @@
}, },
"piwik": { "piwik": {
"url": "https://piwik.riot.im/", "url": "https://piwik.riot.im/",
"siteId": 1 "siteId": 1,
"policyUrl": "https://matrix.org/docs/guides/riot_im_cookie_policy"
},
"phasedRollOut": {
"feature_lazyloading": {
"offset": 1539684000000,
"period": 604800000
}
},
"features": {
"feature_lazyloading": "enable"
},
"enable_presence_by_hs_url": {
"https://matrix.org": false
} }
} }

View file

@ -0,0 +1 @@
export OSSLSIGNCODE_SIGNARGS='-pkcs11module /Library/Frameworks/eToken.framework/Versions/Current/libeToken.dylib -pkcs11engine /usr/local/lib/engines/engine_pkcs11.so -certs electron_app/riot.im/New_Vector_Ltd.pem -key 0a3271cbc1ec0fd8afb37f6bbe0cd65ba08d3b4d -t http://timestamp.comodoca.com -h sha256 -verbose'

View file

@ -1,7 +1,8 @@
/* /*
Copyright 2016 Aviral Dasgupta Copyright 2016 Aviral Dasgupta
Copyright 2016 OpenMarket Ltd Copyright 2016 OpenMarket Ltd
Copyright 2017 Michael Telatynski <7t3chguy@gmail.com> Copyright 2018, 2019 New Vector Ltd
Copyright 2017, 2019 Michael Telatynski <7t3chguy@gmail.com>
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,19 +23,45 @@ limitations under the License.
const checkSquirrelHooks = require('./squirrelhooks'); const checkSquirrelHooks = require('./squirrelhooks');
if (checkSquirrelHooks()) return; if (checkSquirrelHooks()) return;
const argv = require('minimist')(process.argv); const argv = require('minimist')(process.argv, {
const electron = require('electron'); alias: {help: "h"},
});
const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater, protocol} = require('electron');
const AutoLaunch = require('auto-launch'); const AutoLaunch = require('auto-launch');
const path = require('path');
const tray = require('./tray'); const tray = require('./tray');
const vectorMenu = require('./vectormenu'); const vectorMenu = require('./vectormenu');
const webContentsHandler = require('./webcontents-handler'); const webContentsHandler = require('./webcontents-handler');
const updater = require('./updater'); const updater = require('./updater');
const { migrateFromOldOrigin } = require('./originMigrator');
const windowStateKeeper = require('electron-window-state'); const windowStateKeeper = require('electron-window-state');
const Store = require('electron-store');
if (argv.profile) { if (argv["help"]) {
electron.app.setPath('userData', `${electron.app.getPath('userData')}-${argv.profile}`); console.log("Options:");
console.log(" --profile-dir {path}: Path to where to store the profile.");
console.log(" --profile {name}: Name of alternate profile to use, allows for running multiple accounts.");
console.log(" --devtools: Install and use react-devtools and react-perf.");
console.log(" --no-update: Disable automatic updating.");
console.log(" --hidden: Start the application hidden in the system tray.");
console.log(" --help: Displays this help message.");
console.log("And more such as --proxy, see:" +
"https://github.com/electron/electron/blob/master/docs/api/chrome-command-line-switches.md");
app.exit();
}
// boolean flag set whilst we are doing one-time origin migration
// We only serve the origin migration script while we're actually
// migrating to mitigate any risk of it being used maliciously.
let migratingOrigin = false;
if (argv['profile-dir']) {
app.setPath('userData', argv['profile-dir']);
} else if (argv['profile']) {
app.setPath('userData', `${app.getPath('userData')}-${argv['profile']}`);
} }
let vectorConfig = {}; let vectorConfig = {};
@ -47,8 +74,19 @@ try {
// Continue with the defaults (ie. an empty config) // Continue with the defaults (ie. an empty config)
} }
try {
// Load local config and use it to override values from the one baked with the build
const localConfig = require(path.join(app.getPath('userData'), 'config.json'));
vectorConfig = Object.assign(vectorConfig, localConfig);
} catch (e) {
// Could not load local config, this is expected in most cases.
}
const store = new Store({ name: "electron-config" });
let mainWindow = null; let mainWindow = null;
global.appQuitting = false; global.appQuitting = false;
global.minimizeToTray = store.get('minimizeToTray', true);
// handle uncaught errors otherwise it displays // handle uncaught errors otherwise it displays
@ -62,14 +100,14 @@ process.on('uncaughtException', function(error) {
}); });
let focusHandlerAttached = false; let focusHandlerAttached = false;
electron.ipcMain.on('setBadgeCount', function(ev, count) { ipcMain.on('setBadgeCount', function(ev, count) {
electron.app.setBadgeCount(count); app.setBadgeCount(count);
if (count === 0) { if (count === 0 && mainWindow) {
mainWindow.flashFrame(false); mainWindow.flashFrame(false);
} }
}); });
electron.ipcMain.on('loudNotification', function() { ipcMain.on('loudNotification', function() {
if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) { if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) {
mainWindow.flashFrame(true); mainWindow.flashFrame(true);
mainWindow.once('focus', () => { mainWindow.once('focus', () => {
@ -81,39 +119,108 @@ electron.ipcMain.on('loudNotification', function() {
}); });
let powerSaveBlockerId; let powerSaveBlockerId;
electron.ipcMain.on('app_onAction', function(ev, payload) { ipcMain.on('app_onAction', function(ev, payload) {
switch (payload.action) { switch (payload.action) {
case 'call_state': case 'call_state':
if (powerSaveBlockerId && electron.powerSaveBlocker.isStarted(powerSaveBlockerId)) { if (powerSaveBlockerId && powerSaveBlocker.isStarted(powerSaveBlockerId)) {
if (payload.state === 'ended') { if (payload.state === 'ended') {
electron.powerSaveBlocker.stop(powerSaveBlockerId); powerSaveBlocker.stop(powerSaveBlockerId);
} }
} else { } else {
if (payload.state === 'connected') { if (payload.state === 'connected') {
powerSaveBlockerId = electron.powerSaveBlocker.start('prevent-display-sleep'); powerSaveBlockerId = powerSaveBlocker.start('prevent-display-sleep');
} }
} }
break; break;
} }
}); });
autoUpdater.on('update-downloaded', (ev, releaseNotes, releaseName, releaseDate, updateURL) => {
electron.app.commandLine.appendSwitch('--enable-usermedia-screen-capturing'); if (!mainWindow) return;
// forward to renderer
const shouldQuit = electron.app.makeSingleInstance((commandLine, workingDirectory) => { mainWindow.webContents.send('update-downloaded', {
// Someone tried to run a second instance, we should focus our window. releaseNotes,
if (mainWindow) { releaseName,
if (!mainWindow.isVisible()) mainWindow.show(); releaseDate,
if (mainWindow.isMinimized()) mainWindow.restore(); updateURL,
mainWindow.focus(); });
}
}); });
if (shouldQuit) { ipcMain.on('ipcCall', async function(ev, payload) {
console.log('Other instance detected: exiting'); if (!mainWindow) return;
electron.app.exit();
}
const args = payload.args || [];
let ret;
switch (payload.name) {
case 'getUpdateFeedUrl':
ret = autoUpdater.getFeedURL();
break;
case 'getAutoLaunchEnabled':
ret = await launcher.isEnabled();
break;
case 'setAutoLaunchEnabled':
if (args[0]) {
launcher.enable();
} else {
launcher.disable();
}
break;
case 'getMinimizeToTrayEnabled':
ret = global.minimizeToTray;
break;
case 'setMinimizeToTrayEnabled':
store.set('minimizeToTray', global.minimizeToTray = args[0]);
break;
case 'getAutoHideMenuBarEnabled':
ret = global.mainWindow.isMenuBarAutoHide();
break;
case 'setAutoHideMenuBarEnabled':
store.set('autoHideMenuBar', args[0]);
global.mainWindow.setAutoHideMenuBar(args[0]);
global.mainWindow.setMenuBarVisibility(!args[0]);
break;
case 'getAppVersion':
ret = app.getVersion();
break;
case 'focusWindow':
if (mainWindow.isMinimized()) {
mainWindow.restore();
} else if (!mainWindow.isVisible()) {
mainWindow.show();
} else {
mainWindow.focus();
}
break;
case 'origin_migrate':
migratingOrigin = true;
await migrateFromOldOrigin();
migratingOrigin = false;
break;
case 'getConfig':
ret = vectorConfig;
break;
default:
mainWindow.webContents.send('ipcReply', {
id: payload.id,
error: "Unknown IPC Call: " + payload.name,
});
return;
}
mainWindow.webContents.send('ipcReply', {
id: payload.id,
reply: ret,
});
});
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
const gotLock = app.requestSingleInstanceLock();
if (!gotLock) {
console.log('Other instance detected: exiting');
app.exit();
}
const launcher = new AutoLaunch({ const launcher = new AutoLaunch({
name: vectorConfig.brand || 'Riot', name: vectorConfig.brand || 'Riot',
@ -123,61 +230,109 @@ const launcher = new AutoLaunch({
}, },
}); });
const settings = { // Register the scheme the app is served from as 'standard'
'auto-launch': { // which allows things like relative URLs and IndexedDB to
get: launcher.isEnabled, // work.
set: function(bool) { // Also mark it as secure (ie. accessing resources from this
if (bool) { // protocol and HTTPS won't trigger mixed content warnings).
return launcher.enable(); protocol.registerSchemesAsPrivileged([{
} else { scheme: 'vector',
return launcher.disable(); privileges: {
} standard: true,
}, secure: true,
supportFetchAPI: true,
}, },
}; }]);
electron.ipcMain.on('settings_get', async function(ev) { app.on('ready', () => {
const data = {}; if (argv['devtools']) {
try {
await Promise.all(Object.keys(settings).map(async function (setting) {
data[setting] = await settings[setting].get();
}));
ev.sender.send('settings', data);
} catch(e) { console.error(e); }
});
electron.ipcMain.on('settings_set', function(ev, key, value) {
console.log(key, value);
if (settings[key] && settings[key].set) {
settings[key].set(value);
}
});
electron.app.on('ready', () => {
if (argv.devtools) {
try { try {
const { default: installExtension, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer'); const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer');
installExtension(REACT_DEVELOPER_TOOLS) installExt(REACT_DEVELOPER_TOOLS)
.then((name) => console.log(`Added Extension: ${name}`)) .then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log('An error occurred: ', err)); .catch((err) => console.log('An error occurred: ', err));
installExtension(REACT_PERF) installExt(REACT_PERF)
.then((name) => console.log(`Added Extension: ${name}`)) .then((name) => console.log(`Added Extension: ${name}`))
.catch((err) => console.log('An error occurred: ', err)); .catch((err) => console.log('An error occurred: ', err));
} catch(e) {console.log(e);} } catch (e) {
console.log(e);
}
} }
protocol.registerFileProtocol('vector', (request, callback) => {
if (request.method !== 'GET') {
callback({error: -322}); // METHOD_NOT_SUPPORTED from chromium/src/net/base/net_error_list.h
return null;
}
if (vectorConfig.update_base_url) { const parsedUrl = new URL(request.url);
console.log(`Starting auto update with base URL: ${vectorConfig.update_base_url}`); if (parsedUrl.protocol !== 'vector:') {
updater.start(vectorConfig.update_base_url); callback({error: -302}); // UNKNOWN_URL_SCHEME
return;
}
if (parsedUrl.host !== 'vector') {
callback({error: -105}); // NAME_NOT_RESOLVED
return;
}
const target = parsedUrl.pathname.split('/');
// path starts with a '/'
if (target[0] !== '') {
callback({error: -6}); // FILE_NOT_FOUND
return;
}
if (target[target.length - 1] == '') {
target[target.length - 1] = 'index.html';
}
let baseDir;
// first part of the path determines where we serve from
if (migratingOrigin && target[1] === 'origin_migrator_dest') {
// the origin migrator destination page
// (only the destination script needs to come from the
// custom protocol: the source part is loaded from a
// file:// as that's the origin we're migrating from).
baseDir = __dirname + "/../../origin_migrator/dest";
} else if (target[1] === 'webapp') {
baseDir = __dirname + "/../../webapp";
} else {
callback({error: -6}); // FILE_NOT_FOUND
return;
}
// Normalise the base dir and the target path separately, then make sure
// the target path isn't trying to back out beyond its root
baseDir = path.normalize(baseDir);
const relTarget = path.normalize(path.join(...target.slice(2)));
if (relTarget.startsWith('..')) {
callback({error: -6}); // FILE_NOT_FOUND
return;
}
const absTarget = path.join(baseDir, relTarget);
callback({
path: absTarget,
});
}, (error) => {
if (error) console.error('Failed to register protocol');
});
if (argv['no-update']) {
console.log('Auto update disabled via command line flag "--no-update"');
} else if (vectorConfig['update_base_url']) {
console.log(`Starting auto update with base URL: ${vectorConfig['update_base_url']}`);
updater.start(vectorConfig['update_base_url']);
} else { } else {
console.log('No update_base_url is defined: auto update is disabled'); console.log('No update_base_url is defined: auto update is disabled');
} }
const iconPath = `${__dirname}/../img/riot.${process.platform === 'win32' ? 'ico' : 'png'}`; // It's important to call `path.join` so we don't end up with the packaged
// asar in the final path.
const iconFile = `riot.${process.platform === 'win32' ? 'ico' : 'png'}`;
const iconPath = path.join(__dirname, "..", "..", "img", iconFile);
// Load the previous window state with fallback to defaults // Load the previous window state with fallback to defaults
const mainWindowState = windowStateKeeper({ const mainWindowState = windowStateKeeper({
@ -185,18 +340,31 @@ electron.app.on('ready', () => {
defaultHeight: 768, defaultHeight: 768,
}); });
mainWindow = global.mainWindow = new electron.BrowserWindow({ const preloadScript = path.normalize(`${__dirname}/preload.js`);
mainWindow = global.mainWindow = new BrowserWindow({
icon: iconPath, icon: iconPath,
show: false, show: false,
autoHideMenuBar: true, autoHideMenuBar: store.get('autoHideMenuBar', true),
x: mainWindowState.x, x: mainWindowState.x,
y: mainWindowState.y, y: mainWindowState.y,
width: mainWindowState.width, width: mainWindowState.width,
height: mainWindowState.height, height: mainWindowState.height,
webPreferences: {
preload: preloadScript,
nodeIntegration: false,
sandbox: true,
enableRemoteModule: false,
// We don't use this: it's useful for the preload script to
// share a context with the main page so we can give select
// objects to the main page. The sandbox option isolates the
// main page from the background script.
contextIsolation: false,
webgl: false,
},
}); });
mainWindow.loadURL(`file://${__dirname}/../../webapp/index.html`); mainWindow.loadURL('vector://vector/webapp/');
electron.Menu.setApplicationMenu(vectorMenu); Menu.setApplicationMenu(vectorMenu);
// explicitly hide because setApplicationMenu on Linux otherwise shows... // explicitly hide because setApplicationMenu on Linux otherwise shows...
// https://github.com/electron/electron/issues/9621 // https://github.com/electron/electron/issues/9621
@ -208,17 +376,22 @@ electron.app.on('ready', () => {
brand: vectorConfig.brand || 'Riot', brand: vectorConfig.brand || 'Riot',
}); });
if (!argv.hidden) { mainWindow.once('ready-to-show', () => {
mainWindow.once('ready-to-show', () => { mainWindowState.manage(mainWindow);
if (!argv['hidden']) {
mainWindow.show(); mainWindow.show();
}); } else {
} // hide here explicitly because window manage above sometimes shows it
mainWindow.hide();
}
});
mainWindow.on('closed', () => { mainWindow.on('closed', () => {
mainWindow = global.mainWindow = null; mainWindow = global.mainWindow = null;
}); });
mainWindow.on('close', (e) => { mainWindow.on('close', (e) => {
if (!global.appQuitting && (tray.hasTray() || process.platform === 'darwin')) { if (global.minimizeToTray && !global.appQuitting && (tray.hasTray() || process.platform === 'darwin')) {
// On Mac, closing the window just hides it // On Mac, closing the window just hides it
// (this is generally how single-window Mac apps // (this is generally how single-window Mac apps
// behave, eg. Mail.app) // behave, eg. Mail.app)
@ -240,26 +413,37 @@ electron.app.on('ready', () => {
} }
webContentsHandler(mainWindow.webContents); webContentsHandler(mainWindow.webContents);
mainWindowState.manage(mainWindow);
}); });
electron.app.on('window-all-closed', () => { app.on('window-all-closed', () => {
electron.app.quit(); app.quit();
}); });
electron.app.on('activate', () => { app.on('activate', () => {
mainWindow.show(); mainWindow.show();
}); });
electron.app.on('before-quit', () => { app.on('before-quit', () => {
global.appQuitting = true; global.appQuitting = true;
if (mainWindow) { if (mainWindow) {
mainWindow.webContents.send('before-quit'); mainWindow.webContents.send('before-quit');
} }
}); });
app.on('second-instance', (ev, commandLine, workingDirectory) => {
// If other instance launched with --hidden then skip showing window
if (commandLine.includes('--hidden')) return;
// Someone tried to run a second instance, we should focus our window.
if (mainWindow) {
if (!mainWindow.isVisible()) mainWindow.show();
if (mainWindow.isMinimized()) mainWindow.restore();
mainWindow.focus();
}
});
// Set the App User Model ID to match what the squirrel // Set the App User Model ID to match what the squirrel
// installer uses for the shortcut icon. // installer uses for the shortcut icon.
// This makes notifications work on windows 8.1 (and is // This makes notifications work on windows 8.1 (and is
// a noop on other platforms). // a noop on other platforms).
electron.app.setAppUserModelId('com.squirrel.riot-web.Riot'); app.setAppUserModelId('com.squirrel.riot-web.Riot');

View file

@ -0,0 +1,72 @@
/*
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const { BrowserWindow, ipcMain } = require('electron');
const path = require('path');
async function migrateFromOldOrigin() {
console.log("Attempting to migrate data between origins");
// We can use the same preload script: we just need ipcRenderer exposed
const preloadScript = path.normalize(`${__dirname}/preload.js`);
await new Promise(resolve => {
const migrateWindow = new BrowserWindow({
show: false,
webPreferences: {
preload: preloadScript,
nodeIntegration: false,
sandbox: true,
enableRemoteModule: false,
webgl: false,
},
});
const onOriginMigrationComplete = (e, success, sentSummary, storedSummary) => {
// we use once but we'll only get one of these events,
// so remove the listener for the other one
ipcMain.removeListener('origin_migration_nodata', onOriginMigrationNoData);
if (success) {
console.log("Origin migration completed successfully!");
} else {
console.error("Origin migration failed!");
}
console.error("Data sent", sentSummary);
console.error("Data stored", storedSummary);
migrateWindow.close();
resolve();
};
const onOriginMigrationNoData = (e, success, sentSummary, storedSummary) => {
ipcMain.removeListener('origin_migration_complete', onOriginMigrationComplete);
console.log("No session to migrate from old origin");
migrateWindow.close();
resolve();
};
ipcMain.once('origin_migration_complete', onOriginMigrationComplete);
ipcMain.once('origin_migration_nodata', onOriginMigrationNoData);
// Normalise the path because in the distribution, __dirname will be inside the
// electron asar.
const sourcePagePath = path.normalize(__dirname + '/../../origin_migrator/source.html');
console.log("Loading path: " + sourcePagePath);
migrateWindow.loadURL('file://' + sourcePagePath);
});
}
module.exports = {
migrateFromOldOrigin,
};

View file

@ -1,5 +1,5 @@
/* /*
Copyright 2015, 2016 OpenMarket Ltd Copyright 2018, 2019 New Vector Ltd
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,11 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License. limitations under the License.
*/ */
.mx_MTextBody { const { ipcRenderer } = require('electron');
white-space: pre-wrap;
}
.mx_MTextBody pre{ // expose ipcRenderer to the renderer process
overflow-y: auto; window.ipcRenderer = ipcRenderer;
max-height: 30vh;
}

View file

@ -65,7 +65,7 @@ exports.create = function(config) {
global.mainWindow.webContents.on('page-favicon-updated', async function(ev, favicons) { global.mainWindow.webContents.on('page-favicon-updated', async function(ev, favicons) {
if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) { if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) {
if (lastFavicon !== null) { if (lastFavicon !== null) {
win.setIcon(defaultIcon); global.mainWindow.setIcon(defaultIcon);
trayIcon.setImage(defaultIcon); trayIcon.setImage(defaultIcon);
lastFavicon = null; lastFavicon = null;
} }

View file

@ -37,7 +37,7 @@ const template = [
submenu: [ submenu: [
{ type: 'separator' }, { type: 'separator' },
{ role: 'resetzoom' }, { role: 'resetzoom' },
{ role: 'zoomin' }, { role: 'zoomin', accelerator: 'CommandOrControl+=' },
{ role: 'zoomout' }, { role: 'zoomout' },
{ type: 'separator' }, { type: 'separator' },
{ role: 'togglefullscreen' }, { role: 'togglefullscreen' },
@ -57,8 +57,8 @@ const template = [
role: 'help', role: 'help',
submenu: [ submenu: [
{ {
label: 'riot.im', label: 'Riot Help',
click() { shell.openExternal('https://riot.im/'); }, click() { shell.openExternal('https://about.riot.im/help'); },
}, },
], ],
}, },

View file

@ -1,10 +1,14 @@
const {clipboard, nativeImage, Menu, MenuItem, shell} = require('electron'); const {clipboard, nativeImage, Menu, MenuItem, shell, dialog} = require('electron');
const url = require('url'); const url = require('url');
const fs = require('fs');
const request = require('request');
const MAILTO_PREFIX = "mailto:";
const PERMITTED_URL_SCHEMES = [ const PERMITTED_URL_SCHEMES = [
'http:', 'http:',
'https:', 'https:',
'mailto:', MAILTO_PREFIX,
]; ];
function safeOpenURL(target) { function safeOpenURL(target) {
@ -32,19 +36,27 @@ function onWindowOrNavigate(ev, target) {
} }
function onLinkContextMenu(ev, params) { function onLinkContextMenu(ev, params) {
const url = params.linkURL || params.srcURL; let url = params.linkURL || params.srcURL;
if (url.startsWith('vector://vector/webapp')) {
url = "https://riot.im/app/" + url.substring(23);
}
const popupMenu = new Menu(); const popupMenu = new Menu();
popupMenu.append(new MenuItem({ // No point trying to open blob: URLs in an external browser: it ain't gonna work.
label: url, if (!url.startsWith('blob:')) {
click() { popupMenu.append(new MenuItem({
safeOpenURL(url); label: url,
}, click() {
})); safeOpenURL(url);
},
}));
}
let addSaveAs = false;
if (params.mediaType && params.mediaType === 'image' && !url.startsWith('file://')) { if (params.mediaType && params.mediaType === 'image' && !url.startsWith('file://')) {
popupMenu.append(new MenuItem({ popupMenu.append(new MenuItem({
label: 'Copy Image', label: 'Copy image',
click() { click() {
if (url.startsWith('data:')) { if (url.startsWith('data:')) {
clipboard.writeImage(nativeImage.createFromDataURL(url)); clipboard.writeImage(nativeImage.createFromDataURL(url));
@ -53,15 +65,63 @@ function onLinkContextMenu(ev, params) {
} }
}, },
})); }));
// We want the link to be ordered below the copy stuff, but don't want to duplicate
// the `if` statement, so use a flag.
addSaveAs = true;
} }
popupMenu.append(new MenuItem({ // No point offering to copy a blob: URL either
label: 'Copy Link Address', if (!url.startsWith('blob:')) {
click() { // Special-case e-mail URLs to strip the `mailto:` like modern browsers do
clipboard.writeText(url); if (url.startsWith(MAILTO_PREFIX)) {
}, popupMenu.append(new MenuItem({
})); label: 'Copy email address',
popupMenu.popup(); click() {
clipboard.writeText(url.substr(MAILTO_PREFIX.length));
},
}));
} else {
popupMenu.append(new MenuItem({
label: 'Copy link address',
click() {
clipboard.writeText(url);
},
}));
}
}
if (addSaveAs) {
popupMenu.append(new MenuItem({
label: 'Save image as...',
click() {
const targetFileName = params.titleText || "image.png";
const filePath = dialog.showSaveDialog({
defaultPath: targetFileName,
});
if (!filePath) return; // user cancelled dialog
try {
if (url.startsWith("data:")) {
fs.writeFileSync(filePath, nativeImage.createFromDataURL(url));
} else {
request.get(url).pipe(fs.createWriteStream(filePath));
}
} catch (err) {
console.error(err);
dialog.showMessageBox({
type: "error",
title: "Failed to save image",
message: "The image failed to save",
});
}
},
}));
}
// popup() requires an options object even for no options
popupMenu.popup({});
ev.preventDefault(); ev.preventDefault();
} }
@ -88,7 +148,8 @@ function onSelectedContextMenu(ev, params) {
const items = _CutCopyPasteSelectContextMenus(params); const items = _CutCopyPasteSelectContextMenus(params);
const popupMenu = Menu.buildFromTemplate(items); const popupMenu = Menu.buildFromTemplate(items);
popupMenu.popup(); // popup() requires an options object even for no options
popupMenu.popup({});
ev.preventDefault(); ev.preventDefault();
} }
@ -101,13 +162,26 @@ function onEditableContextMenu(ev, params) {
const popupMenu = Menu.buildFromTemplate(items); const popupMenu = Menu.buildFromTemplate(items);
popupMenu.popup(); // popup() requires an options object even for no options
popupMenu.popup({});
ev.preventDefault(); ev.preventDefault();
} }
module.exports = (webContents) => { module.exports = (webContents) => {
webContents.on('new-window', onWindowOrNavigate); webContents.on('new-window', onWindowOrNavigate);
// XXX: The below now does absolutely nothing because of
// https://github.com/electron/electron/issues/8841
// Whilst this isn't a security issue since without
// node integration and with the sandbox, it should be
// no worse than opening the site in Chrome, it obviously
// means the user has to restart Riot to make it usable
// again (often unintuitive because it minimises to the
// system tray). We therefore need to be vigilant about
// putting target="_blank" on links in Riot (although
// we should generally be doing this anyway since links
// navigating you away from Riot in the browser is
// also annoying).
webContents.on('will-navigate', onWindowOrNavigate); webContents.on('will-navigate', onWindowOrNavigate);
webContents.on('context-menu', function(ev, params) { webContents.on('context-menu', function(ev, params) {

837
electron_app/yarn.lock Normal file
View file

@ -0,0 +1,837 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@types/node@^9.4.0":
version "9.6.45"
resolved "https://registry.yarnpkg.com/@types/node/-/node-9.6.45.tgz#a9e5cfd026a3abaaf17e3c0318a470da9f2f178e"
integrity sha512-9scD7xI1kpIoMs3gVFMOWsWDyRIQ1AOZwe56i1CQPE6N/P4POYkn9UtW5F66t8C2AIoPtVfOFycQ2r11t3pcyg==
ajv@^6.5.5:
version "6.10.0"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.10.0.tgz#90d0d54439da587cd7e843bfb7045f50bd22bdf1"
integrity sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==
dependencies:
fast-deep-equal "^2.0.1"
fast-json-stable-stringify "^2.0.0"
json-schema-traverse "^0.4.1"
uri-js "^4.2.2"
applescript@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/applescript/-/applescript-1.0.0.tgz#bb87af568cad034a4e48c4bdaf6067a3a2701317"
integrity sha1-u4evVoytA0pOSMS9r2Bno6JwExc=
asn1@~0.2.3:
version "0.2.4"
resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136"
integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==
dependencies:
safer-buffer "~2.1.0"
assert-plus@1.0.0, assert-plus@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525"
integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha1-x57Zf380y48robyXkLzDZkdLS3k=
auto-launch@^5.0.1:
version "5.0.5"
resolved "https://registry.yarnpkg.com/auto-launch/-/auto-launch-5.0.5.tgz#d14bd002b1ef642f85e991a6195ff5300c8ad3c0"
integrity sha512-ppdF4mihhYzMYLuCcx9H/c5TUOCev8uM7en53zWVQhyYAJrurd2bFZx3qQVeJKF2jrc7rsPRNN5cD+i23l6PdA==
dependencies:
applescript "^1.0.0"
mkdirp "^0.5.1"
path-is-absolute "^1.0.0"
untildify "^3.0.2"
winreg "1.2.4"
aws-sign2@~0.7.0:
version "0.7.0"
resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=
aws4@^1.8.0:
version "1.8.0"
resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.8.0.tgz#f0e003d9ca9e7f59c7a508945d7b2ef9a04a542f"
integrity sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e"
integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=
dependencies:
tweetnacl "^0.14.3"
bignumber.js@^2.1.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-2.4.0.tgz#838a992da9f9d737e0f4b2db0be62bb09dd0c5e8"
integrity sha1-g4qZLan51zfg9LLbC+YrsJ3Qxeg=
bmp-js@0.0.3:
version "0.0.3"
resolved "https://registry.yarnpkg.com/bmp-js/-/bmp-js-0.0.3.tgz#64113e9c7cf1202b376ed607bf30626ebe57b18a"
integrity sha1-ZBE+nHzxICs3btYHvzBibr5XsYo=
buffer-equal@0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/buffer-equal/-/buffer-equal-0.0.1.tgz#91bc74b11ea405bc916bc6aa908faafa5b4aac4b"
integrity sha1-kbx0sR6kBbyRa8aqkI+q+ltKrEs=
caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
combined-stream@^1.0.6, combined-stream@~1.0.6:
version "1.0.7"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.7.tgz#2d1d24317afb8abe95d6d2c0b07b57813539d828"
integrity sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==
dependencies:
delayed-stream "~1.0.0"
conf@^2.0.0:
version "2.2.0"
resolved "https://registry.yarnpkg.com/conf/-/conf-2.2.0.tgz#ee282efafc1450b61e205372041ad7d866802d9a"
integrity sha512-93Kz74FOMo6aWRVpAZsonOdl2I57jKtHrNmxhumehFQw4X8Sk37SohNY11PG7Q8Okta+UnrVaI006WLeyp8/XA==
dependencies:
dot-prop "^4.1.0"
env-paths "^1.0.0"
make-dir "^1.0.0"
pkg-up "^2.0.0"
write-file-atomic "^2.3.0"
core-util-is@1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
dashdash@^1.12.0:
version "1.14.1"
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"
integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=
dependencies:
assert-plus "^1.0.0"
deep-equal@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
integrity sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=
define-properties@^1.1.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.1.3.tgz#cf88da6cbee26fe6db7094f61d870cbd84cee9f1"
integrity sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==
dependencies:
object-keys "^1.0.12"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk=
dom-walk@^0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.1.tgz#672226dc74c8f799ad35307df936aba11acd6018"
integrity sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg=
dot-prop@^4.1.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-4.2.0.tgz#1f19e0c2e1aa0e32797c49799f2837ac6af69c57"
integrity sha512-tUMXrxlExSW6U2EXiiKGSBVdYgtV8qlHL+C10TsW4PURY/ic+eaysnSkwB4kA/mBlCyy/IKDJ+Lc3wbWeaXtuQ==
dependencies:
is-obj "^1.0.0"
ecc-jsbn@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9"
integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=
dependencies:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
electron-store@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/electron-store/-/electron-store-2.0.0.tgz#1035cca2a95409d1f54c7466606345852450d64a"
integrity sha512-1WCFYHsYvZBqDsoaS0Relnz0rd81ZkBAI0Fgx7Nq2UWU77rSNs1qxm4S6uH7TCZ0bV3LQpJFk7id/is/ZgoOPA==
dependencies:
conf "^2.0.0"
electron-window-state@^4.1.0:
version "4.1.1"
resolved "https://registry.yarnpkg.com/electron-window-state/-/electron-window-state-4.1.1.tgz#6b34fdc31b38514dfec8b7c8f7b5d4addb67632d"
integrity sha1-azT9wxs4UU3+yLfI97XUrdtnYy0=
dependencies:
deep-equal "^1.0.1"
jsonfile "^2.2.3"
mkdirp "^0.5.1"
env-paths@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-1.0.0.tgz#4168133b42bb05c38a35b1ae4397c8298ab369e0"
integrity sha1-QWgTO0K7BcOKNbGuQ5fIKYqzaeA=
es-abstract@^1.5.0:
version "1.13.0"
resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.13.0.tgz#ac86145fdd5099d8dd49558ccba2eaf9b88e24e9"
integrity sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==
dependencies:
es-to-primitive "^1.2.0"
function-bind "^1.1.1"
has "^1.0.3"
is-callable "^1.1.4"
is-regex "^1.0.4"
object-keys "^1.0.12"
es-to-primitive@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.0.tgz#edf72478033456e8dda8ef09e00ad9650707f377"
integrity sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==
dependencies:
is-callable "^1.1.4"
is-date-object "^1.0.1"
is-symbol "^1.0.2"
es6-promise@^3.0.2:
version "3.3.1"
resolved "https://registry.yarnpkg.com/es6-promise/-/es6-promise-3.3.1.tgz#a08cdde84ccdbf34d027a1451bc91d4bcd28a613"
integrity sha1-oIzd6EzNvzTQJ6FFG8kdS80ophM=
exif-parser@^0.1.9:
version "0.1.12"
resolved "https://registry.yarnpkg.com/exif-parser/-/exif-parser-0.1.12.tgz#58a9d2d72c02c1f6f02a0ef4a9166272b7760922"
integrity sha1-WKnS1ywCwfbwKg70qRZicrd2CSI=
extend@~3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa"
integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==
extsprintf@1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05"
integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=
extsprintf@^1.2.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f"
integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8=
fast-deep-equal@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz#7b05218ddf9667bf7f370bf7fdb2cb15fdd0aa49"
integrity sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=
fast-json-stable-stringify@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz#d5142c0caee6b1189f87d3a76111064f86c8bbf2"
integrity sha1-1RQsDK7msRifh9OnYREGT4bIu/I=
file-type@^3.1.0:
version "3.9.0"
resolved "https://registry.yarnpkg.com/file-type/-/file-type-3.9.0.tgz#257a078384d1db8087bc449d107d52a52672b9e9"
integrity sha1-JXoHg4TR24CHvESdEH1SpSZyuek=
find-up@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
integrity sha1-RdG35QbHF93UgndaK3eSCjwMV6c=
dependencies:
locate-path "^2.0.0"
for-each@^0.3.3:
version "0.3.3"
resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e"
integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==
dependencies:
is-callable "^1.1.3"
forever-agent@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91"
integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=
form-data@~2.3.2:
version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"
integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.6"
mime-types "^2.1.12"
function-bind@^1.0.2, function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
getpass@^0.1.1:
version "0.1.7"
resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa"
integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=
dependencies:
assert-plus "^1.0.0"
global@~4.3.0:
version "4.3.2"
resolved "https://registry.yarnpkg.com/global/-/global-4.3.2.tgz#e76989268a6c74c38908b1305b10fc0e394e9d0f"
integrity sha1-52mJJopsdMOJCLEwWxD8DjlOnQ8=
dependencies:
min-document "^2.19.0"
process "~0.5.1"
graceful-fs@^4.1.11, graceful-fs@^4.1.6:
version "4.1.15"
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.1.15.tgz#ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00"
integrity sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==
har-schema@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92"
integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=
har-validator@~5.1.0:
version "5.1.3"
resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080"
integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==
dependencies:
ajv "^6.5.5"
har-schema "^2.0.0"
has-symbols@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.0.tgz#ba1a8f1af2a0fc39650f5c850367704122063b44"
integrity sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=
has@^1.0.1, has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
http-signature@~1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"
integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=
dependencies:
assert-plus "^1.0.0"
jsprim "^1.2.2"
sshpk "^1.7.0"
imurmurhash@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea"
integrity sha1-khi5srkoojixPcT7a21XbyMUU+o=
ip-regex@^1.0.1:
version "1.0.3"
resolved "https://registry.yarnpkg.com/ip-regex/-/ip-regex-1.0.3.tgz#dc589076f659f419c222039a33316f1c7387effd"
integrity sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=
is-callable@^1.1.3, is-callable@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.1.4.tgz#1e1adf219e1eeb684d691f9d6a05ff0d30a24d75"
integrity sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==
is-date-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.1.tgz#9aa20eb6aeebbff77fbd33e74ca01b33581d3a16"
integrity sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=
is-function@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.1.tgz#12cfb98b65b57dd3d193a3121f5f6e2f437602b5"
integrity sha1-Es+5i2W1fdPRk6MSH19uL0N2ArU=
is-obj@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-1.0.1.tgz#3e4729ac1f5fde025cd7d83a896dab9f4f67db0f"
integrity sha1-PkcprB9f3gJc19g6iW2rn09n2w8=
is-regex@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.0.4.tgz#5517489b547091b0930e095654ced25ee97e9491"
integrity sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=
dependencies:
has "^1.0.1"
is-symbol@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.2.tgz#a055f6ae57192caee329e7a860118b497a950f38"
integrity sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==
dependencies:
has-symbols "^1.0.0"
is-typedarray@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a"
integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=
isstream@~0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=
jimp@^0.2.28:
version "0.2.28"
resolved "https://registry.yarnpkg.com/jimp/-/jimp-0.2.28.tgz#dd529a937190f42957a7937d1acc3a7762996ea2"
integrity sha1-3VKak3GQ9ClXp5N9Gsw6d2KZbqI=
dependencies:
bignumber.js "^2.1.0"
bmp-js "0.0.3"
es6-promise "^3.0.2"
exif-parser "^0.1.9"
file-type "^3.1.0"
jpeg-js "^0.2.0"
load-bmfont "^1.2.3"
mime "^1.3.4"
mkdirp "0.5.1"
pixelmatch "^4.0.0"
pngjs "^3.0.0"
read-chunk "^1.0.1"
request "^2.65.0"
stream-to-buffer "^0.1.0"
tinycolor2 "^1.1.2"
url-regex "^3.0.0"
jpeg-js@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/jpeg-js/-/jpeg-js-0.2.0.tgz#53e448ec9d263e683266467e9442d2c5a2ef5482"
integrity sha1-U+RI7J0mPmgyZkZ+lELSxaLvVII=
jsbn@~0.1.0:
version "0.1.1"
resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513"
integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM=
json-schema-traverse@^0.4.1:
version "0.4.1"
resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
json-schema@0.2.3:
version "0.2.3"
resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13"
integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=
json-stringify-safe@~5.0.1:
version "5.0.1"
resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb"
integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=
jsonfile@^2.2.3:
version "2.4.0"
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-2.4.0.tgz#3736a2b428b87bbda0cc83b53fa3d633a35c2ae8"
integrity sha1-NzaitCi4e72gzIO1P6PWM6NcKug=
optionalDependencies:
graceful-fs "^4.1.6"
jsprim@^1.2.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=
dependencies:
assert-plus "1.0.0"
extsprintf "1.3.0"
json-schema "0.2.3"
verror "1.10.0"
load-bmfont@^1.2.3:
version "1.4.0"
resolved "https://registry.yarnpkg.com/load-bmfont/-/load-bmfont-1.4.0.tgz#75f17070b14a8c785fe7f5bee2e6fd4f98093b6b"
integrity sha512-kT63aTAlNhZARowaNYcY29Fn/QYkc52M3l6V1ifRcPewg2lvUZDAj7R6dXjOL9D0sict76op3T5+odumDSF81g==
dependencies:
buffer-equal "0.0.1"
mime "^1.3.4"
parse-bmfont-ascii "^1.0.3"
parse-bmfont-binary "^1.0.5"
parse-bmfont-xml "^1.1.4"
phin "^2.9.1"
xhr "^2.0.1"
xtend "^4.0.0"
locate-path@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-2.0.0.tgz#2b568b265eec944c6d9c0de9c3dbbbca0354cd8e"
integrity sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=
dependencies:
p-locate "^2.0.0"
path-exists "^3.0.0"
make-dir@^1.0.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-1.3.0.tgz#79c1033b80515bd6d24ec9933e860ca75ee27f0c"
integrity sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==
dependencies:
pify "^3.0.0"
mime-db@~1.38.0:
version "1.38.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.38.0.tgz#1a2aab16da9eb167b49c6e4df2d9c68d63d8e2ad"
integrity sha512-bqVioMFFzc2awcdJZIzR3HjZFX20QhilVS7hytkKrv7xFAn8bM1gzc/FOX2awLISvWe0PV8ptFKcon+wZ5qYkg==
mime-types@^2.1.12, mime-types@~2.1.19:
version "2.1.22"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.22.tgz#fe6b355a190926ab7698c9a0556a11199b2199bd"
integrity sha512-aGl6TZGnhm/li6F7yx82bJiBZwgiEa4Hf6CNr8YO+r5UHr53tSTYZb102zyU50DOWWKeOv0uQLRL0/9EiKWCog==
dependencies:
mime-db "~1.38.0"
mime@^1.3.4:
version "1.6.0"
resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1"
integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==
min-document@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
integrity sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=
dependencies:
dom-walk "^0.1.0"
minimist@0.0.8:
version "0.0.8"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-0.0.8.tgz#857fcabfc3397d2625b8228262e86aa7a011b05d"
integrity sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=
minimist@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.0.tgz#a35008b20f41383eec1fb914f4cd5df79a264284"
integrity sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=
mkdirp@0.5.1, mkdirp@^0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.1.tgz#30057438eac6cf7f8c4767f38648d6697d75c903"
integrity sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=
dependencies:
minimist "0.0.8"
oauth-sign@~0.9.0:
version "0.9.0"
resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455"
integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==
object-keys@^1.0.12:
version "1.1.0"
resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.0.tgz#11bd22348dd2e096a045ab06f6c85bcc340fa032"
integrity sha512-6OO5X1+2tYkNyNEx6TsCxEqFfRWaqx6EtMiSbGrw8Ob8v9Ne+Hl8rBAgLBZn5wjEz3s/s6U1WXFUFOcxxAwUpg==
p-limit@^1.1.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8"
integrity sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==
dependencies:
p-try "^1.0.0"
p-locate@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43"
integrity sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=
dependencies:
p-limit "^1.1.0"
p-try@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/p-try/-/p-try-1.0.0.tgz#cbc79cdbaf8fd4228e13f621f2b1a237c1b207b3"
integrity sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=
parse-bmfont-ascii@^1.0.3:
version "1.0.6"
resolved "https://registry.yarnpkg.com/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz#11ac3c3ff58f7c2020ab22769079108d4dfa0285"
integrity sha1-Eaw8P/WPfCAgqyJ2kHkQjU36AoU=
parse-bmfont-binary@^1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz#d038b476d3e9dd9db1e11a0b0e53a22792b69006"
integrity sha1-0Di0dtPp3Z2x4RoLDlOiJ5K2kAY=
parse-bmfont-xml@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/parse-bmfont-xml/-/parse-bmfont-xml-1.1.4.tgz#015319797e3e12f9e739c4d513872cd2fa35f389"
integrity sha512-bjnliEOmGv3y1aMEfREMBJ9tfL3WR0i0CKPj61DnSLaoxWR3nLrsQrEbCId/8rF4NyRF0cCqisSVXyQYWM+mCQ==
dependencies:
xml-parse-from-string "^1.0.0"
xml2js "^0.4.5"
parse-headers@^2.0.0:
version "2.0.2"
resolved "https://registry.yarnpkg.com/parse-headers/-/parse-headers-2.0.2.tgz#9545e8a4c1ae5eaea7d24992bca890281ed26e34"
integrity sha512-/LypJhzFmyBIDYP9aDVgeyEb5sQfbfY5mnDq4hVhlQ69js87wXfmEI5V3xI6vvXasqebp0oCytYFLxsBVfCzSg==
dependencies:
for-each "^0.3.3"
string.prototype.trim "^1.1.2"
path-exists@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515"
integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=
path-is-absolute@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18=
performance-now@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b"
integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=
phin@^2.9.1:
version "2.9.3"
resolved "https://registry.yarnpkg.com/phin/-/phin-2.9.3.tgz#f9b6ac10a035636fb65dfc576aaaa17b8743125c"
integrity sha512-CzFr90qM24ju5f88quFC/6qohjC144rehe5n6DH900lgXmUe86+xCKc10ev56gRKC4/BkHUoG4uSiQgBiIXwDA==
pify@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-3.0.0.tgz#e5a4acd2c101fdf3d9a4d07f0dbc4db49dd28176"
integrity sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=
pixelmatch@^4.0.0:
version "4.0.2"
resolved "https://registry.yarnpkg.com/pixelmatch/-/pixelmatch-4.0.2.tgz#8f47dcec5011b477b67db03c243bc1f3085e8854"
integrity sha1-j0fc7FARtHe2fbA8JDvB8wheiFQ=
dependencies:
pngjs "^3.0.0"
pkg-up@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/pkg-up/-/pkg-up-2.0.0.tgz#c819ac728059a461cab1c3889a2be3c49a004d7f"
integrity sha1-yBmscoBZpGHKscOImivjxJoATX8=
dependencies:
find-up "^2.1.0"
png-to-ico@^1.0.2:
version "1.0.7"
resolved "https://registry.yarnpkg.com/png-to-ico/-/png-to-ico-1.0.7.tgz#9346b5f4d6fd7e94cb08fd49eeb585f501c3e5f2"
integrity sha512-heHiZjPFhVgLiuSG4C4wwKN9YPGLpPJvOfXRyI+cEJf0vPutjJ4XDaeI2f/hzTFs+2juihDw3pP8R5JtTuQTGg==
dependencies:
"@types/node" "^9.4.0"
jimp "^0.2.28"
minimist "^1.2.0"
pngjs@^3.0.0:
version "3.4.0"
resolved "https://registry.yarnpkg.com/pngjs/-/pngjs-3.4.0.tgz#99ca7d725965fb655814eaf65f38f12bbdbf555f"
integrity sha512-NCrCHhWmnQklfH4MtJMRjZ2a8c80qXeMlQMv2uVp9ISJMTt562SbGd6n2oq0PaPgKm7Z6pL9E2UlLIhC+SHL3w==
process@~0.5.1:
version "0.5.2"
resolved "https://registry.yarnpkg.com/process/-/process-0.5.2.tgz#1638d8a8e34c2f440a91db95ab9aeb677fc185cf"
integrity sha1-FjjYqONML0QKkduVq5rrZ3/Bhc8=
psl@^1.1.24:
version "1.1.31"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.1.31.tgz#e9aa86d0101b5b105cbe93ac6b784cd547276184"
integrity sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==
punycode@^1.4.1:
version "1.4.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e"
integrity sha1-wNWmOycYgArY4esPpSachN1BhF4=
punycode@^2.1.0:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@~6.5.2:
version "6.5.2"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36"
integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==
read-chunk@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/read-chunk/-/read-chunk-1.0.1.tgz#5f68cab307e663f19993527d9b589cace4661194"
integrity sha1-X2jKswfmY/GZk1J9m1icrORmEZQ=
request@^2.65.0:
version "2.88.0"
resolved "https://registry.yarnpkg.com/request/-/request-2.88.0.tgz#9c2fca4f7d35b592efe57c7f0a55e81052124fef"
integrity sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==
dependencies:
aws-sign2 "~0.7.0"
aws4 "^1.8.0"
caseless "~0.12.0"
combined-stream "~1.0.6"
extend "~3.0.2"
forever-agent "~0.6.1"
form-data "~2.3.2"
har-validator "~5.1.0"
http-signature "~1.2.0"
is-typedarray "~1.0.0"
isstream "~0.1.2"
json-stringify-safe "~5.0.1"
mime-types "~2.1.19"
oauth-sign "~0.9.0"
performance-now "^2.1.0"
qs "~6.5.2"
safe-buffer "^5.1.2"
tough-cookie "~2.4.3"
tunnel-agent "^0.6.0"
uuid "^3.3.2"
safe-buffer@^5.0.1, safe-buffer@^5.1.2:
version "5.1.2"
resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d"
integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==
safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0:
version "2.1.2"
resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a"
integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==
sax@>=0.6.0:
version "1.2.4"
resolved "https://registry.yarnpkg.com/sax/-/sax-1.2.4.tgz#2816234e2378bddc4e5354fab5caa895df7100d9"
integrity sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==
signal-exit@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.2.tgz#b5fdc08f1287ea1178628e415e25132b73646c6d"
integrity sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=
sshpk@^1.7.0:
version "1.16.1"
resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877"
integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==
dependencies:
asn1 "~0.2.3"
assert-plus "^1.0.0"
bcrypt-pbkdf "^1.0.0"
dashdash "^1.12.0"
ecc-jsbn "~0.1.1"
getpass "^0.1.1"
jsbn "~0.1.0"
safer-buffer "^2.0.2"
tweetnacl "~0.14.0"
stream-to-buffer@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/stream-to-buffer/-/stream-to-buffer-0.1.0.tgz#26799d903ab2025c9bd550ac47171b00f8dd80a9"
integrity sha1-JnmdkDqyAlyb1VCsRxcbAPjdgKk=
dependencies:
stream-to "~0.2.0"
stream-to@~0.2.0:
version "0.2.2"
resolved "https://registry.yarnpkg.com/stream-to/-/stream-to-0.2.2.tgz#84306098d85fdb990b9fa300b1b3ccf55e8ef01d"
integrity sha1-hDBgmNhf25kLn6MAsbPM9V6O8B0=
string.prototype.trim@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.1.2.tgz#d04de2c89e137f4d7d206f086b5ed2fae6be8cea"
integrity sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=
dependencies:
define-properties "^1.1.2"
es-abstract "^1.5.0"
function-bind "^1.0.2"
tinycolor2@^1.1.2:
version "1.4.1"
resolved "https://registry.yarnpkg.com/tinycolor2/-/tinycolor2-1.4.1.tgz#f4fad333447bc0b07d4dc8e9209d8f39a8ac77e8"
integrity sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=
tough-cookie@~2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.4.3.tgz#53f36da3f47783b0925afa06ff9f3b165280f781"
integrity sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==
dependencies:
psl "^1.1.24"
punycode "^1.4.1"
tunnel-agent@^0.6.0:
version "0.6.0"
resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd"
integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=
dependencies:
safe-buffer "^5.0.1"
tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
untildify@^3.0.2:
version "3.0.3"
resolved "https://registry.yarnpkg.com/untildify/-/untildify-3.0.3.tgz#1e7b42b140bcfd922b22e70ca1265bfe3634c7c9"
integrity sha512-iSk/J8efr8uPT/Z4eSUywnqyrQU7DSdMfdqK4iWEaUVVmcP5JcnpRqmVMwcwcnmI1ATFNgC5V90u09tBynNFKA==
uri-js@^4.2.2:
version "4.2.2"
resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0"
integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==
dependencies:
punycode "^2.1.0"
url-regex@^3.0.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/url-regex/-/url-regex-3.2.0.tgz#dbad1e0c9e29e105dd0b1f09f6862f7fdb482724"
integrity sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=
dependencies:
ip-regex "^1.0.1"
uuid@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.3.2.tgz#1b4af4955eb3077c501c23872fc6513811587131"
integrity sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==
verror@1.10.0:
version "1.10.0"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400"
integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=
dependencies:
assert-plus "^1.0.0"
core-util-is "1.0.2"
extsprintf "^1.2.0"
winreg@1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/winreg/-/winreg-1.2.4.tgz#ba065629b7a925130e15779108cf540990e98d1b"
integrity sha1-ugZWKbepJRMOFXeRCM9UCZDpjRs=
write-file-atomic@^2.3.0:
version "2.4.2"
resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-2.4.2.tgz#a7181706dfba17855d221140a9c06e15fcdd87b9"
integrity sha512-s0b6vB3xIVRLWywa6X9TOMA7k9zio0TMOsl9ZnDkliA/cfJlpHXAscj0gbHVJiTdIuAYpIyqS5GW91fqm6gG5g==
dependencies:
graceful-fs "^4.1.11"
imurmurhash "^0.1.4"
signal-exit "^3.0.2"
xhr@^2.0.1:
version "2.5.0"
resolved "https://registry.yarnpkg.com/xhr/-/xhr-2.5.0.tgz#bed8d1676d5ca36108667692b74b316c496e49dd"
integrity sha512-4nlO/14t3BNUZRXIXfXe+3N6w3s1KoxcJUUURctd64BLRe67E4gRwp4PjywtDY72fXpZ1y6Ch0VZQRY/gMPzzQ==
dependencies:
global "~4.3.0"
is-function "^1.0.1"
parse-headers "^2.0.0"
xtend "^4.0.0"
xml-parse-from-string@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz#a9029e929d3dbcded169f3c6e28238d95a5d5a28"
integrity sha1-qQKekp09vN7RafPG4oI42VpdWig=
xml2js@^0.4.5:
version "0.4.19"
resolved "https://registry.yarnpkg.com/xml2js/-/xml2js-0.4.19.tgz#686c20f213209e94abf0d1bcf1efaa291c7827a7"
integrity sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==
dependencies:
sax ">=0.6.0"
xmlbuilder "~9.0.1"
xmlbuilder@~9.0.1:
version "9.0.7"
resolved "https://registry.yarnpkg.com/xmlbuilder/-/xmlbuilder-9.0.7.tgz#132ee63d2ec5565c557e20f4c22df9aca686b10d"
integrity sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=
xtend@^4.0.0:
version "4.0.1"
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.1.tgz#a5c6d532be656e23db820efb943a1f04998d63af"
integrity sha1-pcbVMr5lbiPbgg77lDofBJmNY68=

View file

@ -9,7 +9,7 @@ var webpack_config = require('./webpack.config');
* to build everything; however it's the easiest way to load our dependencies * to build everything; however it's the easiest way to load our dependencies
* from node_modules. * from node_modules.
* *
* If you run karma in multi-run mode (with `npm run test-multi`), it will watch * 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 * the tests for changes, and webpack will rebuild using a cache. This is much quicker
* than a clean rebuild. * than a clean rebuild.
*/ */
@ -32,9 +32,12 @@ const olm_entry = webpack_config.entry['olm'];
// 'preprocessors' config below) // 'preprocessors' config below)
delete webpack_config['entry']; delete webpack_config['entry'];
// make sure we're flagged as development to avoid wasting time optimising
webpack_config.mode = 'development';
// add ./test as a search path for js // add ./test as a search path for js
webpack_config.module.loaders.unshift({ webpack_config.module.rules.unshift({
test: /\.js$/, loader: "babel", test: /\.js$/, use: "babel-loader",
include: [path.resolve('./src'), path.resolve('./test')], include: [path.resolve('./src'), path.resolve('./test')],
}); });
@ -46,8 +49,9 @@ webpack_config.module.noParse.push(/sinon\/pkg\/sinon\.js$/);
// ? // ?
webpack_config.resolve.alias['sinon'] = 'sinon/pkg/sinon.js'; webpack_config.resolve.alias['sinon'] = 'sinon/pkg/sinon.js';
webpack_config.resolve.root = [ webpack_config.resolve.modules = [
path.resolve('./test'), path.resolve('./test'),
"node_modules"
]; ];
webpack_config.devtool = 'inline-source-map'; webpack_config.devtool = 'inline-source-map';
@ -70,14 +74,21 @@ module.exports = function (config) {
// This isn't required by any of the tests, but it stops karma // This isn't required by any of the tests, but it stops karma
// logging warnings when it serves a 404 for them. // logging warnings when it serves a 404 for them.
{ {
pattern: 'src/skins/vector/img/*', pattern: 'node_modules/matrix-react-sdk/res/img/*',
watched: false, included: false, served: true, nocache: false,
},
{
pattern: 'res/**',
watched: false, included: false, served: true, nocache: false, watched: false, included: false, served: true, nocache: false,
}, },
], ],
proxies: { proxies: {
// redirect img links to the karma server. See above. // redirect img links to the karma server. See above.
"/img/": "/base/src/skins/vector/img/", "/img/": "/base/node_modules/matrix-react-sdk/res/img/",
"/themes/": "/base/res/themes/",
"/welcome.html": "/base/res/welcome.html",
"/welcome/": "/base/res/welcome/",
}, },
// preprocess matching files before serving them to the browser // preprocess matching files before serving them to the browser
@ -89,7 +100,7 @@ module.exports = function (config) {
// test results reporter to use // test results reporter to use
// available reporters: https://npmjs.org/browse/keyword/karma-reporter // available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['logcapture', 'spec', 'junit', 'summary'], reporters: ['logcapture', 'spec', 'summary'],
specReporter: { specReporter: {
suppressErrorSummary: false, // do print error summary suppressErrorSummary: false, // do print error summary
@ -127,10 +138,10 @@ module.exports = function (config) {
], ],
customLaunchers: { customLaunchers: {
'ChromeHeadless': { 'VectorChromeHeadless': {
base: 'Chrome', base: 'Chrome',
flags: [ flags: [
// '--no-sandbox', '--no-sandbox',
// See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md // See https://chromium.googlesource.com/chromium/src/+/lkgr/headless/README.md
'--headless', '--headless',
'--disable-gpu', '--disable-gpu',
@ -148,10 +159,6 @@ module.exports = function (config) {
// how many browser should be started simultaneous // how many browser should be started simultaneous
concurrency: Infinity, concurrency: Infinity,
junitReporter: {
outputDir: 'karma-reports',
},
webpack: webpack_config, webpack: webpack_config,
webpackMiddleware: { webpackMiddleware: {

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,6 @@
<html>
<body>
<script src="browser-matrix.min.js"></script>
<script src="dest.js"></script>
</body>
</html>

View file

@ -0,0 +1,125 @@
/*
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const SOURCE_ORIGIN = 'file://';
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
let accountStored = 0;
let sessionsStored = 0;
let inboundGroupSessionsStored = 0;
let deviceDataStored = 0;
let roomsStored = 0;
let localStorageKeysStored = 0;
const promises = [];
async function onMessage(e) {
if (e.origin !== SOURCE_ORIGIN) return;
const data = e.data.data; // bleh, naming clash
switch (e.data.cmd) {
case 'init':
// start with clean stores before we migrate data in
window.localStorage.clear();
await cryptoStore.deleteAllData();
e.source.postMessage({
cmd: 'initOK',
}, SOURCE_ORIGIN);
break;
case 'storeAccount':
promises.push(cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_ACCOUNT],
(txn) => {
cryptoStore.storeAccount(txn, data);
},
).then(() => {
++accountStored;
}));
break;
case 'storeSessions':
promises.push(cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_SESSIONS],
(txn) => {
for (const sess of data) {
cryptoStore.storeEndToEndSession(sess.deviceKey, sess.sessionId, sess, txn);
}
},
).then(() => {
sessionsStored += data.length;
}));
break;
case 'storeInboundGroupSessions':
promises.push(cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
(txn) => {
for (const sess of data) {
cryptoStore.addEndToEndInboundGroupSession(
sess.senderKey, sess.sessionId, sess.sessionData, txn,
);
}
},
).then(() => {
inboundGroupSessionsStored += data.length;
}));
break;
case 'storeDeviceData':
promises.push(cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
(txn) => {
cryptoStore.storeEndToEndDeviceData(data, txn);
},
).then(() => {
++deviceDataStored;
}));
break;
case 'storeRooms':
promises.push(cryptoStore.doTxn(
'readwrite', [IndexedDBCryptoStore.STORE_ROOMS],
(txn) => {
for (const [roomId, roomInfo] of Object.entries(data)) {
cryptoStore.storeEndToEndRoom(roomId, roomInfo, txn);
}
},
).then(() => {
++roomsStored;
}));
break;
case 'storeLocalStorage':
window.localStorage.setItem(data.key, data.val);
++localStorageKeysStored;
break;
case 'getSummary':
await Promise.all(promises);
e.source.postMessage({
cmd: 'summary',
data: {
accountStored,
sessionsStored,
inboundGroupSessionsStored,
deviceDataStored,
roomsStored,
localStorageKeysStored,
},
}, SOURCE_ORIGIN);
break;
}
}
window.addEventListener('message', onMessage);

View file

@ -0,0 +1,7 @@
<html>
<body>
<script src="dest/browser-matrix.min.js"></script>
<script src="source.js"></script>
<iframe name="dest" src="vector://vector/origin_migrator_dest/dest.html" onload="doMigrate()"></iframe>
</body>
</html>

210
origin_migrator/source.js Normal file
View file

@ -0,0 +1,210 @@
/*
Copyright 2018 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const TARGET_ORIGIN = 'vector://vector';
const BATCH_SIZE = 500;
let destFrame;
let initResolver = null;
let getSummaryResolver = null;
function onMessage(e) {
if (e.origin !== TARGET_ORIGIN) return;
if (e.data.cmd === 'initOK' && initResolver) {
initResolver();
initResolver = null;
} else if (e.data.cmd === 'summary' && getSummaryResolver) {
getSummaryResolver(e.data.data);
getSummaryResolver = null;
}
}
async function initDestFrame() {
return new Promise(resolve => {
initResolver = resolve;
destFrame.postMessage({
cmd: 'init',
}, TARGET_ORIGIN);
});
}
async function getSummary() {
return new Promise(resolve => {
getSummaryResolver = resolve;
destFrame.postMessage({
cmd: 'getSummary',
}, TARGET_ORIGIN);
});
}
async function doMigrate() {
let accountSent = 0;
let sessionsSent = 0;
let inboundGroupSessionsSent = 0;
let deviceDataSent = 0;
let roomsSent = 0;
let localStorageKeysSent = 0;
if (!window.ipcRenderer) {
console.error("ipcRenderer not found");
return;
}
if (window.localStorage.getItem('mx_user_id') === null) {
window.ipcRenderer.send("origin_migration_nodata");
return;
}
destFrame = window.parent.frames.dest;
await initDestFrame();
const IndexedDBCryptoStore = window.matrixcs.IndexedDBCryptoStore;
const cryptoStore = new IndexedDBCryptoStore(window.indexedDB, 'matrix-js-sdk:crypto');
await cryptoStore.doTxn(
'readonly', [IndexedDBCryptoStore.STORE_ACCOUNT],
(txn) => {
cryptoStore.getAccount(txn, (account) => {
destFrame.postMessage({
cmd: 'storeAccount',
data: account,
}, TARGET_ORIGIN);
++accountSent;
});
},
);
await cryptoStore.doTxn(
'readonly', [IndexedDBCryptoStore.STORE_SESSIONS],
(txn) => {
let sessBatch = [];
cryptoStore.getAllEndToEndSessions(txn, (sessInfo) => {
if (sessInfo) {
++sessionsSent;
sessBatch.push(sessInfo);
}
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
destFrame.postMessage({
cmd: 'storeSessions',
data: sessBatch,
}, TARGET_ORIGIN);
sessBatch = [];
}
});
},
);
await cryptoStore.doTxn(
'readonly', [IndexedDBCryptoStore.STORE_INBOUND_GROUP_SESSIONS],
(txn) => {
let sessBatch = [];
cryptoStore.getAllEndToEndInboundGroupSessions(txn, (sessInfo) => {
if (sessInfo) {
++inboundGroupSessionsSent;
sessBatch.push(sessInfo);
}
if (sessBatch.length >= BATCH_SIZE || sessInfo === null) {
destFrame.postMessage({
cmd: 'storeInboundGroupSessions',
data: sessBatch,
}, TARGET_ORIGIN);
sessBatch = [];
}
});
},
);
await cryptoStore.doTxn(
'readonly', [IndexedDBCryptoStore.STORE_DEVICE_DATA],
(txn) => {
cryptoStore.getEndToEndDeviceData(txn, (deviceData) => {
destFrame.postMessage({
cmd: 'storeDeviceData',
data: deviceData,
}, TARGET_ORIGIN);
++deviceDataSent;
});
},
);
await cryptoStore.doTxn(
'readonly', [IndexedDBCryptoStore.STORE_ROOMS],
(txn) => {
cryptoStore.getEndToEndRooms(txn, (rooms) => {
destFrame.postMessage({
cmd: 'storeRooms',
data: rooms,
}, TARGET_ORIGIN);
++roomsSent;
});
},
);
// we don't bother migrating;
// * sync data (we can just initialsync again)
// * logs
// * key requests (worst case they'll just be re-sent)
// * sessions needing backup (feature isn't available on Electron)
for (let i = 0; i < window.localStorage.length; ++i) {
const key = window.localStorage.key(i);
const val = window.localStorage.getItem(key);
destFrame.postMessage({
cmd: 'storeLocalStorage',
data: { key, val },
}, TARGET_ORIGIN);
++localStorageKeysSent;
}
const summary = await getSummary();
let success = false;
if (
summary.accountStored === accountSent &&
summary.sessionsStored === sessionsSent &&
summary.inboundGroupSessionsStored === inboundGroupSessionsSent &&
summary.deviceDataStored === deviceDataSent &&
summary.roomsStored === roomsSent &&
summary.localStorageKeysStored === localStorageKeysSent
) {
success = true;
window.localStorage.clear();
await cryptoStore.deleteAllData();
// we don't bother migrating them, but also blow away the sync & logs db,
// otherwise they'll just hang about taking up space
await new Promise(resolve => {
const req = window.indexedDB.deleteDatabase('matrix-js-sdk:riot-web-sync');
req.onsuccess = resolve;
req.onerror = resolve;
});
await new Promise(resolve => {
const req = window.indexedDB.deleteDatabase('logs');
req.onsuccess = resolve;
req.onerror = resolve;
});
}
window.ipcRenderer.send("origin_migration_complete", success, {
accountSent, sessionsSent, inboundGroupSessionsSent,
deviceDataSent, roomsSent, localStorageKeysSent,
}, summary);
}
window.addEventListener('message', onMessage);

9512
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -2,7 +2,7 @@
"name": "riot-web", "name": "riot-web",
"productName": "Riot", "productName": "Riot",
"main": "electron_app/src/electron-main.js", "main": "electron_app/src/electron-main.js",
"version": "0.13.5", "version": "1.5.0",
"description": "A feature-rich client for Matrix.org", "description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.", "author": "New Vector Ltd.",
"repository": { "repository": {
@ -30,141 +30,142 @@
"reskindex:watch": "reskindex -h src/header -w", "reskindex:watch": "reskindex -h src/header -w",
"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 && yarn i18n && node scripts/compare-file.js src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
"build:res": "node scripts/copy-res.js", "build:res": "node scripts/copy-res.js",
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js", "build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
"build:compile": "npm run reskindex && babel --source-maps -d lib src", "build:compile": "yarn reskindex && babel --source-maps -d lib src",
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail", "build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production",
"build:bundle:dev": "webpack --optimize-occurence-order --progress --bail", "build:bundle:dev": "webpack --progress --bail --mode development",
"build:electron": "npm run clean && npm run build && npm run install:electron && build -wml --ia32 --x64", "build:electron": "yarn clean && yarn build && yarn install:electron && electron-builder -wml --ia32 --x64",
"build": "npm run reskindex && npm run build:res && npm run build:bundle", "build:electron:linux": "yarn build && electron-builder -l --x64",
"build:dev": "npm run reskindex && npm run build:res && npm run build:bundle:dev", "build:electron:macos": "yarn build && electron-builder -m --x64",
"build:electron:windows": "yarn build && electron-builder -w --ia32 --x64",
"build:react-sdk": "node scripts/yarn-sub.js matrix-react-sdk build",
"build:js-sdk": "node scripts/yarn-sub.js matrix-js-sdk start:init",
"build": "yarn build:js-sdk && yarn build:react-sdk && yarn reskindex && yarn build:res && yarn build:bundle",
"build:dev": "yarn build:js-sdk && yarn build:react-sdk && yarn reskindex && yarn build:res && yarn build:bundle:dev",
"dist": "scripts/package.sh", "dist": "scripts/package.sh",
"install:electron": "install-app-deps", "install:electron": "electron-builder install-app-deps",
"electron": "npm run install:electron && electron .", "electron": "yarn install:electron && electron .",
"start:res": "node scripts/copy-res.js -w", "start:res": "node scripts/copy-res.js -w",
"start:js": "webpack-dev-server --output-filename=bundles/_dev_/[name].js --output-chunk-file=bundles/_dev_/[name].js -w --progress", "start:js": "webpack-dev-server --host=0.0.0.0 --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --progress --mode development",
"start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress", "start:js:prod": "cross-env NODE_ENV=production webpack-dev-server -w --progress --mode production",
"start": "parallelshell \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js\"", "start:js-sdk": "node scripts/yarn-sub.js matrix-js-sdk start:watch",
"start:prod": "parallelshell \"npm run reskindex:watch\" \"npm run start:res\" \"npm run start:js:prod\"", "start:js-sdk:prod": "cross-env NODE_ENV=production node scripts/yarn-sub.js matrix-js-sdk start:watch",
"start:react-sdk": "node scripts/yarn-sub.js matrix-react-sdk start:all",
"start:react-sdk:prod": "cross-env NODE_ENV=production node scripts/yarn-sub.js matrix-react-sdk start:all",
"start": "yarn build:js-sdk && yarn build:react-sdk && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"yarn start:js-sdk\" \"yarn start:react-sdk\" \"yarn reskindex:watch\" \"yarn start:res\" \"yarn start:js\"",
"start:prod": "yarn build:js-sdk && yarn build:react-sdk && concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n js-sdk,react-sdk,reskindex,res,riot-js \"yarn start:js-sdk:prod\" \"yarn start:react-sdk:prod\" \"yarn reskindex:watch\" \"yarn start:res\" \"yarn start:js:prod\"",
"lint": "eslint src/", "lint": "eslint src/",
"lintall": "eslint src/ test/", "lintall": "eslint src/ test/",
"clean": "rimraf lib webapp electron_app/dist", "clean": "rimraf lib webapp electron_app/dist",
"prepublish": "npm run clean && npm run build:compile", "prepare": "yarn clean && yarn build:compile",
"test": "karma start --single-run=true --autoWatch=false --browsers ChromeHeadless", "test": "karma start --single-run=true --autoWatch=false --browsers VectorChromeHeadless",
"test-multi": "karma start" "test-multi": "karma start"
}, },
"dependencies": { "dependencies": {
"babel-polyfill": "^6.5.0", "babel-polyfill": "^6.26.0",
"babel-runtime": "^6.11.6", "babel-runtime": "^6.26.0",
"bluebird": "^3.5.0", "bluebird": "^3.5.2",
"browser-request": "^0.3.3", "browser-request": "^0.3.3",
"classnames": "^2.1.2",
"draft-js": "^0.11.0-alpha", "draft-js": "^0.11.0-alpha",
"extract-text-webpack-plugin": "^0.9.1", "extract-text-webpack-plugin": "^4.0.0-beta.0",
"favico.js": "^0.3.10", "favico.js": "^0.3.10",
"filesize": "3.5.6", "gemini-scrollbar": "github:matrix-org/gemini-scrollbar#91e1e566",
"flux": "2.1.1", "gfm.css": "^1.1.2",
"gemini-scrollbar": "matrix-org/gemini-scrollbar#b302279", "highlight.js": "^9.13.1",
"gfm.css": "^1.1.1", "matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
"highlight.js": "^9.0.0", "matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop",
"linkifyjs": "^2.1.3", "modernizr": "^3.6.0",
"matrix-js-sdk": "0.9.2", "olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz",
"matrix-react-sdk": "0.11.4", "prop-types": "^15.7.2",
"modernizr": "^3.1.0", "react": "^16.9.0",
"pako": "^1.0.5", "react-dom": "^16.9.0",
"prop-types": "^15.5.10", "sanitize-html": "^1.19.1",
"react": "^15.6.0", "ua-parser-js": "^0.7.19",
"react-beautiful-dnd": "^4.0.1", "url": "^0.11.0"
"react-dom": "^15.6.0",
"react-gemini-scrollbar": "matrix-org/react-gemini-scrollbar#5e97aef",
"sanitize-html": "^1.11.1",
"text-encoding-utf-8": "^1.0.1",
"ua-parser-js": "^0.7.10",
"url": "^0.11.0",
"velocity-vector": "vector-im/velocity#059e3b2"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^6.6.0", "autoprefixer": "^6.6.0",
"babel-cli": "^6.5.2", "babel-cli": "^6.26.0",
"babel-core": "^6.14.0", "babel-core": "^6.26.3",
"babel-eslint": "^6.1.0", "babel-eslint": "^8.1.1",
"babel-loader": "^6.2.5", "babel-loader": "^7.1.5",
"babel-plugin-add-module-exports": "^0.2.1", "babel-plugin-add-module-exports": "^0.2.1",
"babel-plugin-syntax-dynamic-import": "^6.18.0",
"babel-plugin-transform-async-to-bluebird": "^1.1.1", "babel-plugin-transform-async-to-bluebird": "^1.1.1",
"babel-plugin-transform-class-properties": "^6.16.0", "babel-plugin-transform-builtin-extend": "^1.1.2",
"babel-plugin-transform-object-rest-spread": "^6.16.0", "babel-plugin-transform-class-properties": "^6.24.1",
"babel-plugin-transform-runtime": "^6.15.0", "babel-plugin-transform-object-rest-spread": "^6.26.0",
"babel-preset-es2015": "^6.16.0", "babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2016": "^6.16.0", "babel-preset-es2015": "^6.24.1",
"babel-preset-es2017": "^6.16.0", "babel-preset-es2016": "^6.24.1",
"babel-preset-react": "^6.16.0", "babel-preset-es2017": "^6.24.1",
"babel-preset-stage-2": "^6.17.0", "babel-preset-react": "^6.24.1",
"chokidar": "^1.6.1", "babel-preset-stage-2": "^6.24.1",
"chokidar": "^2.0.4",
"concurrently": "^4.0.1",
"cpx": "^1.3.2", "cpx": "^1.3.2",
"cross-env": "^4.0.0", "cross-env": "^4.0.0",
"css-raw-loader": "^0.1.1", "css-loader": "^2.1.0",
"electron-builder": "^11.2.4", "electron-builder": "^21.2.0",
"electron-builder-squirrel-windows": "^11.2.1", "electron-builder-squirrel-windows": "^21.2.0",
"electron-devtools-installer": "^2.2.0", "electron-devtools-installer": "^2.2.4",
"emojione": "^2.2.7", "electron-notarize": "^0.1.1",
"eslint": "^3.14.0", "eslint": "^5.8.0",
"eslint-config-google": "^0.7.1", "eslint-config-google": "^0.7.1",
"eslint-plugin-babel": "^4.1.1", "eslint-plugin-babel": "^4.1.2",
"eslint-plugin-flowtype": "^2.30.0", "eslint-plugin-flowtype": "^2.50.3",
"eslint-plugin-react": "^7.4.0", "eslint-plugin-react": "^7.11.1",
"expect": "^1.16.0", "expect": "^1.16.0",
"file-loader": "^3.0.1",
"fs-extra": "^0.30.0", "fs-extra": "^0.30.0",
"html-webpack-plugin": "^2.24.0", "html-webpack-plugin": "^3.2.0",
"json-loader": "^0.5.3", "json-loader": "^0.5.3",
"karma": "^1.7.0", "karma": "^3.1.2",
"karma-chrome-launcher": "^0.2.3", "karma-chrome-launcher": "^2.2.0",
"karma-cli": "^0.1.2", "karma-cli": "^1.0.1",
"karma-junit-reporter": "^0.4.1",
"karma-logcapture-reporter": "0.0.1", "karma-logcapture-reporter": "0.0.1",
"karma-mocha": "^0.2.2", "karma-mocha": "^1.3.0",
"karma-sourcemap-loader": "^0.3.7", "karma-sourcemap-loader": "^0.3.7",
"karma-spec-reporter": "0.0.31", "karma-spec-reporter": "0.0.31",
"karma-summary-reporter": "^1.3.3", "karma-summary-reporter": "^1.5.1",
"karma-webpack": "^1.7.0", "karma-webpack": "4.0.0-beta.0",
"matrix-mock-request": "^1.2.0", "loader-utils": "^1.2.3",
"matrix-react-test-utils": "^0.2.0", "matrix-mock-request": "^1.2.3",
"matrix-react-test-utils": "^0.2.2",
"minimist": "^1.2.0", "minimist": "^1.2.0",
"mkdirp": "^0.5.1", "mkdirp": "^0.5.1",
"mocha": "^2.4.5", "mocha": "^5.2.0",
"parallelshell": "^3.0.2",
"postcss-extend": "^1.0.5", "postcss-extend": "^1.0.5",
"postcss-import": "^9.0.0", "postcss-import": "^11.1.0",
"postcss-loader": "^1.2.2", "postcss-loader": "^2.1.6",
"postcss-mixins": "^5.4.1", "postcss-mixins": "^6.2.0",
"postcss-nested": "^1.0.0", "postcss-nested": "^3.0.0",
"postcss-scss": "^0.4.0", "postcss-scss": "^1.0.6",
"postcss-simple-vars": "^3.0.0", "postcss-simple-vars": "^4.1.0",
"postcss-strip-inline-comments": "^0.1.5", "postcss-strip-inline-comments": "^0.1.5",
"react-addons-perf": "^15.4.0",
"react-addons-test-utils": "^15.6.0",
"rimraf": "^2.4.3", "rimraf": "^2.4.3",
"source-map-loader": "^0.1.5", "shell-escape": "^0.2.0",
"webpack": "^1.12.14", "source-map-loader": "^0.2.4",
"webpack-dev-server": "^1.16.2" "webpack": "^4.23.1",
}, "webpack-cli": "^3.1.2",
"optionalDependencies": { "webpack-dev-server": "^3.1.11"
"olm": "https://matrix.org/packages/npm/olm/olm-2.2.1.tgz"
}, },
"build": { "build": {
"appId": "im.riot.app", "appId": "im.riot.app",
"category": "Network", "electronVersion": "6.0.11",
"electronVersion": "1.7.9",
"//asar=false": "https://github.com/electron-userland/electron-builder/issues/675",
"asar": false,
"dereference": true,
"//files": "We bundle everything, so we only need to include webapp/",
"files": [ "files": [
"node_modules/**", "node_modules/**",
"src/**", "src/**"
"img/**"
], ],
"extraResources": [ "extraResources": [
"webapp/**/*" {
"from": "electron_app/img",
"to": "img"
},
"webapp/**/*",
"origin_migrator/**/*"
], ],
"linux": { "linux": {
"target": "deb", "target": "deb",
@ -174,13 +175,23 @@
"StartupWMClass": "riot" "StartupWMClass": "riot"
} }
}, },
"deb": {
"afterInstall": "electron_app/build/linux/after-install.tpl"
},
"mac": {
"category": "public.app-category.social-networking",
"darkModeSupport": true
},
"win": { "win": {
"target": "squirrel" "target": {
"target": "squirrel"
}
}, },
"directories": { "directories": {
"buildResources": "electron_app/build", "buildResources": "electron_app/build",
"output": "electron_app/dist", "output": "electron_app/dist",
"app": "electron_app" "app": "electron_app"
} },
"afterSign": "scripts/electron_afterSign.js"
} }
} }

View file

@ -1,18 +1,27 @@
#!/bin/bash #!/bin/bash
# #
# Script to perform a release of vector-web. # Script to perform a release of riot-web.
# #
# Requires github-changelog-generator; to install, do # Requires github-changelog-generator; to install, do
# pip install git+https://github.com/matrix-org/github-changelog-generator.git # pip install git+https://github.com/matrix-org/github-changelog-generator.git
set -e set -e
orig_args=$@
# chomp any args starting with '-' as these need to go
# through to the release script and otherwise we'll get
# confused about what the version arg is.
while [[ "$1" == -* ]]; do
shift
done
cd `dirname $0` cd `dirname $0`
for i in matrix-js-sdk matrix-react-sdk for i in matrix-js-sdk matrix-react-sdk
do do
depver=`cat package.json | jq -r .dependencies[\"$i\"]` depver=`cat package.json | jq -r .dependencies[\"$i\"]`
latestver=`npm show $i version` latestver=`yarn info -s $i version`
if [ "$depver" != "$latestver" ] if [ "$depver" != "$latestver" ]
then then
echo "The latest version of $i is $latestver but package.json depends on $depver" echo "The latest version of $i is $latestver but package.json depends on $depver"
@ -29,13 +38,12 @@ done
# bump Electron's package.json first # bump Electron's package.json first
release="${1#v}" release="${1#v}"
tag="v${release}" tag="v${release}"
echo "electron npm version" echo "electron yarn version"
cd electron_app cd electron_app
npm version --no-git-tag-version "$release" yarn version --no-git-tag-version --new-version "$release"
git commit package.json -m "$tag" git commit package.json -m "$tag"
cd .. cd ..
exec ./node_modules/matrix-js-sdk/release.sh -z "$@" exec ./node_modules/matrix-js-sdk/release.sh -u vector-im -z "$orig_args"

View file

@ -1 +1 @@
signing_id: packages@riot.im signing_id: releases@riot.im

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1,015 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 654 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 655 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 659 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 566 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 668 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 672 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 669 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 568 B

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