Merge branch 'develop' of github.com:vector-im/element-web into t3chguy/querystring
Conflicts: package.json src/@types/global.d.ts src/vector/app.tsx src/vector/jitsi/index.ts src/vector/platform/WebPlatform.ts yarn.lock
|
@ -3,7 +3,6 @@ test/
|
||||||
webapp/
|
webapp/
|
||||||
lib/
|
lib/
|
||||||
node_modules/
|
node_modules/
|
||||||
electron_app/
|
|
||||||
karma-reports/
|
karma-reports/
|
||||||
.idea/
|
.idea/
|
||||||
.tmp/
|
.tmp/
|
||||||
|
|
31
.eslintrc.js
|
@ -1,3 +1,30 @@
|
||||||
module.exports = {
|
module.exports = {
|
||||||
extends: ["./node_modules/matrix-react-sdk/.eslintrc.js"],
|
plugins: ["matrix-org"],
|
||||||
}
|
extends: [
|
||||||
|
"plugin:matrix-org/babel",
|
||||||
|
"plugin:matrix-org/react",
|
||||||
|
],
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
// Things we do that break the ideal style
|
||||||
|
"quotes": "off",
|
||||||
|
},
|
||||||
|
overrides: [{
|
||||||
|
files: ["src/**/*.{ts,tsx}"],
|
||||||
|
extends: [
|
||||||
|
"plugin:matrix-org/typescript",
|
||||||
|
"plugin:matrix-org/react",
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
// Things we do that break the ideal style
|
||||||
|
"prefer-promise-reject-errors": "off",
|
||||||
|
"quotes": "off",
|
||||||
|
|
||||||
|
// We disable this while we're transitioning
|
||||||
|
"@typescript-eslint/no-explicit-any": "off",
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
};
|
||||||
|
|
12
.github/ISSUE_TEMPLATE.md
vendored
|
@ -1,3 +1,5 @@
|
||||||
|
<!-- A picture's worth a thousand words: PLEASE INCLUDE A SCREENSHOT :P -->
|
||||||
|
|
||||||
<!-- Please report security issues by email to security@matrix.org -->
|
<!-- Please report security issues by email to security@matrix.org -->
|
||||||
|
|
||||||
<!-- This is a bug report template. By following the instructions below and
|
<!-- This is a bug report template. By following the instructions below and
|
||||||
|
@ -10,11 +12,11 @@ that aren't relevant to your particular case.
|
||||||
Text between <!-- and --> marks will be invisible in the report.
|
Text between <!-- and --> marks will be invisible in the report.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
### Description
|
#### Description
|
||||||
|
|
||||||
Describe here the problem that you are experiencing, or the feature you are requesting.
|
Describe here the problem that you are experiencing, or the feature you are requesting.
|
||||||
|
|
||||||
### Steps to reproduce
|
#### Steps to reproduce
|
||||||
|
|
||||||
- For bugs, list the steps
|
- For bugs, list the steps
|
||||||
- that reproduce the bug
|
- that reproduce the bug
|
||||||
|
@ -28,7 +30,7 @@ file a bug here too! -->
|
||||||
|
|
||||||
<!-- Include screenshots if possible: you can drag and drop images below. -->
|
<!-- Include screenshots if possible: you can drag and drop images below. -->
|
||||||
|
|
||||||
### Version information
|
#### Version information
|
||||||
|
|
||||||
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
|
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
|
||||||
|
|
||||||
|
@ -36,9 +38,9 @@ file a bug here too! -->
|
||||||
|
|
||||||
For the web app:
|
For the web app:
|
||||||
|
|
||||||
- **Browser**: Chrome, Safari, Firefox? which version?
|
- **Browser**: Chrome, Firefox, Safari, Edge? which version?
|
||||||
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
|
- **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?
|
- **URL**: develop.element.io / app.element.io / somewhere else? If a private server, what version of Element Web?
|
||||||
|
|
||||||
For the desktop app:
|
For the desktop app:
|
||||||
|
|
||||||
|
|
14
.github/ISSUE_TEMPLATE/bug_report.md
vendored
|
@ -2,11 +2,13 @@
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
title: ''
|
title: ''
|
||||||
labels: bug
|
labels: T-Defect
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
<!-- A picture's worth a thousand words: PLEASE INCLUDE A SCREENSHOT :P -->
|
||||||
|
|
||||||
<!-- Please report security issues by email to security@matrix.org -->
|
<!-- Please report security issues by email to security@matrix.org -->
|
||||||
|
|
||||||
<!-- This is a bug report template. By following the instructions below and
|
<!-- This is a bug report template. By following the instructions below and
|
||||||
|
@ -19,11 +21,11 @@ that aren't relevant to your particular case.
|
||||||
Text between <!-- and --> marks will be invisible in the report.
|
Text between <!-- and --> marks will be invisible in the report.
|
||||||
-->
|
-->
|
||||||
|
|
||||||
### Description
|
#### Description
|
||||||
|
|
||||||
Describe here the problem that you are experiencing, or the feature you are requesting.
|
Describe here the problem that you are experiencing, or the feature you are requesting.
|
||||||
|
|
||||||
### Steps to reproduce
|
#### Steps to reproduce
|
||||||
|
|
||||||
- For bugs, list the steps
|
- For bugs, list the steps
|
||||||
- that reproduce the bug
|
- that reproduce the bug
|
||||||
|
@ -38,7 +40,7 @@ Logs being sent: yes/no
|
||||||
|
|
||||||
<!-- Include screenshots if possible: you can drag and drop images below. -->
|
<!-- Include screenshots if possible: you can drag and drop images below. -->
|
||||||
|
|
||||||
### Version information
|
#### Version information
|
||||||
|
|
||||||
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
|
<!-- IMPORTANT: please answer the following questions, to help us narrow down the problem -->
|
||||||
|
|
||||||
|
@ -46,9 +48,9 @@ Logs being sent: yes/no
|
||||||
|
|
||||||
For the web app:
|
For the web app:
|
||||||
|
|
||||||
- **Browser**: Chrome, Safari, Firefox? which version?
|
- **Browser**: Chrome, Firefox, Safari, Edge? which version?
|
||||||
- **OS**: Windows, macOS, Ubuntu, Arch Linux, etc?
|
- **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?
|
- **URL**: develop.element.io / app.element.io / somewhere else? If a private server, what version of Element Web?
|
||||||
|
|
||||||
For the desktop app:
|
For the desktop app:
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,19 @@
|
||||||
name: Suggestion or Feature request
|
name: Suggestion or Feature request
|
||||||
about: Suggest an idea for this project
|
about: Suggest an idea for this project
|
||||||
title: ''
|
title: ''
|
||||||
labels: suggestion
|
labels: T-Enhancement
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
**Is your suggestion related to a problem? Please describe.**
|
#### 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 [...]
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
#### Describe the solution you'd like.
|
||||||
A clear and concise description of what you want to happen.
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
#### Describe alternatives you've considered.
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
**Additional context**
|
#### Additional context
|
||||||
Add any other context or screenshots about the feature request here.
|
Add any other context or screenshots about the feature request here.
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
---
|
|
||||||
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 -->
|
|
11
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
<!-- Please read https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md before submitting your pull request -->
|
||||||
|
|
||||||
|
<!-- Include a Sign-Off as described in https://github.com/matrix-org/matrix-js-sdk/blob/develop/CONTRIBUTING.md#sign-off -->
|
||||||
|
|
||||||
|
<!-- To specify text for the changelog entry (otherwise the PR title will be used):
|
||||||
|
Notes:
|
||||||
|
|
||||||
|
Changelog entries will also appear in element-desktop. For PRs that *only* affect the desktop version:
|
||||||
|
Notes: none
|
||||||
|
element-desktop notes: <notes>
|
||||||
|
-->
|
5
.gitignore
vendored
|
@ -4,9 +4,6 @@
|
||||||
/key.pem
|
/key.pem
|
||||||
/lib
|
/lib
|
||||||
/node_modules
|
/node_modules
|
||||||
/electron_app/node_modules
|
|
||||||
/electron_app/dist
|
|
||||||
/electron_app/pub
|
|
||||||
/packages/
|
/packages/
|
||||||
/webapp
|
/webapp
|
||||||
/.npmrc
|
/.npmrc
|
||||||
|
@ -22,3 +19,5 @@ electron/pub
|
||||||
/src/component-index.js
|
/src/component-index.js
|
||||||
/.tmp
|
/.tmp
|
||||||
/webpack-stats.json
|
/webpack-stats.json
|
||||||
|
.vscode
|
||||||
|
.vscode/
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
{
|
{
|
||||||
"minify": true,
|
"minify": true,
|
||||||
"classPrefix": "modernizr_",
|
"enableClasses": false,
|
||||||
"options": [
|
|
||||||
"setClasses"
|
|
||||||
],
|
|
||||||
"feature-detects": [
|
"feature-detects": [
|
||||||
"test/css/animations",
|
"test/css/animations",
|
||||||
"test/css/displaytable",
|
"test/css/displaytable",
|
||||||
|
@ -29,6 +26,7 @@
|
||||||
"test/url/urlsearchparams",
|
"test/url/urlsearchparams",
|
||||||
|
|
||||||
"test/cors",
|
"test/cors",
|
||||||
|
"test/crypto",
|
||||||
"test/iframe/sandbox",
|
"test/iframe/sandbox",
|
||||||
"test/json",
|
"test/json",
|
||||||
"test/network/fetch",
|
"test/network/fetch",
|
||||||
|
|
|
@ -19,7 +19,7 @@ module.exports = {
|
||||||
"at-rule-no-unknown": null,
|
"at-rule-no-unknown": null,
|
||||||
"no-descending-specificity": null,
|
"no-descending-specificity": null,
|
||||||
"scss/at-rule-no-unknown": [true, {
|
"scss/at-rule-no-unknown": [true, {
|
||||||
// https://github.com/vector-im/riot-web/issues/10544
|
// https://github.com/vector-im/element-web/issues/10544
|
||||||
"ignoreAtRules": ["define-mixin"],
|
"ignoreAtRules": ["define-mixin"],
|
||||||
}],
|
}],
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,3 +16,6 @@ include:
|
||||||
|
|
||||||
* Alexandr Korsak (https://github.com/oivoodoo)
|
* Alexandr Korsak (https://github.com/oivoodoo)
|
||||||
Improved multiple file uploading
|
Improved multiple file uploading
|
||||||
|
|
||||||
|
* Thom Cleary (https://github.com/thomcatdotrocks)
|
||||||
|
Small update for tarball deployment
|
||||||
|
|
1205
CHANGELOG.md
4
CONTRIBUTING.md
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
Contributing code to Element
|
||||||
|
============================
|
||||||
|
|
||||||
|
Element follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.rst.
|
|
@ -1,4 +0,0 @@
|
||||||
Contributing code to Riot
|
|
||||||
=========================
|
|
||||||
|
|
||||||
Riot follows the same pattern as https://github.com/matrix-org/matrix-js-sdk/blob/master/CONTRIBUTING.rst.
|
|
|
@ -1,8 +1,8 @@
|
||||||
# Builder
|
# Builder
|
||||||
FROM node:10 as builder
|
FROM node:14-buster as builder
|
||||||
|
|
||||||
# Support custom branches of the react-sdk and js-sdk. This also helps us build
|
# Support custom branches of the react-sdk and js-sdk. This also helps us build
|
||||||
# images of riot-web develop.
|
# images of element-web develop.
|
||||||
ARG USE_CUSTOM_SDKS=false
|
ARG USE_CUSTOM_SDKS=false
|
||||||
ARG REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git"
|
ARG REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git"
|
||||||
ARG REACT_SDK_BRANCH="master"
|
ARG REACT_SDK_BRANCH="master"
|
||||||
|
@ -34,4 +34,4 @@ COPY --from=builder /src/webapp /app
|
||||||
RUN sed -i '3i\ \ \ \ application/wasm wasm\;' /etc/nginx/mime.types
|
RUN sed -i '3i\ \ \ \ application/wasm wasm\;' /etc/nginx/mime.types
|
||||||
|
|
||||||
RUN rm -rf /usr/share/nginx/html \
|
RUN rm -rf /usr/share/nginx/html \
|
||||||
&& ln -s /app /usr/share/nginx/html
|
&& ln -s /app /usr/share/nginx/html
|
||||||
|
|
353
README.md
|
@ -1,80 +1,122 @@
|
||||||
Riot
|
Element
|
||||||
====
|
=======
|
||||||
|
|
||||||
Riot (formerly known as Vector) is a Matrix web client built using the [Matrix
|
Element (formerly known as Vector and Riot) 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).
|
||||||
|
|
||||||
Supported Environments
|
Supported Environments
|
||||||
======================
|
======================
|
||||||
|
|
||||||
Riot has several tiers of support for different environments:
|
Element has several tiers of support for different environments:
|
||||||
|
|
||||||
* Supported
|
* Supported
|
||||||
* Definition: Issues **actively triaged**, regressions **block** the release
|
* Definition: Issues **actively triaged**, regressions **block** the release
|
||||||
* Last 2 major versions of Chrome, Firefox, and Safari on desktop OSes
|
* Last 2 major versions of Chrome, Firefox, Safari, and Edge on desktop OSes
|
||||||
* Latest release of official Riot Desktop app on desktop OSes
|
* Latest release of official Element Desktop app on desktop OSes
|
||||||
* Desktop OSes means macOS, Windows, and Linux versions for desktop devices
|
* Desktop OSes means macOS, Windows, and Linux versions for desktop devices
|
||||||
that are actively supported by the OS vendor and receive security updates
|
that are actively supported by the OS vendor and receive security updates
|
||||||
* Experimental
|
* Experimental
|
||||||
* Definition: Issues **accepted**, regressions **do not block** the release
|
* Definition: Issues **accepted**, regressions **do not block** the release
|
||||||
* Riot as an installed PWA via current stable version of Chrome, Firefox, and Safari
|
* Element as an installed PWA via current stable version of Chrome, Firefox, and Safari
|
||||||
* Mobile web for current stable version of Chrome, Firefox, and Safari on Android, iOS, and iPadOS
|
* Mobile web for current stable version of Chrome, Firefox, and Safari on Android, iOS, and iPadOS
|
||||||
* Not supported
|
* Not supported
|
||||||
* Definition: Issues only affecting unsupported environments are **closed**
|
* Definition: Issues only affecting unsupported environments are **closed**
|
||||||
* Everything else
|
* Everything else
|
||||||
|
|
||||||
For accessing Riot on an Android or iOS device, we currently recommend the
|
For accessing Element on an Android or iOS device, we currently recommend the
|
||||||
native apps [riot-android](https://github.com/vector-im/riot-android)
|
native apps [element-android](https://github.com/vector-im/element-android)
|
||||||
and [riot-ios](https://github.com/vector-im/riot-ios).
|
and [element-ios](https://github.com/vector-im/element-ios).
|
||||||
|
|
||||||
Getting Started
|
Getting Started
|
||||||
===============
|
===============
|
||||||
|
|
||||||
The easiest way to test Riot is to just use the hosted copy at https://riot.im/app.
|
The easiest way to test Element is to just use the hosted copy at https://app.element.io.
|
||||||
The `develop` branch is continuously deployed by Jenkins at https://riot.im/develop
|
The `develop` branch is continuously deployed to https://develop.element.io
|
||||||
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 Element, the quickest bet is to use a pre-built
|
||||||
released version of Riot:
|
released version of Element:
|
||||||
|
|
||||||
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/element-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 `element-x.x.x` directory to an appropriate name
|
||||||
1. Configure the correct caching headers in your webserver (see below)
|
1. Configure the correct caching headers in your webserver (see below)
|
||||||
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 the [configuration docs](docs/config.md) 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 Element!
|
||||||
|
|
||||||
Releases are signed using gpg and the OpenPGP standard, and can be checked against the public key located
|
Releases are signed using gpg and the OpenPGP standard, and can be checked against the public key located
|
||||||
at https://packages.riot.im/riot-release-key.asc.
|
at https://packages.riot.im/element-release-key.asc.
|
||||||
|
|
||||||
Note that for the security of your chats will need to serve Riot
|
Note that for the security of your chats will need to serve Element
|
||||||
over HTTPS. Major browsers also do not allow you to use VoIP/video
|
over HTTPS. Major browsers also do not allow you to use VoIP/video
|
||||||
chats over HTTP, as WebRTC is only usable over HTTPS.
|
chats over HTTP, as WebRTC is only usable over HTTPS.
|
||||||
There are some exceptions like when using localhost, which is
|
There are some exceptions like when using localhost, which is
|
||||||
considered a [secure context](https://developer.mozilla.org/docs/Web/Security/Secure_Contexts)
|
considered a [secure context](https://developer.mozilla.org/docs/Web/Security/Secure_Contexts)
|
||||||
and thus allowed.
|
and thus allowed.
|
||||||
|
|
||||||
To install Riot as a desktop application, see [Running as a desktop
|
To install Element as a desktop application, see [Running as a desktop
|
||||||
app](#running-as-a-desktop-app) below.
|
app](#running-as-a-desktop-app) below.
|
||||||
|
|
||||||
Important Security Note
|
Important Security Notes
|
||||||
=======================
|
========================
|
||||||
|
|
||||||
We do not recommend running Riot from the same domain name as your Matrix
|
Separate domains
|
||||||
|
----------------
|
||||||
|
|
||||||
|
We do not recommend running Element from the same domain name as your Matrix
|
||||||
homeserver. The reason is the risk of XSS (cross-site-scripting)
|
homeserver. The reason is the risk of XSS (cross-site-scripting)
|
||||||
vulnerabilities that could occur if someone caused Riot to load and render
|
vulnerabilities that could occur if someone caused Element to load and render
|
||||||
malicious user generated content from a Matrix API which then had trusted
|
malicious user generated content from a Matrix API which then had trusted
|
||||||
access to Riot (or other apps) due to sharing the same domain.
|
access to Element (or other apps) due to sharing the same domain.
|
||||||
|
|
||||||
We have put some coarse mitigations into place to try to protect against this
|
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/element-web/issues/1977 for more details.
|
||||||
|
|
||||||
|
Configuration best practices
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
Unless you have special requirements, you will want to add the following to
|
||||||
|
your web server configuration when hosting Element Web:
|
||||||
|
|
||||||
|
- The `X-Frame-Options: SAMEORIGIN` header, to prevent Element Web from being
|
||||||
|
framed and protect from [clickjacking][owasp-clickjacking].
|
||||||
|
- The `frame-ancestors 'none'` directive to your `Content-Security-Policy`
|
||||||
|
header, as the modern replacement for `X-Frame-Options` (though both should be
|
||||||
|
included since not all browsers support it yet, see
|
||||||
|
[this][owasp-clickjacking-csp]).
|
||||||
|
- The `X-Content-Type-Options: nosniff` header, to [disable MIME
|
||||||
|
sniffing][mime-sniffing].
|
||||||
|
- The `X-XSS-Protection: 1; mode=block;` header, for basic XSS protection in
|
||||||
|
legacy browsers.
|
||||||
|
|
||||||
|
[mime-sniffing]:
|
||||||
|
<https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types#mime_sniffing>
|
||||||
|
|
||||||
|
[owasp-clickjacking-csp]:
|
||||||
|
<https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html#content-security-policy-frame-ancestors-examples>
|
||||||
|
|
||||||
|
[owasp-clickjacking]:
|
||||||
|
<https://cheatsheetseries.owasp.org/cheatsheets/Clickjacking_Defense_Cheat_Sheet.html>
|
||||||
|
|
||||||
|
If you are using nginx, this would look something like the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
add_header X-Frame-Options SAMEORIGIN;
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header Content-Security-Policy "frame-ancestors 'none'";
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: In case you are already setting a `Content-Security-Policy` header
|
||||||
|
elsewhere, you should modify it to include the `frame-ancestors` directive
|
||||||
|
instead of adding that last line.
|
||||||
|
|
||||||
Building From Source
|
Building From Source
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Riot is a modular webapp built with modern ES6 and uses a Node.js build system.
|
Element is a modular webapp built with modern ES6 and uses a Node.js build system.
|
||||||
Ensure you have the latest LTS version of Node.js installed.
|
Ensure you have the latest LTS version of Node.js installed.
|
||||||
|
|
||||||
Using `yarn` instead of `npm` is recommended. Please see the Yarn [install
|
Using `yarn` instead of `npm` is recommended. Please see the Yarn [install
|
||||||
|
@ -82,13 +124,13 @@ guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it alread
|
||||||
|
|
||||||
1. Install or update `node.js` so that your `node` is at least v10.x.
|
1. Install or update `node.js` so that your `node` is at least v10.x.
|
||||||
1. Install `yarn` if not present already.
|
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/element-web.git`.
|
||||||
1. Switch to the riot-web directory: `cd riot-web`.
|
1. Switch to the element-web directory: `cd element-web`.
|
||||||
1. Install the prerequisites: `yarn install`.
|
1. Install the prerequisites: `yarn install`.
|
||||||
* If you're using the `develop` branch, then it is recommended to set up a
|
* If you're using the `develop` branch, then it is recommended to set up a
|
||||||
proper development environment (see [Setting up a dev
|
proper development environment (see [Setting up a dev
|
||||||
environment](#setting-up-a-dev-environment) below). Alternatively, you
|
environment](#setting-up-a-dev-environment) below). Alternatively, you
|
||||||
can use https://riot.im/develop - the continuous integration release of
|
can use https://develop.element.io - the continuous integration release of
|
||||||
the develop branch.
|
the develop branch.
|
||||||
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 the [configuration docs](docs/config.md) for details.
|
modifying it. See the [configuration docs](docs/config.md) for details.
|
||||||
|
@ -97,51 +139,19 @@ guide](https://classic.yarnpkg.com/en/docs/install) if you do not have it alread
|
||||||
web server.
|
web server.
|
||||||
|
|
||||||
Note that `yarn dist` is not supported on Windows, so Windows users can run `yarn build`,
|
Note that `yarn dist` is not supported on Windows, so Windows users can run `yarn build`,
|
||||||
which will build all the necessary files into the `webapp` directory. The version of Riot
|
which will build all the necessary files into the `webapp` directory. The version of Element
|
||||||
will not appear in Settings without using the dist script. You can then mount the
|
will not appear in Settings without using the dist script. You can then mount the
|
||||||
`webapp` directory on your webserver to actually serve up the app, which is entirely static content.
|
`webapp` directory on your web server to actually serve up the app, which is
|
||||||
|
entirely static content.
|
||||||
|
|
||||||
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
|
Element can also be run as a desktop app, wrapped in Electron. You can download a
|
||||||
pre-built version from https://riot.im/download/desktop/ or, if you prefer,
|
pre-built version from https://element.io/get-started or, if you prefer,
|
||||||
build it yourself.
|
build it yourself.
|
||||||
|
|
||||||
To build it yourself, follow the instructions below.
|
To build it yourself, follow the instructions at https://github.com/vector-im/element-desktop.
|
||||||
|
|
||||||
1. Follow the instructions in 'Building From Source' above, but run
|
|
||||||
`yarn build` instead of `yarn dist` (since we don't need the tarball).
|
|
||||||
2. Install Electron and run it:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
yarn electron
|
|
||||||
```
|
|
||||||
|
|
||||||
To build packages, use `electron-builder`. This is configured to output:
|
|
||||||
* `dmg` + `zip` for macOS
|
|
||||||
* `exe` + `nupkg` for Windows
|
|
||||||
* `deb` for Linux
|
|
||||||
But this can be customised by editing the `build` section of package.json
|
|
||||||
as per https://github.com/electron-userland/electron-builder/wiki/Options
|
|
||||||
|
|
||||||
See https://github.com/electron-userland/electron-builder/wiki/Multi-Platform-Build
|
|
||||||
for dependencies required for building packages for various platforms.
|
|
||||||
|
|
||||||
The only platform that can build packages for all three platforms is macOS:
|
|
||||||
```bash
|
|
||||||
brew install mono
|
|
||||||
yarn install
|
|
||||||
yarn build:electron
|
|
||||||
```
|
|
||||||
|
|
||||||
For other packages, use `electron-builder` manually. For example, to build a
|
|
||||||
package for 64 bit Linux:
|
|
||||||
|
|
||||||
1. Follow the instructions in 'Building From Source' above
|
|
||||||
2. `node_modules/.bin/build -l --x64`
|
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
@ -150,7 +160,7 @@ Other options for running as a desktop app:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
yarn global add nativefier
|
yarn global add nativefier
|
||||||
nativefier https://riot.im/app/
|
nativefier https://app.element.io/
|
||||||
```
|
```
|
||||||
|
|
||||||
The [configuration docs](docs/config.md#desktop-app-configuration) show how to
|
The [configuration docs](docs/config.md#desktop-app-configuration) show how to
|
||||||
|
@ -159,31 +169,31 @@ override the desktop app's default settings if desired.
|
||||||
Running from Docker
|
Running from Docker
|
||||||
===================
|
===================
|
||||||
|
|
||||||
The Docker image can be used to serve riot-web as a web server. The easiest way to use
|
The Docker image can be used to serve element-web as a web server. The easiest way to use
|
||||||
it is to use the prebuilt image:
|
it is to use the prebuilt image:
|
||||||
```bash
|
```bash
|
||||||
docker run -p 80:80 vectorim/riot-web
|
docker run -p 80:80 vectorim/element-web
|
||||||
```
|
```
|
||||||
|
|
||||||
To supply your own custom `config.json`, map a volume to `/app/config.json`. For example,
|
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
|
if your custom config was located at `/etc/element-web/config.json` then your Docker command
|
||||||
would be:
|
would be:
|
||||||
```bash
|
```bash
|
||||||
docker run -p 80:80 -v /etc/riot-web/config.json:/app/config.json vectorim/riot-web
|
docker run -p 80:80 -v /etc/element-web/config.json:/app/config.json vectorim/element-web
|
||||||
```
|
```
|
||||||
|
|
||||||
To build the image yourself:
|
To build the image yourself:
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/vector-im/riot-web.git riot-web
|
git clone https://github.com/vector-im/element-web.git element-web
|
||||||
cd riot-web
|
cd element-web
|
||||||
git checkout master
|
git checkout master
|
||||||
docker build -t vectorim/riot-web .
|
docker build .
|
||||||
```
|
```
|
||||||
|
|
||||||
If you're building a custom branch, or want to use the develop branch, check out the appropriate
|
If you're building a custom branch, or want to use the develop branch, check out the appropriate
|
||||||
riot-web branch and then run:
|
element-web branch and then run:
|
||||||
```bash
|
```bash
|
||||||
docker build -t vectorim/riot-web:develop \
|
docker build -t \
|
||||||
--build-arg USE_CUSTOM_SDKS=true \
|
--build-arg USE_CUSTOM_SDKS=true \
|
||||||
--build-arg REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git" \
|
--build-arg REACT_SDK_REPO="https://github.com/matrix-org/matrix-react-sdk.git" \
|
||||||
--build-arg REACT_SDK_BRANCH="develop" \
|
--build-arg REACT_SDK_BRANCH="develop" \
|
||||||
|
@ -192,22 +202,28 @@ docker build -t vectorim/riot-web:develop \
|
||||||
.
|
.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Running in Kubernetes
|
||||||
|
=====================
|
||||||
|
|
||||||
|
The provided element-web docker image can also be run from within a Kubernetes cluster.
|
||||||
|
See the [Kubernetes example](docs/kubernetes.md) for more details.
|
||||||
|
|
||||||
config.json
|
config.json
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Riot supports a variety of settings to configure default servers, behaviour, themes, etc.
|
Element supports a variety of settings to configure default servers, behaviour, themes, etc.
|
||||||
See the [configuration docs](docs/config.md) for more details.
|
See the [configuration docs](docs/config.md) for more details.
|
||||||
|
|
||||||
Labs Features
|
Labs Features
|
||||||
=============
|
=============
|
||||||
|
|
||||||
Some features of Riot may be enabled by flags in the `Labs` section of the settings.
|
Some features of Element 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).
|
Some of these features are described in [labs.md](https://github.com/vector-im/element-web/blob/develop/docs/labs.md).
|
||||||
|
|
||||||
Caching requirements
|
Caching requirements
|
||||||
====================
|
====================
|
||||||
|
|
||||||
Riot requires the following URLs not to be cached, when/if you are serving Riot from your own webserver:
|
Element requires the following URLs not to be cached, when/if you are serving Element from your own webserver:
|
||||||
```
|
```
|
||||||
/config.*.json
|
/config.*.json
|
||||||
/i18n
|
/i18n
|
||||||
|
@ -219,20 +235,20 @@ Riot requires the following URLs not to be cached, when/if you are serving Riot
|
||||||
Development
|
Development
|
||||||
===========
|
===========
|
||||||
|
|
||||||
Before attempting to develop on Riot you **must** read the [developer guide
|
Before attempting to develop on Element you **must** read the [developer guide
|
||||||
for `matrix-react-sdk`](https://github.com/matrix-org/matrix-react-sdk), which
|
for `matrix-react-sdk`](https://github.com/matrix-org/matrix-react-sdk#developer-guide), which
|
||||||
also defines the design, architecture and style for Riot too.
|
also defines the design, architecture and style for Element too.
|
||||||
|
|
||||||
Before starting work on a feature, it's best to ensure your plan aligns well
|
Before starting work on a feature, it's best to ensure your plan aligns well
|
||||||
with our vision for Riot. Please chat with the team in
|
with our vision for Element. Please chat with the team in
|
||||||
[#riot-dev:matrix.org](https://matrix.to/#/#riot-dev:matrix.org) before you
|
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) before you
|
||||||
start so we can ensure it's something we'd be willing to merge.
|
start so we can ensure it's something we'd be willing to merge.
|
||||||
|
|
||||||
You should also familiarise yourself with the ["Here be Dragons" guide
|
You should also familiarise yourself with the ["Here be Dragons" guide
|
||||||
](https://docs.google.com/document/d/12jYzvkidrp1h7liEuLIe6BMdU0NUjndUYI971O06ooM)
|
](https://docs.google.com/document/d/12jYzvkidrp1h7liEuLIe6BMdU0NUjndUYI971O06ooM)
|
||||||
to the tame & not-so-tame dragons (gotchas) which exist in the codebase.
|
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 Element 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.
|
||||||
|
@ -240,15 +256,15 @@ apps using React.
|
||||||
After creating a new component you must run `yarn reskindex` to regenerate
|
After creating a new component you must run `yarn reskindex` to regenerate
|
||||||
the `component-index.js` for the app (used in future for skinning).
|
the `component-index.js` for the app (used in future for skinning).
|
||||||
|
|
||||||
Please note that Riot is intended to run correctly without access to the public
|
Please note that Element 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)
|
||||||
hosted by external CDNs or servers but instead please package all dependencies
|
hosted by external CDNs or servers but instead please package all dependencies
|
||||||
into Riot itself.
|
into Element itself.
|
||||||
|
|
||||||
Setting up a dev environment
|
Setting up a dev environment
|
||||||
============================
|
============================
|
||||||
|
|
||||||
Much of the functionality in Riot is actually in the `matrix-react-sdk` and
|
Much of the functionality in Element is actually in the `matrix-react-sdk` and
|
||||||
`matrix-js-sdk` modules. It is possible to set these up in a way that makes it
|
`matrix-js-sdk` modules. It is possible to set these up in a way that makes it
|
||||||
easy to track the `develop` branches in git and to make local changes without
|
easy to track the `develop` branches in git and to make local changes without
|
||||||
having to manually rebuild each time.
|
having to manually rebuild each time.
|
||||||
|
@ -258,7 +274,6 @@ First clone and build `matrix-js-sdk`:
|
||||||
``` bash
|
``` bash
|
||||||
git clone https://github.com/matrix-org/matrix-js-sdk.git
|
git clone https://github.com/matrix-org/matrix-js-sdk.git
|
||||||
pushd matrix-js-sdk
|
pushd matrix-js-sdk
|
||||||
git checkout develop
|
|
||||||
yarn link
|
yarn link
|
||||||
yarn install
|
yarn install
|
||||||
popd
|
popd
|
||||||
|
@ -269,36 +284,31 @@ Then similarly with `matrix-react-sdk`:
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/matrix-org/matrix-react-sdk.git
|
git clone https://github.com/matrix-org/matrix-react-sdk.git
|
||||||
pushd matrix-react-sdk
|
pushd matrix-react-sdk
|
||||||
git checkout develop
|
|
||||||
yarn link
|
yarn link
|
||||||
yarn link matrix-js-sdk
|
yarn link matrix-js-sdk
|
||||||
yarn install
|
yarn install
|
||||||
popd
|
popd
|
||||||
```
|
```
|
||||||
|
|
||||||
Finally, build and start Riot itself:
|
Finally, build and start Element itself:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
git clone https://github.com/vector-im/riot-web.git
|
git clone https://github.com/vector-im/element-web.git
|
||||||
cd riot-web
|
cd element-web
|
||||||
git checkout develop
|
|
||||||
yarn link matrix-js-sdk
|
yarn link matrix-js-sdk
|
||||||
yarn link matrix-react-sdk
|
yarn link matrix-react-sdk
|
||||||
yarn install
|
yarn install
|
||||||
|
yarn reskindex
|
||||||
yarn start
|
yarn start
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
Wait a few seconds for the initial build to finish; you should see something like:
|
Wait a few seconds for the initial build to finish; you should see something like:
|
||||||
```
|
```
|
||||||
Hash: b0af76309dd56d7275c8
|
[element-js] <s> [webpack.Progress] 100%
|
||||||
Version: webpack 1.12.14
|
[element-js]
|
||||||
Time: 14533ms
|
[element-js] ℹ 「wdm」: 1840 modules
|
||||||
Asset Size Chunks Chunk Names
|
[element-js] ℹ 「wdm」: Compiled successfully.
|
||||||
bundle.js 4.2 MB 0 [emitted] main
|
|
||||||
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
|
||||||
|
@ -307,19 +317,43 @@ bundle.css.map 116 kB 0 [emitted] main
|
||||||
Configure the app by copying `config.sample.json` to `config.json` and
|
Configure the app by copying `config.sample.json` to `config.json` and
|
||||||
modifying it. See the [configuration docs](docs/config.md) for details.
|
modifying it. See the [configuration docs](docs/config.md) for details.
|
||||||
|
|
||||||
Open http://127.0.0.1:8080/ in your browser to see your newly built Riot.
|
Open http://127.0.0.1:8080/ in your browser to see your newly built Element.
|
||||||
|
|
||||||
|
**Note**: The build script uses inotify by default on Linux to monitor directories
|
||||||
|
for changes. If the inotify limits are too low your build will fail silently or with
|
||||||
|
`Error: EMFILE: too many open files`. To avoid these issues, we recommend a watch limit
|
||||||
|
of at least `128M` and instance limit around `512`.
|
||||||
|
|
||||||
|
You may be interested in issues [#15750](https://github.com/vector-im/element-web/issues/15750) and
|
||||||
|
[#15774](https://github.com/vector-im/element-web/issues/15774) for further details.
|
||||||
|
|
||||||
|
To set a new inotify watch and instance limit, execute:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo sysctl fs.inotify.max_user_watches=131072
|
||||||
|
sudo sysctl fs.inotify.max_user_instances=512
|
||||||
|
sudo sysctl -p
|
||||||
|
```
|
||||||
|
|
||||||
|
If you wish, you can make the new limits permanent, by executing:
|
||||||
|
|
||||||
|
```
|
||||||
|
echo fs.inotify.max_user_watches=131072 | sudo tee -a /etc/sysctl.conf
|
||||||
|
echo fs.inotify.max_user_instances=512 | sudo tee -a /etc/sysctl.conf
|
||||||
|
sudo sysctl -p
|
||||||
|
```
|
||||||
|
|
||||||
___
|
___
|
||||||
|
|
||||||
When you make changes to `matrix-react-sdk` or `matrix-js-sdk` they should be
|
When you make changes to `matrix-react-sdk` or `matrix-js-sdk` they should be
|
||||||
automatically picked up by webpack and built.
|
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 Element skin, you will need to rebuild
|
||||||
the skin's index by running, `yarn 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.
|
||||||
You'll need to do this in each new terminal you open before building Riot.
|
You'll need to do this in each new terminal you open before building Element.
|
||||||
|
|
||||||
Running the tests
|
Running the tests
|
||||||
-----------------
|
-----------------
|
||||||
|
@ -351,56 +385,81 @@ To add a new translation, head to the [translating doc](docs/translating.md).
|
||||||
|
|
||||||
For a developer guide, see the [translating dev doc](docs/translating-dev.md).
|
For a developer guide, see the [translating dev doc](docs/translating-dev.md).
|
||||||
|
|
||||||
[<img src="https://translate.riot.im/widgets/riot-web/-/multi-auto.svg" alt="translationsstatus" width="340">](https://translate.riot.im/engage/riot-web/?utm_source=widget)
|
[<img src="https://translate.element.io/widgets/element-web/-/multi-auto.svg" alt="translationsstatus" width="340">](https://translate.element.io/engage/element-web/?utm_source=widget)
|
||||||
|
|
||||||
Triaging issues
|
Triaging issues
|
||||||
===============
|
===============
|
||||||
|
|
||||||
Issues will be triaged by the core team using the below set of tags.
|
We strive to completely cover all applicable issues with these core labels:
|
||||||
|
|
||||||
Tags are meant to be used in combination - e.g.:
|
1. __Type__ — Every issue is assigned a type:
|
||||||
* P1 critical bug == really urgent stuff that should be next in the bugfixing todo list
|
- __[T-Defect](https://github.com/vector-im/element-web/labels/T-Defect):__
|
||||||
* "release blocker" == stuff which is blocking us from cutting the next release.
|
Bugs, crashes, hangs, vulnerabilities, or other reported problems
|
||||||
* P1 feature type:voip == what VoIP features should we be working on next?
|
- __[T-Enhancement](https://github.com/vector-im/element-web/labels/T-Enhancement):__
|
||||||
|
New features, changes in functionality, performance boosts, user-facing
|
||||||
|
improvements
|
||||||
|
- __[T-Task](https://github.com/vector-im/element-web/labels/T-Task):__
|
||||||
|
Refactoring, enabling or disabling functionality, other engineering tasks
|
||||||
|
- __[T-Other](https://github.com/vector-im/element-web/labels/T-Other):__
|
||||||
|
Questions, user support, anything else
|
||||||
|
|
||||||
priority: **compulsory**
|
2. __Severity__ — All issues labeled `T-Defect` are also assigned a severity:
|
||||||
|
* __[S-Critical](https://github.com/vector-im/element-web/labels/S-Critical):__
|
||||||
|
Prevents work, causes data loss, affects many users, and/or has no
|
||||||
|
workaround
|
||||||
|
* __[S-Major](https://github.com/vector-im/element-web/labels/S-Major):__
|
||||||
|
Severely degrades major functionality or product features, with no
|
||||||
|
satisfactory workaround
|
||||||
|
* __[S-Minor](https://github.com/vector-im/element-web/labels/S-Minor):__
|
||||||
|
Impairs non-critical functionality, or suitable workarounds exist
|
||||||
|
* __[S-Tolerable](https://github.com/vector-im/element-web/labels/S-Tolerable):__
|
||||||
|
Purely cosmetic or low / no impact to users
|
||||||
|
|
||||||
* P1: top priority - i.e. pool of stuff which we should be working on next
|
3. __Priority__ — All issues which are not `T-Other` are assigned a priority:
|
||||||
* P2: still need to fix, but lower than P1
|
* __[P1](https://github.com/vector-im/element-web/labels/P1):__ Next
|
||||||
* P3: non-urgent
|
* __[P2](https://github.com/vector-im/element-web/labels/P2):__ Later
|
||||||
* P4: interesting idea - bluesky some day
|
* __[P3](https://github.com/vector-im/element-web/labels/P3):__ Eventually
|
||||||
* P5: recorded for posterity/to avoid duplicates. No intention to resolves right now.
|
* __[P4](https://github.com/vector-im/element-web/labels/P4):__ Interesting —
|
||||||
|
Not yet scheduled, will accept patches
|
||||||
|
* __[P5](https://github.com/vector-im/element-web/labels/P5):__ Dubious —
|
||||||
|
Will not schedule, would consider patches
|
||||||
|
|
||||||
bug or feature: **compulsory**
|
4. __Area__ — Most issues are assigned one or several "areas" using one of the
|
||||||
|
many `A-` prefixed labels, e.g. `A-Composer` or `A-Spaces`. Each area label
|
||||||
|
maps to a group of features or portion of the UI surface in the app.
|
||||||
|
|
||||||
* bug
|
### Other common labels
|
||||||
* feature
|
|
||||||
|
|
||||||
bug severity: **compulsory, if bug**
|
We have a handful of other labels which are added on an as-needed basis, and not expected to be exhaustive:
|
||||||
|
|
||||||
* critical - whole app doesn't work
|
* __Exceptions__ — Special flags for issues and pull requests:
|
||||||
* major - entire feature doesn't work
|
* __[X-Needs-Info](https://github.com/vector-im/element-web/labels/X-Needs-Info):__
|
||||||
* minor - partially broken feature (but still usable)
|
This issue is blocked pending further information from the reporter
|
||||||
* cosmetic - feature works functionally but UI/UX is broken
|
* __[X-Regression](https://github.com/vector-im/element-web/labels/X-Regression):__
|
||||||
|
Denotes things breaking which previously worked
|
||||||
|
* __[X-Release-Blocker](https://github.com/vector-im/element-web/labels/X-Release-Blocker):__
|
||||||
|
Issues which must be resolved before making a release
|
||||||
|
|
||||||
types
|
* __[Easy](https://github.com/vector-im/element-web/labels/Easy)__ / __[Help
|
||||||
* type:* - refers to a particular part of the app; used to filter bugs
|
Wanted](https://github.com/vector-im/element-web/labels/Help%20Wanted)__ —
|
||||||
on a given topic - e.g. VOIP, signup, timeline, etc.
|
Well-defined issues which are suitable for folks new to the codebase
|
||||||
|
|
||||||
additional categories (self-explanatory):
|
* __[A11y](https://github.com/vector-im/element-web/labels/A11y)__ /
|
||||||
|
__[Meta](https://github.com/vector-im/element-web/labels/Meta)__ /
|
||||||
|
__[I18n](https://github.com/vector-im/element-web/labels/I18n)__ /
|
||||||
|
__[Privacy](https://github.com/vector-im/element-web/labels/Privacy)__ /
|
||||||
|
__[Security](https://github.com/vector-im/element-web/labels/Security)__ —
|
||||||
|
Issues which fall under these conceptual themes (which apply to many software
|
||||||
|
projects and are not specific to Element)
|
||||||
|
|
||||||
* release blocker
|
* __[Sponsored](https://github.com/vector-im/element-web/labels/Sponsored)__ —
|
||||||
* ui/ux (think of this as cosmetic)
|
Used internally by Element to denote issues with external funding
|
||||||
* network (specific to network conditions)
|
|
||||||
* platform specific
|
|
||||||
* accessibility
|
|
||||||
* maintenance
|
|
||||||
* performance
|
|
||||||
* i18n
|
|
||||||
* blocked - whether this issue currently can't be progressed due to outside factors
|
|
||||||
|
|
||||||
community engagement
|
### Ad hoc labels (`Z-`)
|
||||||
* easy
|
|
||||||
* hacktoberfest
|
We have reserved the `Z-` prefix for ad hoc labels.
|
||||||
* bounty? - proposal to be included in a bounty programme
|
|
||||||
* bounty - included in Status Open Bounty
|
Any member of the core team is welcome to create labels beginning with `Z-` for
|
||||||
|
any purpose, such as tracking personal areas of interest or providing a common
|
||||||
|
way to label cross-repo initiatives. The prefix avoids interference with the
|
||||||
|
project's main labels.
|
||||||
|
|
1
__mocks__/cssMock.js
Normal file
|
@ -0,0 +1 @@
|
||||||
|
module.exports = "css-file-stub";
|
|
@ -3,12 +3,14 @@ module.exports = {
|
||||||
"presets": [
|
"presets": [
|
||||||
["@babel/preset-env", {
|
["@babel/preset-env", {
|
||||||
"targets": [
|
"targets": [
|
||||||
"last 2 Chrome versions", "last 2 Firefox versions", "last 2 Safari versions"
|
"last 2 Chrome versions",
|
||||||
|
"last 2 Firefox versions",
|
||||||
|
"last 2 Safari versions",
|
||||||
|
"last 2 Edge versions",
|
||||||
],
|
],
|
||||||
}],
|
}],
|
||||||
"@babel/preset-typescript",
|
"@babel/preset-typescript",
|
||||||
"@babel/preset-flow",
|
"@babel/preset-react",
|
||||||
"@babel/preset-react"
|
|
||||||
],
|
],
|
||||||
"plugins": [
|
"plugins": [
|
||||||
["@babel/plugin-proposal-decorators", {legacy: true}],
|
["@babel/plugin-proposal-decorators", {legacy: true}],
|
||||||
|
@ -16,8 +18,9 @@ module.exports = {
|
||||||
"@babel/plugin-proposal-numeric-separator",
|
"@babel/plugin-proposal-numeric-separator",
|
||||||
"@babel/plugin-proposal-class-properties",
|
"@babel/plugin-proposal-class-properties",
|
||||||
"@babel/plugin-proposal-object-rest-spread",
|
"@babel/plugin-proposal-object-rest-spread",
|
||||||
"@babel/plugin-transform-flow-comments",
|
"@babel/plugin-proposal-optional-chaining",
|
||||||
|
"@babel/plugin-proposal-nullish-coalescing-operator",
|
||||||
"@babel/plugin-syntax-dynamic-import",
|
"@babel/plugin-syntax-dynamic-import",
|
||||||
"@babel/plugin-transform-runtime"
|
"@babel/plugin-transform-runtime",
|
||||||
]
|
],
|
||||||
};
|
};
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
"disable_guests": false,
|
"disable_guests": false,
|
||||||
"disable_login_language_selector": false,
|
"disable_login_language_selector": false,
|
||||||
"disable_3pid_login": false,
|
"disable_3pid_login": false,
|
||||||
"brand": "Riot",
|
"brand": "Element",
|
||||||
"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": [
|
||||||
|
@ -22,15 +22,10 @@
|
||||||
"https://scalar-staging.vector.im/api",
|
"https://scalar-staging.vector.im/api",
|
||||||
"https://scalar-staging.riot.im/scalar/api"
|
"https://scalar-staging.riot.im/scalar/api"
|
||||||
],
|
],
|
||||||
"bug_report_endpoint_url": "https://riot.im/bugreports/submit",
|
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||||
"defaultCountryCode": "GB",
|
"defaultCountryCode": "GB",
|
||||||
"showLabsSettings": false,
|
"showLabsSettings": false,
|
||||||
"features": {
|
"features": { },
|
||||||
"feature_pinning": "labs",
|
|
||||||
"feature_custom_status": "labs",
|
|
||||||
"feature_custom_tags": "labs",
|
|
||||||
"feature_state_counters": "labs"
|
|
||||||
},
|
|
||||||
"default_federate": true,
|
"default_federate": true,
|
||||||
"default_theme": "light",
|
"default_theme": "light",
|
||||||
"roomDirectory": {
|
"roomDirectory": {
|
||||||
|
@ -38,7 +33,6 @@
|
||||||
"matrix.org"
|
"matrix.org"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"welcomeUserId": "@riot-bot:matrix.org",
|
|
||||||
"piwik": {
|
"piwik": {
|
||||||
"url": "https://piwik.riot.im/",
|
"url": "https://piwik.riot.im/",
|
||||||
"whitelistedHSUrls": ["https://matrix.org"],
|
"whitelistedHSUrls": ["https://matrix.org"],
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "Riot",
|
"name": "Element",
|
||||||
"description": "A glossy Matrix collaboration client for the web.",
|
"description": "A glossy Matrix collaboration client for the web.",
|
||||||
"repository": {
|
"repository": {
|
||||||
"url": "https://github.com/vector-im/riot-web",
|
"url": "https://github.com/vector-im/element-web",
|
||||||
"license": "Apache License 2.0"
|
"license": "Apache License 2.0"
|
||||||
},
|
},
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"list": "https://github.com/vector-im/riot-web/issues",
|
"list": "https://github.com/vector-im/element-web/issues",
|
||||||
"report": "https://github.com/vector-im/riot-web/issues/new/choose"
|
"report": "https://github.com/vector-im/element-web/issues/new/choose"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"chat",
|
"chat",
|
||||||
|
|
81
docs/app-load.md
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
# App load order
|
||||||
|
|
||||||
|
Old slow flow:
|
||||||
|
![image](https://user-images.githubusercontent.com/2403652/73848963-00a2a080-4821-11ea-97d4-1200fc2638f3.png)
|
||||||
|
|
||||||
|
Current more parallel flow:
|
||||||
|
![image](https://user-images.githubusercontent.com/2403652/83146440-303a2900-a0ee-11ea-806b-4f53f039b957.png)
|
||||||
|
|
||||||
|
<details><summary>Code</summary>
|
||||||
|
<p>
|
||||||
|
<pre><code>
|
||||||
|
digraph G {
|
||||||
|
node [shape=box];
|
||||||
|
|
||||||
|
subgraph cluster_0 {
|
||||||
|
color=orange;
|
||||||
|
node [style=filled];
|
||||||
|
label = "index.ts";
|
||||||
|
|
||||||
|
entrypoint, s0, ready [shape=point];
|
||||||
|
rageshake, config, i18n, theme, skin, olm [shape=parallelogram];
|
||||||
|
mobile [shape=diamond, label="mobile"];
|
||||||
|
modernizr [shape=diamond];
|
||||||
|
redirect, incompatible [shape=egg];
|
||||||
|
|
||||||
|
entrypoint -> rageshake;
|
||||||
|
rageshake -> mobile [color=blue];
|
||||||
|
mobile -> s0 [label="No"];
|
||||||
|
mobile -> redirect [label="Yes"];
|
||||||
|
|
||||||
|
s0 -> platform;
|
||||||
|
s0 -> olm;
|
||||||
|
platform -> config;
|
||||||
|
|
||||||
|
config -> i18n [color=blue];
|
||||||
|
config -> theme [color=blue];
|
||||||
|
config -> skin [color=blue];
|
||||||
|
|
||||||
|
i18n -> modernizr [color=blue];
|
||||||
|
theme -> modernizr [color=blue];
|
||||||
|
skin -> modernizr [color=blue];
|
||||||
|
|
||||||
|
modernizr -> ready [label="Yes"];
|
||||||
|
modernizr -> incompatible [label="No"];
|
||||||
|
incompatible -> ready [label="user ignore"];
|
||||||
|
|
||||||
|
olm -> ready [color=red];
|
||||||
|
config -> ready [color=red];
|
||||||
|
skin -> ready [color=red];
|
||||||
|
theme -> ready [color=red];
|
||||||
|
i18n -> ready [color=red];
|
||||||
|
}
|
||||||
|
|
||||||
|
subgraph cluster_1 {
|
||||||
|
color = green;
|
||||||
|
node [style=filled];
|
||||||
|
label = "init.tsx";
|
||||||
|
|
||||||
|
ready -> loadApp;
|
||||||
|
loadApp -> matrixchat;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</code></pre>
|
||||||
|
</p>
|
||||||
|
</details>
|
||||||
|
|
||||||
|
Key:
|
||||||
|
+ Parallelogram: async/await task
|
||||||
|
+ Box: sync task
|
||||||
|
+ Diamond: conditional branch
|
||||||
|
+ Egg: user interaction
|
||||||
|
+ Blue arrow: async task is allowed to settle but allowed to fail
|
||||||
|
+ Red arrow: async task success is asserted
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
+ A task begins when all its dependencies (arrows going into it) are fulfilled.
|
||||||
|
+ The success of setting up rageshake is never asserted, element-web has a fallback path for running without IDB (and thus rageshake).
|
||||||
|
+ Everything is awaited to be settled before the Modernizr check, to allow it to make use of things like i18n if they are successful.
|
||||||
|
|
||||||
|
Underlying dependencies:
|
||||||
|
![image](https://user-images.githubusercontent.com/2403652/73848977-08624500-4821-11ea-9830-bb0317c41086.png)
|
|
@ -1,52 +0,0 @@
|
||||||
# VoIP Conferencing
|
|
||||||
|
|
||||||
This is a draft proposal for a naive voice/video conferencing implementation for
|
|
||||||
Matrix clients. There are many possible conferencing architectures possible for
|
|
||||||
Matrix (Multipoint Conferencing Unit (MCU); Stream Forwarding Unit (SFU); Peer-
|
|
||||||
to-Peer mesh (P2P), etc; events shared in the group room; events shared 1:1;
|
|
||||||
possibly even out-of-band signalling).
|
|
||||||
|
|
||||||
This is a starting point for a naive MCU implementation which could provide one
|
|
||||||
possible Matrix-wide solution in future, which retains backwards compatibility
|
|
||||||
with standard 1:1 calling.
|
|
||||||
|
|
||||||
* A client chooses to initiate a conference for a given room by starting a
|
|
||||||
voice or video call with a 'conference focus' user. This is a virtual user
|
|
||||||
(typically Application Service) which implements a conferencing bridge. It
|
|
||||||
isn't defined how the client discovers or selects this user.
|
|
||||||
|
|
||||||
* The conference focus user MUST join the room in which the client has
|
|
||||||
initiated the conference - this may require the client to invite the
|
|
||||||
conference focus user to the room, depending on the room's `join_rules`. The
|
|
||||||
conference focus user needs to be in the room to let the bridge eject users
|
|
||||||
from the conference who have left the room in which it was initiated, and aid
|
|
||||||
discovery of the conference by other users in the room. The bridge
|
|
||||||
identifies the room to join based on the user ID by which it was invited.
|
|
||||||
The format of this identifier is implementation dependent for now.
|
|
||||||
|
|
||||||
* If a client leaves the group chat room, they MUST be ejected from the
|
|
||||||
conference. If a client leaves the 1:1 room with the conference focus user,
|
|
||||||
they SHOULD be ejected from the conference.
|
|
||||||
|
|
||||||
* For now, rooms can contain multiple conference focus users - it's left to
|
|
||||||
user or client implementation to select which to converge on. In future this
|
|
||||||
could be mediated using a state event (e.g. `im.vector.call.mcu`), but we
|
|
||||||
can't do that right now as by default normal users can't set arbitrary state
|
|
||||||
events on a room.
|
|
||||||
|
|
||||||
* To participate in the conference, other clients initiates a standard 1:1
|
|
||||||
voice or video call to the conference focus user.
|
|
||||||
|
|
||||||
* For best UX, clients SHOULD show the ongoing voice/video call in the UI
|
|
||||||
context of the group room rather than 1:1 with the focus user. If a client
|
|
||||||
recognises a conference user present in the room, it MAY chose to highlight
|
|
||||||
this in the UI (e.g. with a "conference ongoing" notification, to aid
|
|
||||||
discovery). Clients MAY hide the 1:1 room with the focus user (although in
|
|
||||||
future this room could be used for floor control or other direct
|
|
||||||
communication with the conference focus)
|
|
||||||
|
|
||||||
* When all users have left the conference, the 'conference focus' user SHOULD
|
|
||||||
leave the room.
|
|
||||||
|
|
||||||
* If a conference focus user joins a room but does not receive a 1:1 voice or
|
|
||||||
video call, it SHOULD time out after a period of time and leave the room.
|
|
151
docs/config.md
|
@ -4,13 +4,13 @@ Configuration
|
||||||
You can configure the app by copying `config.sample.json` to
|
You can configure the app by copying `config.sample.json` to
|
||||||
`config.json` and customising it:
|
`config.json` and customising it:
|
||||||
|
|
||||||
For a good example, see https://riot.im/develop/config.json.
|
For a good example, see https://develop.element.io/config.json.
|
||||||
|
|
||||||
1. `default_server_config` sets the default homeserver and identity server URL for
|
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),
|
Element 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
|
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`
|
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
|
instead which is where Element 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.
|
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
|
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.
|
whereas the `server_name` in the `default_server_config` is for display purposes only.
|
||||||
|
@ -18,21 +18,24 @@ For a good example, see https://riot.im/develop/config.json.
|
||||||
`default_is_url`, however these are deprecated. They are maintained for backwards
|
`default_is_url`, however these are deprecated. They are maintained for backwards
|
||||||
compatibility with older configurations. `default_is_url` is respected only
|
compatibility with older configurations. `default_is_url` is respected only
|
||||||
if `default_hs_url` is used.
|
if `default_hs_url` is used.
|
||||||
* Riot will fail to load if a mix of `default_server_config`, `default_server_name`, or
|
* Element 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
|
`default_hs_url` is specified. When multiple sources are specified, it is unclear
|
||||||
which should take priority and therefore the application cannot continue.
|
which should take priority and therefore the application cannot continue.
|
||||||
* As of Riot 1.4.0, identity servers are optional. See [Identity servers](#identity-servers) below.
|
* As of Element 1.4.0, identity servers are optional. See [Identity servers](#identity-servers) below.
|
||||||
1. `features`: Lookup of optional features that may be `enable`d, `disable`d, or
|
1. `sso_immediate_redirect`: When `true`, Element will assume the default server supports SSO
|
||||||
exposed to the user in the `labs` section of settings. The available
|
and attempt to send the user there to continue (if they aren't already logged in). Default
|
||||||
optional experimental features vary from release to release and are [documented](labs.md). The feature flag process is
|
`false`. Note that this disables all usage of the welcome page.
|
||||||
[documented](feature-flags.md) as well.
|
1. `features`: Lookup of optional features that may be force-enabled (`true`) or force-disabled (`false`).
|
||||||
1. `showLabsSettings`: Shows the "labs" tab of user settings even when no `features` are enabled
|
When features are not listed here, their defaults will be used, and users can turn them on/off if `showLabsSettings`
|
||||||
or present. Useful for getting at settings which may be otherwise hidden.
|
allows them to. The available optional experimental features vary from release to release and are
|
||||||
|
[documented](labs.md). The feature flag process is [documented](feature-flags.md) as well.
|
||||||
|
1. `showLabsSettings`: Shows the "labs" tab of user settings. Useful to allow users to turn on experimental features
|
||||||
|
they might not otherwise have access to.
|
||||||
1. `brand`: String to pass to your homeserver when configuring email notifications, to let the
|
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.
|
homeserver know what email template to use when talking to you.
|
||||||
1. `branding`: Configures various branding and logo details, such as:
|
1. `branding`: Configures various branding and logo details, such as:
|
||||||
1. `welcomeBackgroundUrl`: An image to use as a wallpaper outside the app
|
1. `welcomeBackgroundUrl`: An image to use as a wallpaper outside the app
|
||||||
during authentication flows
|
during authentication flows. If an array is passed, an image is chosen randomly for each visit.
|
||||||
1. `authHeaderLogoUrl`: An logo image that is shown in the header during
|
1. `authHeaderLogoUrl`: An logo image that is shown in the header during
|
||||||
authentication flows
|
authentication flows
|
||||||
1. `authFooterLinks`: a list of links to show in the authentication page footer:
|
1. `authFooterLinks`: a list of links to show in the authentication page footer:
|
||||||
|
@ -42,13 +45,13 @@ For a good example, see https://riot.im/develop/config.json.
|
||||||
1. `adminMessageMD`: An extra message to show on the reporting dialog to
|
1. `adminMessageMD`: An extra message to show on the reporting dialog to
|
||||||
mention homeserver-specific policies. Accepts Markdown.
|
mention homeserver-specific policies. Accepts Markdown.
|
||||||
1. `integrations_ui_url`: URL to the web interface for the integrations server. The integrations
|
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
|
server is not Element and normally not your homeserver either. The integration server settings
|
||||||
may be left blank to disable integrations.
|
may be left blank to disable integrations.
|
||||||
1. `integrations_rest_url`: URL to the REST interface for the integrations server.
|
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. `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
|
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
|
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
|
"Send Logs" within the application. Bug reports can be disabled/hidden by leaving the
|
||||||
`bug_report_endpoint_url` out of your config file.
|
`bug_report_endpoint_url` out of your config file.
|
||||||
1. `roomDirectory`: config for the public room directory. This section is optional.
|
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
|
1. `roomDirectory.servers`: List of other homeservers' directories to include in the drop
|
||||||
|
@ -65,13 +68,16 @@ For a good example, see https://riot.im/develop/config.json.
|
||||||
1. `whitelistedISUrls`: a list of IS 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. `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. `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
|
1. `embeddedPages`: Configures the pages displayed in portions of Element that
|
||||||
embed static files, such as:
|
embed static files, such as:
|
||||||
1. `welcomeUrl`: Initial content shown on the outside of the app when not
|
1. `welcomeUrl`: Initial content shown on the outside of the app when not
|
||||||
logged in. Defaults to `welcome.html` supplied with Riot.
|
logged in. Defaults to `welcome.html` supplied with Element.
|
||||||
1. `homeUrl`: Content shown on the inside of the app when a specific room is
|
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
|
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.
|
button to access it will be shown in the top left menu.
|
||||||
|
1. `loginForWelcome`: Overrides `welcomeUrl` to make the welcome page be the
|
||||||
|
same page as the login page when `true`. This effectively disables the
|
||||||
|
welcome page.
|
||||||
1. `defaultCountryCode`: The ISO 3166 alpha2 country code to use when showing
|
1. `defaultCountryCode`: The ISO 3166 alpha2 country code to use when showing
|
||||||
country selectors, like the phone number input on the registration page.
|
country selectors, like the phone number input on the registration page.
|
||||||
Defaults to `GB` if the given code is unknown or not provided.
|
Defaults to `GB` if the given code is unknown or not provided.
|
||||||
|
@ -80,25 +86,66 @@ For a good example, see https://riot.im/develop/config.json.
|
||||||
is special cased to the `default_theme` in the config file).
|
is special cased to the `default_theme` in the config file).
|
||||||
1. `disable_custom_urls`: disallow the user to change the
|
1. `disable_custom_urls`: disallow the user to change the
|
||||||
default homeserver when signing up or logging in.
|
default homeserver when signing up or logging in.
|
||||||
1. `permalinkPrefix`: Used to change the URL that Riot generates permalinks with.
|
1. `permalinkPrefix`: Used to change the URL that Element generates permalinks with.
|
||||||
By default, this is "https://matrix.to" to generate matrix.to (spec) permalinks.
|
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:
|
Set this to your Element instance URL if you run an unfederated server (eg:
|
||||||
"https://riot.example.org").
|
"https://element.example.org").
|
||||||
1. `jitsi`: Used to change the default conference options. Learn more about the
|
1. `jitsi`: Used to change the default conference options. Learn more about the
|
||||||
Jitsi options at [jitsi.md](./jitsi.md).
|
Jitsi options at [jitsi.md](./jitsi.md).
|
||||||
1. `preferredDomain`: The domain name of the preferred Jitsi instance. Defaults
|
1. `preferredDomain`: The domain name of the preferred Jitsi instance. Defaults
|
||||||
to `jitsi.riot.im`. This is used whenever a user clicks on the voice/video
|
to `jitsi.riot.im`. This is used whenever a user clicks on the voice/video
|
||||||
call buttons - integration managers may use a different domain.
|
call buttons - integration managers may use a different domain.
|
||||||
|
1. `enable_presence_by_hs_url`: The property key should be the URL of the homeserver
|
||||||
|
and its value defines whether to enable/disable the presence status display
|
||||||
|
from that homeserver. If no options are configured, presence is shown for all
|
||||||
|
homeservers.
|
||||||
|
1. `disable_guests`: Disables guest access tokens and auto-guest registrations.
|
||||||
|
Defaults to false (guests are allowed).
|
||||||
|
1. `disable_login_language_selector`: Disables the login language selector. Defaults
|
||||||
|
to false (language selector is shown).
|
||||||
|
1. `disable_3pid_login`: Disables 3rd party identity options on login and registration form
|
||||||
|
Defaults to false (3rd party identity options are shown).
|
||||||
|
1. `default_federate`: Default option for room federation when creating a room
|
||||||
|
Defaults to true (room federation enabled).
|
||||||
|
1. `desktopBuilds`: Used to alter promotional links to the desktop app. By default
|
||||||
|
the builds are considered available and accessible from https://element.io. This
|
||||||
|
config option is typically used in the context of encouraging encrypted message
|
||||||
|
search capabilities (Seshat). All the options listed below are required if this
|
||||||
|
option is specified.
|
||||||
|
1. `available`: When false, the desktop app will not be promoted to the user.
|
||||||
|
1. `logo`: An HTTP URL to the avatar for the desktop build. Should be 24x24, ideally
|
||||||
|
an SVG.
|
||||||
|
1. `url`: An HTTP URL for where to send the user to download the desktop build.
|
||||||
|
1. `mobileBuilds`: Used to alter promotional links to the mobile app. By default the
|
||||||
|
builds are considered available and accessible from https://element.io. This config
|
||||||
|
option is typically used in a context of encouraging the user to try the mobile app
|
||||||
|
instead of a mobile/incompatible browser.
|
||||||
|
1. `ios`: The URL to the iOS build. If `null`, it will be assumed to be not available.
|
||||||
|
If not set, the default element.io builds will be used.
|
||||||
|
1. `android`: The URL to the Android build. If `null`, it will be assumed to be not available.
|
||||||
|
If not set, the default element.io builds will be used.
|
||||||
|
1. `fdroid`: The URL to the FDroid build. If `null`, it will be assumed to be not available.
|
||||||
|
If not set, the default element.io builds will be used.
|
||||||
|
1. `mobileGuideToast`: Whether to show a toast a startup which nudges users on
|
||||||
|
iOS and Android towards the native mobile apps. The toast redirects to the
|
||||||
|
mobile guide if they accept. Defaults to false.
|
||||||
|
1. `audioStreamUrl`: If supplied, show an option on Jitsi widgets to stream
|
||||||
|
audio using Jitsi's live streaming feature. This option is experimental and
|
||||||
|
may be removed at any time without notice.
|
||||||
|
1. `voip`: Behaviour related to calls
|
||||||
|
1. `obeyAssertedIdentity`: If set, MSC3086 asserted identity messages sent
|
||||||
|
on VoIP calls will cause the call to appear in the room corresponding to the
|
||||||
|
asserted identity. This *must* only be set in trusted environments.
|
||||||
|
|
||||||
Note that `index.html` also has an og:image meta tag that is set to an image
|
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
|
hosted on riot.im. This is the image used if links to your copy of Element
|
||||||
appear in some websites like Facebook, and indeed Riot itself. This has to be
|
appear in some websites like Facebook, and indeed Element itself. This has to be
|
||||||
static in the HTML and an absolute URL (and HTTP rather than HTTPS), so it's
|
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
|
not possible for this to be an option in config.json. If you'd like to change
|
||||||
it, you can build Riot, but run
|
it, you can build Element, but run
|
||||||
`RIOT_OG_IMAGE_URL="http://example.com/logo.png" yarn build`.
|
`RIOT_OG_IMAGE_URL="http://example.com/logo.png" yarn build`.
|
||||||
Alternatively, you can edit the `og:image` meta tag in `index.html` directly
|
Alternatively, you can edit the `og:image` meta tag in `index.html` directly
|
||||||
each time you download a new version of Riot.
|
each time you download a new version of Element.
|
||||||
|
|
||||||
Identity servers
|
Identity servers
|
||||||
================
|
================
|
||||||
|
@ -107,10 +154,10 @@ The identity server is used for inviting other users to a room via third party
|
||||||
identifiers like emails and phone numbers. It is not used to store your password
|
identifiers like emails and phone numbers. It is not used to store your password
|
||||||
or account information.
|
or account information.
|
||||||
|
|
||||||
As of Riot 1.4.0, all identity server functions are optional and you are
|
As of Element 1.4.0, all identity server functions are optional and you are
|
||||||
prompted to agree to terms before data is sent to the identity server.
|
prompted to agree to terms before data is sent to the identity server.
|
||||||
|
|
||||||
Riot will check multiple sources when looking for an identity server to use in
|
Element will check multiple sources when looking for an identity server to use in
|
||||||
the following order of preference:
|
the following order of preference:
|
||||||
|
|
||||||
1. The identity server set in the user's account data
|
1. The identity server set in the user's account data
|
||||||
|
@ -120,28 +167,56 @@ the following order of preference:
|
||||||
login
|
login
|
||||||
3. The identity server provided by the Riot config file
|
3. The identity server provided by the Riot config file
|
||||||
|
|
||||||
If none of these sources have an identity server set, then Riot will prompt the
|
If none of these sources have an identity server set, then Element will prompt the
|
||||||
user to set an identity server first when attempting to use features that
|
user to set an identity server first when attempting to use features that
|
||||||
require one.
|
require one.
|
||||||
|
|
||||||
Currently the only two public identity servers are https://vector.im and
|
Currently, the only two public identity servers are https://vector.im and
|
||||||
https://matrix.org, however in the future identity servers will be
|
https://matrix.org, however in the future identity servers will be
|
||||||
decentralised.
|
decentralised.
|
||||||
|
|
||||||
Desktop app configuration
|
Desktop app configuration
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
To run multiple instances of the desktop app for different accounts, you can
|
See https://github.com/vector-im/element-desktop#user-specified-configjson
|
||||||
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
|
UI Features
|
||||||
`--profile-dir` flag followed by the desired path.
|
===========
|
||||||
|
|
||||||
+ `%APPDATA%\$NAME\config.json` on Windows
|
Parts of the UI can be disabled using UI features. These are settings which appear
|
||||||
+ `$XDG_CONFIG_HOME\$NAME\config.json` or `~/.config/$NAME/config.json` on Linux
|
under `settingDefaults` and can only be `true` (default) or `false`. When `false`,
|
||||||
+ `~Library/Application Support/$NAME/config.json` on macOS
|
parts of the UI relating to that feature will be disabled regardless of the user's
|
||||||
|
preferences.
|
||||||
|
|
||||||
In the paths above, `$NAME` is typically `Riot`, unless you use `--profile
|
Currently, the following UI feature flags are supported:
|
||||||
$PROFILE` in which case it becomes `Riot-$PROFILE`.
|
|
||||||
|
* `UIFeature.urlPreviews` - Whether URL previews are enabled across the entire application.
|
||||||
|
* `UIFeature.feedback` - Whether prompts to supply feedback are shown.
|
||||||
|
* `UIFeature.voip` - Whether or not VoIP is shown readily to the user. When disabled,
|
||||||
|
Jitsi widgets will still work though they cannot easily be added.
|
||||||
|
* `UIFeature.widgets` - Whether or not widgets will be shown.
|
||||||
|
* `UIFeature.flair` - Whether or not community flair is shown in rooms.
|
||||||
|
* `UIFeature.communities` - Whether or not to show any UI related to communities. Implicitly
|
||||||
|
disables `UIFeature.flair` when disabled.
|
||||||
|
* `UIFeature.advancedSettings` - Whether or not sections titled "advanced" in room and
|
||||||
|
user settings are shown to the user.
|
||||||
|
* `UIFeature.shareQrCode` - Whether or not the QR code on the share room/event dialog
|
||||||
|
is shown.
|
||||||
|
* `UIFeature.shareSocial` - Whether or not the social icons on the share room/event dialog
|
||||||
|
are shown.
|
||||||
|
* `UIFeature.identityServer` - Whether or not functionality requiring an identity server
|
||||||
|
is shown. When disabled, the user will not be able to interact with the identity
|
||||||
|
server (sharing email addresses, 3PID invites, etc).
|
||||||
|
* `UIFeature.thirdPartyId` - Whether or not UI relating to third party identifiers (3PIDs)
|
||||||
|
is shown. Typically this is considered "contact information" on the homeserver, and is
|
||||||
|
not directly related to the identity server.
|
||||||
|
* `UIFeature.registration` - Whether or not the registration page is accessible. Typically
|
||||||
|
useful if accounts are managed externally.
|
||||||
|
* `UIFeature.passwordReset` - Whether or not the password reset page is accessible. Typically
|
||||||
|
useful if accounts are managed externally.
|
||||||
|
* `UIFeature.deactivate` - Whether or not the deactivate account button is accessible. Typically
|
||||||
|
useful if accounts are managed externally.
|
||||||
|
* `UIFeature.advancedEncryption` - Whether or not advanced encryption options are shown to the
|
||||||
|
user.
|
||||||
|
* `UIFeature.roomHistorySettings` - Whether or not the room history settings are shown to the user.
|
||||||
|
This should only be used if the room history visibility options are managed by the server.
|
||||||
|
|
34
docs/customisations.md
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
# Customisations
|
||||||
|
|
||||||
|
Element Web and the React SDK support "customisation points" that can be used to
|
||||||
|
easily add custom logic specific to a particular deployment of Element Web.
|
||||||
|
|
||||||
|
An example of this is the [security customisations
|
||||||
|
module](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/customisations/Security.ts).
|
||||||
|
This module in the React SDK only defines some empty functions and their types:
|
||||||
|
it does not do anything by default.
|
||||||
|
|
||||||
|
To make use of these customisation points, you will first need to fork Element
|
||||||
|
Web so that you can add your own code. Even though the default module is part of
|
||||||
|
the React SDK, you can still override it from the Element Web layer:
|
||||||
|
|
||||||
|
1. Copy the default customisation module to
|
||||||
|
`element-web/src/customisations/YourNameSecurity.ts`
|
||||||
|
2. Edit customisations points and make sure export the ones you actually want to
|
||||||
|
activate
|
||||||
|
3. Tweak the Element build process to use the customised module instead of the
|
||||||
|
default by adding this to the `additionalPlugins` array in `webpack.config.js`:
|
||||||
|
|
||||||
|
```js
|
||||||
|
new webpack.NormalModuleReplacementPlugin(
|
||||||
|
/src[\/\\]customisations[\/\\]Security\.ts/,
|
||||||
|
path.resolve(__dirname, 'src/customisations/YourNameSecurity.ts'),
|
||||||
|
),
|
||||||
|
```
|
||||||
|
|
||||||
|
If we add more customisation modules in the future, we'll likely improve these
|
||||||
|
steps to remove the need for build changes like the above.
|
||||||
|
|
||||||
|
By isolating customisations to their own module, this approach should remove the
|
||||||
|
chance of merge conflicts when updating your fork, and thus simplify ongoing
|
||||||
|
maintenance.
|
63
docs/e2ee.md
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
# End to end encryption by default
|
||||||
|
|
||||||
|
By default, Element will create encrypted DM rooms if the user you are chatting with has keys uploaded on their account.
|
||||||
|
For private room creation, Element will default to encryption on but give you the choice to opt-out.
|
||||||
|
|
||||||
|
## Disabling encryption by default
|
||||||
|
|
||||||
|
Set the following on your homeserver's
|
||||||
|
`/.well-known/matrix/client` config:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"io.element.e2ee": {
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Secure backup
|
||||||
|
|
||||||
|
By default, Element strongly encourages (but does not require) users to set up
|
||||||
|
Secure Backup so that cross-signing identity key and message keys can be
|
||||||
|
recovered in case of a disaster where you lose access to all active devices.
|
||||||
|
|
||||||
|
## Requiring secure backup
|
||||||
|
|
||||||
|
To require Secure Backup to be configured before Element can be used, set the
|
||||||
|
following on your homeserver's `/.well-known/matrix/client` config:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"io.element.e2ee": {
|
||||||
|
"secure_backup_required": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Preferring setup methods
|
||||||
|
|
||||||
|
By default, Element offers users a choice of a random key or user-chosen
|
||||||
|
passphrase when setting up Secure Backup. If a homeserver admin would like to
|
||||||
|
only offer one of these, you can signal this via the
|
||||||
|
`/.well-known/matrix/client` config, for example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"io.element.e2ee": {
|
||||||
|
"secure_backup_setup_methods": ["passphrase"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The field `secure_backup_setup_methods` is an array listing the methods the
|
||||||
|
client should display. Supported values currently include `key` and
|
||||||
|
`passphrase`. If the `secure_backup_setup_methods` field is not present or
|
||||||
|
exists but does not contain any supported methods, Element will fallback to the
|
||||||
|
default value of: `["key", "passphrase"]`.
|
||||||
|
|
||||||
|
# Compatibility
|
||||||
|
|
||||||
|
The settings above were first proposed under a `im.vector.riot.e2ee` key, which
|
||||||
|
is now deprecated. Element will check for either key, preferring
|
||||||
|
`io.element.e2ee` if both exist.
|
|
@ -1,6 +1,6 @@
|
||||||
# Feature flags
|
# Feature flags
|
||||||
|
|
||||||
When developing new features for Riot, we use feature flags to give us more
|
When developing new features for Element, we use feature flags to give us more
|
||||||
flexibility and control over when and where those features are enabled.
|
flexibility and control over when and where those features are enabled.
|
||||||
|
|
||||||
For example, flags make the following things possible:
|
For example, flags make the following things possible:
|
||||||
|
@ -8,7 +8,7 @@ For example, flags make the following things possible:
|
||||||
* Extended testing of a feature via labs on develop
|
* Extended testing of a feature via labs on develop
|
||||||
* Enabling features when ready instead of the first moment the code is released
|
* Enabling features when ready instead of the first moment the code is released
|
||||||
* Testing a feature with a specific set of users (by enabling only on a specific
|
* Testing a feature with a specific set of users (by enabling only on a specific
|
||||||
Riot instance)
|
Element instance)
|
||||||
|
|
||||||
The size of the feature controlled by a feature flag may vary widely: it could
|
The size of the feature controlled by a feature flag may vary widely: it could
|
||||||
be a large project like reactions or a smaller change to an existing algorithm.
|
be a large project like reactions or a smaller change to an existing algorithm.
|
||||||
|
@ -35,7 +35,7 @@ clients commit to doing the associated clean up work once a feature stabilises.
|
||||||
When starting work on a feature, we should create a matching feature flag:
|
When starting work on a feature, we should create a matching feature flag:
|
||||||
|
|
||||||
1. Add a new
|
1. Add a new
|
||||||
[setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.js)
|
[setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.ts)
|
||||||
of the form:
|
of the form:
|
||||||
```js
|
```js
|
||||||
"feature_cats": {
|
"feature_cats": {
|
||||||
|
@ -47,66 +47,61 @@ When starting work on a feature, we should create a matching feature flag:
|
||||||
```
|
```
|
||||||
2. Check whether the feature is enabled as appropriate:
|
2. Check whether the feature is enabled as appropriate:
|
||||||
```js
|
```js
|
||||||
SettingsStore.isFeatureEnabled("feature_cats")
|
SettingsStore.getValue("feature_cats")
|
||||||
```
|
```
|
||||||
3. Add the feature to the [set of labs on develop](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json):
|
3. Document the feature in the [labs documentation](https://github.com/vector-im/element-web/blob/develop/docs/labs.md)
|
||||||
```json
|
|
||||||
"features": {
|
|
||||||
"feature_cats": "labs"
|
|
||||||
},
|
|
||||||
```
|
|
||||||
4. Document the feature in the [labs documentation](https://github.com/vector-im/riot-web/blob/develop/docs/labs.md)
|
|
||||||
|
|
||||||
With these steps completed, the feature is disabled by default, but can be
|
With these steps completed, the feature is disabled by default, but can be
|
||||||
enabled on develop by interested users for testing.
|
enabled on develop and nightly by interested users for testing.
|
||||||
|
|
||||||
Different features may have different deployment plans for when to enable where.
|
Different features may have different deployment plans for when to enable where.
|
||||||
The following lists a few common options.
|
The following lists a few common options.
|
||||||
|
|
||||||
## Enabling by default on develop
|
## Enabling by default on develop and nightly
|
||||||
|
|
||||||
Set the feature to `enable` in the [develop config](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json):
|
Set the feature to `true` in the
|
||||||
|
[develop](https://github.com/vector-im/element-web/blob/develop/element.io/develop/config.json)
|
||||||
|
and
|
||||||
|
[nightly](https://github.com/vector-im/element-desktop/blob/develop/element.io/nightly/config.json)
|
||||||
|
configs:
|
||||||
|
|
||||||
```json
|
```json
|
||||||
"features": {
|
"features": {
|
||||||
"feature_cats": "enable"
|
"feature_cats": true
|
||||||
},
|
},
|
||||||
```
|
```
|
||||||
|
|
||||||
## Enabling by default on staging and app
|
## Enabling by default on staging, app, and release
|
||||||
|
|
||||||
Set the feature to `enable` in the [app
|
Set the feature to `true` in the
|
||||||
config](https://github.com/vector-im/riot-web/blob/develop/riot.im/app/config.json).
|
[staging / app](https://github.com/vector-im/element-web/blob/develop/element.io/app/config.json)
|
||||||
|
and
|
||||||
|
[release](https://github.com/vector-im/element-desktop/blob/develop/element.io/release/config.json)
|
||||||
|
configs.
|
||||||
|
|
||||||
|
**Note:** The above will only enable the feature for https://app.element.io and official Element
|
||||||
|
Desktop builds. It will not be enabled for self-hosted installed, custom desktop builds, etc. To
|
||||||
|
cover these cases, change the setting's `default` in `Settings.ts` to `true`.
|
||||||
|
|
||||||
## Feature deployed successfully
|
## Feature deployed successfully
|
||||||
|
|
||||||
Once we're confident that a feature is working well, we should remove the flag:
|
Once we're confident that a feature is working well, we should remove or convert the flag.
|
||||||
|
|
||||||
1. Remove the [setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.js)
|
If the feature is meant to be turned off/on by the user:
|
||||||
2. Remove all `isFeatureEnabled` lines that test for the feature's setting
|
1. Remove `isFeature` from the [setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.ts)
|
||||||
3. Remove the feature from the [labs documentation](https://github.com/vector-im/riot-web/blob/develop/docs/labs.md)
|
2. Change the `default` to `true` (if desired).
|
||||||
4. Remove feature state from
|
3. Remove the feature from the [labs documentation](https://github.com/vector-im/element-web/blob/develop/docs/labs.md)
|
||||||
[develop](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json)
|
4. Celebrate! 🥳
|
||||||
and [app](https://github.com/vector-im/riot-web/blob/develop/riot.im/app/config.json)
|
|
||||||
|
If the feature is meant to be forced on (non-configurable):
|
||||||
|
1. Remove the [setting](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.ts)
|
||||||
|
2. Remove all `getValue` lines that test for the feature.
|
||||||
|
3. Remove the feature from the [labs documentation](https://github.com/vector-im/element-web/blob/develop/docs/labs.md)
|
||||||
|
4. If applicable, remove the feature state from
|
||||||
|
[develop](https://github.com/vector-im/element-web/blob/develop/element.io/develop/config.json),
|
||||||
|
[nightly](https://github.com/vector-im/element-desktop/blob/develop/element.io/nightly/config.json),
|
||||||
|
[staging / app](https://github.com/vector-im/element-web/blob/develop/element.io/app/config.json),
|
||||||
|
and
|
||||||
|
[release](https://github.com/vector-im/element-desktop/blob/develop/element.io/release/config.json)
|
||||||
configs
|
configs
|
||||||
5. Celebrate! 🥳
|
5. Celebrate! 🥳
|
||||||
|
|
||||||
## Convert to a regular setting (optional)
|
|
||||||
|
|
||||||
Sometimes we decide a feature should always be user-controllable as a setting
|
|
||||||
even after it has been fully deployed. In that case, we would craft a new,
|
|
||||||
regular setting:
|
|
||||||
|
|
||||||
1. Remove the feature flag from
|
|
||||||
[settings](https://github.com/matrix-org/matrix-react-sdk/blob/develop/src/settings/Settings.js)
|
|
||||||
and add a regular setting with the appropriate levels for your feature
|
|
||||||
2. Replace the `isFeatureEnabled` lines with `getValue` or similar calls
|
|
||||||
according to the [settings
|
|
||||||
docs](https://github.com/matrix-org/matrix-react-sdk/blob/develop/docs/settings.md)
|
|
||||||
(checking carefully, as we may want a different mix of code paths when the
|
|
||||||
feature is always present but gated by a setting)
|
|
||||||
3. Remove the feature from the [labs documentation](https://github.com/vector-im/riot-web/blob/develop/docs/labs.md)
|
|
||||||
4. Remove feature state from
|
|
||||||
[develop](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json)
|
|
||||||
and [app](https://github.com/vector-im/riot-web/blob/develop/riot.im/app/config.json)
|
|
||||||
configs
|
|
||||||
|
|
BIN
docs/img/pr-checks.png
Normal file
After Width: | Height: | Size: 155 KiB |
|
@ -1,10 +1,10 @@
|
||||||
# Jitsi wrapper developer docs
|
# Jitsi wrapper developer docs
|
||||||
|
|
||||||
*If you're looking for information on how to set up Jitsi in your Riot, see
|
*If you're looking for information on how to set up Jitsi in your Element, see
|
||||||
[jitsi.md](./jitsi.md) instead.*
|
[jitsi.md](./jitsi.md) instead.*
|
||||||
|
|
||||||
These docs are for developers wondering how the different conference buttons work
|
These docs are for developers wondering how the different conference buttons work
|
||||||
within Riot. If you're not a developer, you're probably looking for [jitsi.md](./jitsi.md).
|
within Element. If you're not a developer, you're probably looking for [jitsi.md](./jitsi.md).
|
||||||
|
|
||||||
## Brief introduction to widgets
|
## Brief introduction to widgets
|
||||||
|
|
||||||
|
@ -17,8 +17,8 @@ in the react-sdk), though for some widgets special integration can be done. v2 w
|
||||||
have a `data` object which helps achieve that special integration, though v1 widgets
|
have a `data` object which helps achieve that special integration, though v1 widgets
|
||||||
are best iframed and left alone.
|
are best iframed and left alone.
|
||||||
|
|
||||||
Widgets have a `postMessage` API they can use to interact with Riot, which also allows
|
Widgets have a `postMessage` API they can use to interact with Element, which also allows
|
||||||
Riot to interact with them. Typically this is most used by the sticker picker (an
|
Element to interact with them. Typically this is most used by the sticker picker (an
|
||||||
account-level widget), though widgets like the Jitsi widget will request permissions to
|
account-level widget), though widgets like the Jitsi widget will request permissions to
|
||||||
get 'stuck' into the room list during a conference.
|
get 'stuck' into the room list during a conference.
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ Widgets can be added with the `/addwidget <url>` command.
|
||||||
|
|
||||||
Integration managers (like Scalar and Dimension) are accessible via the 4 squares in
|
Integration managers (like Scalar and Dimension) are accessible via the 4 squares in
|
||||||
the top right of the room and provide a simple UI over top of bridges, bots, and other
|
the top right of the room and provide a simple UI over top of bridges, bots, and other
|
||||||
stuff to plug into a room. They are a separate service to Riot and are thus iframed
|
stuff to plug into a room. They are a separate service to Element and are thus iframed
|
||||||
in a dialog as well. They also have a `postMessage` API they can use to interact with
|
in a dialog as well. They also have a `postMessage` API they can use to interact with
|
||||||
the client to create things like widgets, give permissions to bridges, and generally
|
the client to create things like widgets, give permissions to bridges, and generally
|
||||||
set everything up for the integration the user is working with.
|
set everything up for the integration the user is working with.
|
||||||
|
@ -51,7 +51,7 @@ over `postMessage`, even if they aren't going to be using the widget APIs).
|
||||||
|
|
||||||
Widgets added with the `/addwidget` command will *not* be wrapped as they are not going
|
Widgets added with the `/addwidget` command will *not* be wrapped as they are not going
|
||||||
through an integration manager. The widgets themselves *should* also work outside of
|
through an integration manager. The widgets themselves *should* also work outside of
|
||||||
Riot. Widgets currently have a "pop out" button which opens them in a new tab and
|
Element. Widgets currently have a "pop out" button which opens them in a new tab and
|
||||||
therefore have no connection back to Riot.
|
therefore have no connection back to Riot.
|
||||||
|
|
||||||
## Jitsi widgets from integration managers
|
## Jitsi widgets from integration managers
|
||||||
|
@ -65,27 +65,27 @@ server they specified in their config.json - this is expected.
|
||||||
Some integration managers allow the user to change the conference name while others
|
Some integration managers allow the user to change the conference name while others
|
||||||
will generate one for the user.
|
will generate one for the user.
|
||||||
|
|
||||||
## Jitsi widgets generated by Riot itself
|
## Jitsi widgets generated by Element itself
|
||||||
|
|
||||||
When the user clicks on the call buttons by the composer, the integration manager is
|
When the user clicks on the call buttons by the composer, the integration manager is
|
||||||
not involved in the slightest. Instead, Riot itself generates a widget event, this time
|
not involved in the slightest. Instead, Element itself generates a widget event, this time
|
||||||
using the config.json parameters, and publishes that to the room. If there's only two
|
using the config.json parameters, and publishes that to the room. If there's only two
|
||||||
people in the room, a plain WebRTC call is made instead of using a widget at all - these
|
people in the room, a plain WebRTC call is made instead of using a widget at all - these
|
||||||
are defined in the Matrix specification.
|
are defined in the Matrix specification.
|
||||||
|
|
||||||
The Jitsi widget created by Riot uses a local `jitsi.html` wrapper (or one hosted by
|
The Jitsi widget created by Element uses a local `jitsi.html` wrapper (or one hosted by
|
||||||
`https://riot.im/app` for desktop users or those on non-https domains) as the widget
|
`https://app.element.io` for desktop users or those on non-https domains) as the widget
|
||||||
`url`. The wrapper has some basic functionality for talking to Riot to ensure the
|
`url`. The wrapper has some basic functionality for talking to Element to ensure the
|
||||||
required `postMessage` calls are fulfilled.
|
required `postMessage` calls are fulfilled.
|
||||||
|
|
||||||
**Note**: Per [jitsi.md](./jitsi.md) the `preferredDomain` can also come from the server's
|
**Note**: Per [jitsi.md](./jitsi.md) the `preferredDomain` can also come from the server's
|
||||||
client .well-known data.
|
client .well-known data.
|
||||||
|
|
||||||
## The Jitsi wrapper in Riot
|
## The Jitsi wrapper in Element
|
||||||
|
|
||||||
Whenever Riot sees a Jitsi widget, it ditches the `url` and instead replaces it with
|
Whenever Element sees a Jitsi widget, it ditches the `url` and instead replaces it with
|
||||||
its local wrapper, much like what it would do when creating a widget. However, instead
|
its local wrapper, much like what it would do when creating a widget. However, instead
|
||||||
of using one from riot.im/app, it will use one local to the client instead.
|
of using one from [app.element.io](https://app.element.io), it will use one local to the client instead.
|
||||||
|
|
||||||
The wrapper is used to provide a consistent experience to users, as well as being faster
|
The wrapper is used to provide a consistent experience to users, as well as being faster
|
||||||
and less risky to load. The local wrapper URL is populated with the conference information
|
and less risky to load. The local wrapper URL is populated with the conference information
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Jitsi in Riot
|
# Jitsi in Element
|
||||||
|
|
||||||
Riot uses [Jitsi](https://jitsi.org/) for conference calls, which provides options for
|
Element uses [Jitsi](https://jitsi.org/) for conference calls, which provides options for
|
||||||
self-hosting your own server and supports most major platforms.
|
self-hosting your own server and supports most major platforms.
|
||||||
|
|
||||||
1:1 calls, or calls between you and one other person, do not use Jitsi. Instead, those
|
1:1 calls, or calls between you and one other person, do not use Jitsi. Instead, those
|
||||||
|
@ -14,13 +14,13 @@ will add a Jitsi widget which allows anyone in the room to join.
|
||||||
Integration managers (available through the 4 squares in the top right of the room) may
|
Integration managers (available through the 4 squares in the top right of the room) may
|
||||||
provide their own approaches for adding Jitsi widgets.
|
provide their own approaches for adding Jitsi widgets.
|
||||||
|
|
||||||
## Configuring Riot to use your self-hosted Jitsi server
|
## Configuring Element to use your self-hosted Jitsi server
|
||||||
|
|
||||||
Riot will use the Jitsi server that is embedded in the widget, even if it is not the
|
Element will use the Jitsi server that is embedded in the widget, even if it is not the
|
||||||
one you configured. This is because conference calls must be held on a single Jitsi
|
one you configured. This is because conference calls must be held on a single Jitsi
|
||||||
server and cannot be split over multiple servers.
|
server and cannot be split over multiple servers.
|
||||||
|
|
||||||
However, you can configure Riot to *start* a conference with your Jitsi server by adding
|
However, you can configure Element to *start* a conference with your Jitsi server by adding
|
||||||
to your [config](./config.md) the following:
|
to your [config](./config.md) the following:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
|
@ -30,17 +30,18 @@ to your [config](./config.md) the following:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
The default is `jitsi.riot.im` (a free service offered by Riot), and the demo site for
|
The default is `jitsi.riot.im` (a free service offered by Element), and the demo site for
|
||||||
Jitsi uses `meet.jit.si` (also free).
|
Jitsi uses `meet.jit.si` (also free).
|
||||||
|
|
||||||
Once you've applied the config change, refresh Riot and press the call button. This
|
Once you've applied the config change, refresh Element and press the call button. This
|
||||||
should start a new conference on your Jitsi server.
|
should start a new conference on your Jitsi server.
|
||||||
|
|
||||||
**Note**: The widget URL will point to a `jitsi.html` page hosted by Riot. The Jitsi
|
**Note**: The widget URL will point to a `jitsi.html` page hosted by Element. The Jitsi
|
||||||
domain will appear later in the URL as a configuration parameter.
|
domain will appear later in the URL as a configuration parameter.
|
||||||
|
|
||||||
**Hint**: If you want everyone on your homeserver to use the same Jitsi server by
|
**Hint**: If you want everyone on your homeserver to use the same Jitsi server by
|
||||||
default, set the following on your homeserver's `/.well-known/matrix/client` config:
|
default, and you are using element-web 1.6 or newer, set the following on your homeserver's
|
||||||
|
`/.well-known/matrix/client` config:
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"im.vector.riot.jitsi": {
|
"im.vector.riot.jitsi": {
|
||||||
|
@ -49,9 +50,24 @@ default, set the following on your homeserver's `/.well-known/matrix/client` con
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
## Mobile app support
|
## Element Android
|
||||||
|
|
||||||
Currently the Riot mobile apps do not support custom Jitsi servers and will instead
|
Element Android (1.0.5+) supports custom Jitsi domains, similar to Element Web above.
|
||||||
|
|
||||||
|
1:1 calls, or calls between you and one other person, do not use Jitsi. Instead, those
|
||||||
|
calls work directly between clients or via TURN servers configured on the respective
|
||||||
|
homeservers.
|
||||||
|
|
||||||
|
For rooms with more than 2 joined members, when creating a Jitsi conference via call/video buttons of the toolbar (not via integration manager), Element Android will create a widget using the [wrapper](https://github.com/vector-im/element-web/blob/develop/docs/jitsi-dev.md) hosted on `app.element.io`.
|
||||||
|
The domain used is the one specified by the `/.well-known/matrix/client` endpoint, and if not present it uses the fallback defined in `config.xml` (jitsi.riot.im)
|
||||||
|
|
||||||
|
For active Jitsi widgets in the room, a native Jitsi widget UI is created and points to the instance specified in the `domain` key of the widget content data.
|
||||||
|
|
||||||
|
Element Android manages allowed native widgets permissions a bit differently than web widgets (as the data shared are different and never shared with the widget URL). For Jitsi widgets, permissions are requested only once per domain (consent saved in account data).
|
||||||
|
|
||||||
|
## Element iOS
|
||||||
|
|
||||||
|
Currently the Element mobile apps do not support custom Jitsi servers and will instead
|
||||||
use the default `jitsi.riot.im` server. When users on the mobile apps join the call,
|
use the default `jitsi.riot.im` server. When users on the mobile apps join the call,
|
||||||
they will be joining a different conference which has the same name, but not the same
|
they will be joining a different conference which has the same name, but not the same
|
||||||
participants. This is a known bug and which needs to be fixed.
|
participants. This is a known bug and which needs to be fixed.
|
||||||
|
|
187
docs/kubernetes.md
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
Running in Kubernetes
|
||||||
|
=====================
|
||||||
|
|
||||||
|
In case you would like to deploy element-web in a kubernetes cluster you can use
|
||||||
|
the provided Kubernetes example below as a starting point. Note that this example assumes the
|
||||||
|
Nginx ingress to be installed.
|
||||||
|
|
||||||
|
Note that the content of the required `config.json` is defined inside this yaml because it needs
|
||||||
|
to be put in your Kubernetes cluster as a `ConfigMap`.
|
||||||
|
|
||||||
|
So to use it you must create a file with this content as a starting point and modify it so it meets
|
||||||
|
the requirements of your environment.
|
||||||
|
|
||||||
|
Then you can deploy it to your cluster with something like `kubectl apply -f my-element-web.yaml`.
|
||||||
|
|
||||||
|
# This is an example of a POSSIBLE config for deploying a single element-web instance in Kubernetes
|
||||||
|
|
||||||
|
# Use the element-web namespace to put it all in.
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: element-web
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# The config.json file is to be put into Kubernetes as a config file in such a way that
|
||||||
|
# the element web instance can read it.
|
||||||
|
# The code below shows how this can be done with the config.sample.json content.
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: element-config
|
||||||
|
namespace: element-web
|
||||||
|
data:
|
||||||
|
config.json: |
|
||||||
|
{
|
||||||
|
"default_server_config": {
|
||||||
|
"m.homeserver": {
|
||||||
|
"base_url": "https://matrix-client.matrix.org",
|
||||||
|
"server_name": "matrix.org"
|
||||||
|
},
|
||||||
|
"m.identity_server": {
|
||||||
|
"base_url": "https://vector.im"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"disable_custom_urls": false,
|
||||||
|
"disable_guests": false,
|
||||||
|
"disable_login_language_selector": false,
|
||||||
|
"disable_3pid_login": false,
|
||||||
|
"brand": "Element",
|
||||||
|
"integrations_ui_url": "https://scalar.vector.im/",
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||||
|
"defaultCountryCode": "GB",
|
||||||
|
"showLabsSettings": false,
|
||||||
|
"features": { },
|
||||||
|
"default_federate": true,
|
||||||
|
"default_theme": "light",
|
||||||
|
"roomDirectory": {
|
||||||
|
"servers": [
|
||||||
|
"matrix.org"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"piwik": {
|
||||||
|
"url": "https://piwik.riot.im/",
|
||||||
|
"whitelistedHSUrls": ["https://matrix.org"],
|
||||||
|
"whitelistedISUrls": ["https://vector.im", "https://matrix.org"],
|
||||||
|
"siteId": 1
|
||||||
|
},
|
||||||
|
"enable_presence_by_hs_url": {
|
||||||
|
"https://matrix.org": false,
|
||||||
|
"https://matrix-client.matrix.org": false
|
||||||
|
},
|
||||||
|
"settingDefaults": {
|
||||||
|
"breadcrumbs": true
|
||||||
|
},
|
||||||
|
"jitsi": {
|
||||||
|
"preferredDomain": "jitsi.riot.im"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# A deployment of the element-web for a single instance
|
||||||
|
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: element
|
||||||
|
namespace: element-web
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: element
|
||||||
|
replicas: 1
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: element
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: element
|
||||||
|
image: vectorim/element-web:latest
|
||||||
|
volumeMounts:
|
||||||
|
- name: config-volume
|
||||||
|
mountPath: /app/config.json
|
||||||
|
subPath: config.json
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
name: element
|
||||||
|
protocol: TCP
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: element
|
||||||
|
initialDelaySeconds: 2
|
||||||
|
periodSeconds: 3
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /
|
||||||
|
port: element
|
||||||
|
initialDelaySeconds: 10
|
||||||
|
periodSeconds: 10
|
||||||
|
volumes:
|
||||||
|
- name: config-volume
|
||||||
|
configMap:
|
||||||
|
name: element-config
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# Wrap it all in a Service
|
||||||
|
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: element
|
||||||
|
namespace: element-web
|
||||||
|
spec:
|
||||||
|
selector:
|
||||||
|
app: element
|
||||||
|
ports:
|
||||||
|
- name: default
|
||||||
|
protocol: TCP
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
# An ingress definition to expose the service via a hostname
|
||||||
|
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: element
|
||||||
|
namespace: element-web
|
||||||
|
annotations:
|
||||||
|
kubernetes.io/ingress.class: nginx
|
||||||
|
nginx.ingress.kubernetes.io/configuration-snippet: |
|
||||||
|
add_header X-Frame-Options SAMEORIGIN;
|
||||||
|
add_header X-Content-Type-Options nosniff;
|
||||||
|
add_header X-XSS-Protection "1; mode=block";
|
||||||
|
add_header Content-Security-Policy "frame-ancestors 'none'";
|
||||||
|
spec:
|
||||||
|
rules:
|
||||||
|
- host: element.example.nl
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
- pathType: Prefix
|
||||||
|
path: /
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: element
|
||||||
|
port:
|
||||||
|
number: 80
|
||||||
|
|
||||||
|
---
|
||||||
|
|
84
docs/labs.md
|
@ -1,11 +1,29 @@
|
||||||
# Labs features
|
# Labs features
|
||||||
|
|
||||||
Some notes on the features you can enable by going to `Settings->Labs`. Not exhaustive, chat in
|
If Labs is enabled in the [Element config](config.md), you can enable some of these features by going
|
||||||
[#riot-web:matrix.org](https://matrix.to/#/#riot-web:matrix.org) for more information.
|
to `Settings->Labs`. This list is non-exhaustive and subject to change, chat in
|
||||||
|
[#element-web:matrix.org](https://matrix.to/#/#element-web:matrix.org) for more information.
|
||||||
|
|
||||||
**Be warned! Labs features are not finalised, they may be fragile, they may change, they may be
|
**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.**
|
dropped. Ask in the room if you are unclear about any details here.**
|
||||||
|
|
||||||
|
## Submit Abuse Report to Moderators [MSC3215](https://github.com/matrix-org/matrix-doc/pull/3215) support (`feature_report_to_moderators`)
|
||||||
|
|
||||||
|
A new version of the "Report" dialog that lets users send abuse reports directly to room moderators,
|
||||||
|
if the room supports it.
|
||||||
|
|
||||||
|
## Matrix Spaces [MSC1772](https://github.com/matrix-org/matrix-doc/pull/1772) support (`feature_spaces`)
|
||||||
|
|
||||||
|
Enables showing, using, creating, and managing spaces. Create Spaces from the all new Space Panel (to left of Room List).
|
||||||
|
|
||||||
|
Incompatible with (will disable) `feature_custom_tags`, `feature_communities_v2_prototypes` and stable Communities/Groups support.
|
||||||
|
|
||||||
|
Still in heavy development.
|
||||||
|
|
||||||
|
## Render LaTeX maths in messages (`feature_latex_maths`)
|
||||||
|
|
||||||
|
Enables rendering of LaTeX maths in messages using [KaTeX](https://katex.org/). LaTeX between single dollar-signs is interpreted as inline maths and double dollar-signs as display maths (i.e. centred on its own line).
|
||||||
|
|
||||||
## Message pinning (`feature_pinning`)
|
## 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
|
Allows you to pin messages in the room. To pin a message, use the 3 dots to the right of the message
|
||||||
|
@ -21,7 +39,7 @@ your avatar next to the message composer.
|
||||||
An experimental approach for dealing with custom tags. Custom tags will appear in the bottom portion
|
An experimental approach for dealing with custom tags. Custom tags will appear in the bottom portion
|
||||||
of the community filter panel.
|
of the community filter panel.
|
||||||
|
|
||||||
Setting custom tags is not supported by Riot.
|
Setting custom tags is not supported by Element.
|
||||||
|
|
||||||
## Render simple counters in room header (`feature_state_counters`)
|
## Render simple counters in room header (`feature_state_counters`)
|
||||||
|
|
||||||
|
@ -48,7 +66,7 @@ That's it. Now should see your new counter under the header.
|
||||||
|
|
||||||
## Multiple integration managers (`feature_many_integration_managers`)
|
## 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).
|
Exposes a way to access all the integration managers known to Element. This is an implementation of [MSC1957](https://github.com/matrix-org/matrix-doc/pull/1957).
|
||||||
|
|
||||||
## New ways to ignore people (`feature_mjolnir`)
|
## New ways to ignore people (`feature_mjolnir`)
|
||||||
|
|
||||||
|
@ -66,21 +84,8 @@ An implementation of [MSC2241](https://github.com/matrix-org/matrix-doc/pull/224
|
||||||
|
|
||||||
This also includes a new implementation of the user & member info panel, designed to share more code between showing community members & room members. Built on top of this new panel is also a new UX for verification from the member panel.
|
This also includes a new implementation of the user & member info panel, designed to share more code between showing community members & room members. Built on top of this new panel is also a new UX for verification from the member panel.
|
||||||
|
|
||||||
## Cross-signing (in development) (`feature_cross_signing`)
|
The setting will be removed in a future release, enabling it non-optionally for
|
||||||
|
all users.
|
||||||
Cross-signing ([MSC1756](https://github.com/matrix-org/matrix-doc/pull/1756))
|
|
||||||
improves the device verification experience by allowing you to verify a user
|
|
||||||
instead of verifying each of their devices.
|
|
||||||
|
|
||||||
This feature is still in development and will be landing in several chunks.
|
|
||||||
|
|
||||||
## Event indexing and E2EE search support using Seshat (`feature_event_indexing`)
|
|
||||||
|
|
||||||
Adds support for search in E2E encrypted rooms. This enables an event indexer
|
|
||||||
that downloads, stores, and indexes room messages for E2E encrypted rooms.
|
|
||||||
|
|
||||||
The existing search will transparently work for encrypted rooms just like it
|
|
||||||
does for non-encrypted.
|
|
||||||
|
|
||||||
## Bridge info tab (`feature_bridge_state`)
|
## Bridge info tab (`feature_bridge_state`)
|
||||||
|
|
||||||
|
@ -94,16 +99,41 @@ tab as the single source of truth just yet.
|
||||||
This adds a presence indicator in the room list next to DM rooms where the other
|
This adds a presence indicator in the room list next to DM rooms where the other
|
||||||
person is online.
|
person is online.
|
||||||
|
|
||||||
## Show padlocks on invite only rooms (`feature_invite_only_padlocks`)
|
|
||||||
|
|
||||||
This adds padlocks to room list tiles and room header for invite only rooms.
|
|
||||||
This feature flag (unlike most) is enabled by default.
|
|
||||||
|
|
||||||
## Custom themes (`feature_custom_themes`)
|
## Custom themes (`feature_custom_themes`)
|
||||||
|
|
||||||
Custom themes are possible through Riot's [theme support](./theming.md), though
|
Custom themes are possible through Element's [theme support](./theming.md), though
|
||||||
normally these themes need to be defined in the config for Riot. This labs flag
|
normally these themes need to be defined in the config for Element. This labs flag
|
||||||
adds an ability for end users to add themes themselves by using a URL to the JSON
|
adds an ability for end users to add themes themselves by using a URL to the JSON
|
||||||
theme definition.
|
theme definition.
|
||||||
|
|
||||||
For some sample themes, check out [aaronraimist/riot-web-themes](https://github.com/aaronraimist/riot-web-themes).
|
For some sample themes, check out [aaronraimist/element-themes](https://github.com/aaronraimist/element-themes).
|
||||||
|
|
||||||
|
## Message preview tweaks
|
||||||
|
|
||||||
|
To enable message previews for reactions in all rooms, enable `feature_roomlist_preview_reactions_all`.
|
||||||
|
To enable message previews for reactions in DMs, enable `feature_roomlist_preview_reactions_dms`, ignored when it is enabled for all rooms.
|
||||||
|
|
||||||
|
## Communities v2 prototyping (`feature_communities_v2_prototypes`) [In Development]
|
||||||
|
|
||||||
|
**This is a highly experimental implementation for parts of the communities v2 experience.** It does not
|
||||||
|
represent what communities v2 will look/feel like and can/will change without notice. Due to the early
|
||||||
|
stages this feature is in and the requirement for a compatible homeserver, we will not be accepting issues
|
||||||
|
or feedback for this functionality at this time.
|
||||||
|
|
||||||
|
## Dehydrated devices (`feature_dehydration`)
|
||||||
|
|
||||||
|
Allows users to receive encrypted messages by creating a device that is stored
|
||||||
|
encrypted on the server, as described in [MSC2697](https://github.com/matrix-org/matrix-doc/pull/2697).
|
||||||
|
|
||||||
|
## Voice messages (`feature_voice_messages`)
|
||||||
|
|
||||||
|
Offers a way to send more time-sensitive information through the power of voice. When enabled, use the microphone
|
||||||
|
icon on the lower right to start recording your message. You will have a chance to review after you're done recording,
|
||||||
|
and if it sounds fine then send it off for the rest of the room to hear.
|
||||||
|
|
||||||
|
Voice messages are automatically downloaded to ensure they are ready for playback as soon as possible.
|
||||||
|
|
||||||
|
## Do not disturb (`feature_dnd`)
|
||||||
|
|
||||||
|
Enables UI for turning on "do not disturb" mode for the current device. When DND mode is engaged, popups
|
||||||
|
and notification noises are suppressed. Not perfect, but can help reduce noise.
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
## Memory leaks
|
## Memory leaks
|
||||||
|
|
||||||
Riot usually emits slow behaviour just before it is about to crash. Getting a
|
Element 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
|
memory snapshot (below) just before that happens is ideal in figuring out what
|
||||||
is going wrong.
|
is going wrong.
|
||||||
|
|
||||||
|
@ -14,14 +14,14 @@ this happens though so we can try and narrow down what might have gone wrong.
|
||||||
## Memory profiles/snapshots
|
## Memory profiles/snapshots
|
||||||
|
|
||||||
When investigating memory leaks/problems it's usually important to compare 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
|
from different points in the Element session lifecycle. Most importantly, a snapshot
|
||||||
to establish the baseline or "normal" memory usage is useful. Taking 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"
|
roughly 30-60 minutes after starting Element is a good time to establish "normal"
|
||||||
memory usage for the app - anything after that is at risk of hiding the memory leak
|
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.
|
and anything newer is still in the warmup stages of the app.
|
||||||
|
|
||||||
**Memory profiles can contain sensitive information.** If you are submitting a memory
|
**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
|
profile to us for debugging purposes, please pick the appropriate Element developer and
|
||||||
send them over an encrypted private message. *Do not share your memory profile in
|
send them over an encrypted private message. *Do not share your memory profile in
|
||||||
public channels or with people you do not trust.*
|
public channels or with people you do not trust.*
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ While the profile is in progress, the tab might be frozen or unresponsive.
|
||||||
|
|
||||||
1. Press CTRL+SHIFT+I (I as in eye).
|
1. Press CTRL+SHIFT+I (I as in eye).
|
||||||
2. Click the Memory tab.
|
2. Click the Memory tab.
|
||||||
3. Select "Heap Snapshot" and the riot.im VM instance (not the indexeddb one).
|
3. Select "Heap Snapshot" and the app.element.io VM instance (not the indexeddb one).
|
||||||
4. Click "Take Snapshot".
|
4. Click "Take Snapshot".
|
||||||
5. Wait a bit (coffee is a good option).
|
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
|
6. When the save button appears on the left side of the panel, click it to save the
|
||||||
|
|
|
@ -1,60 +1,3 @@
|
||||||
# Native Node Modules
|
# Native Node Modules
|
||||||
|
|
||||||
For some features, the desktop version of Riot can make use of native Node
|
This documentation moved to the [`element-desktop`](https://github.com/vector-im/element-desktop/blob/develop/docs/native-node-modules.md) repository.
|
||||||
modules. These allow Riot to integrate with the desktop in ways that a browser
|
|
||||||
cannot.
|
|
||||||
|
|
||||||
While native modules enable powerful new features, they must be complied for
|
|
||||||
each operating system. For official Riot releases, we will always build these
|
|
||||||
modules from source to ensure we can trust the compiled output. In the future,
|
|
||||||
we may offer a pre-compiled path for those who want to use these features in a
|
|
||||||
custom build of Riot without installing the various build tools required.
|
|
||||||
|
|
||||||
Do note that compiling a module for a particular operating system
|
|
||||||
(Linux/macOS/Windows) will need to be done on that operating system.
|
|
||||||
Cross-compiling from a host OS for a different target OS may be possible, but
|
|
||||||
we don't support this flow with Riot dependencies at this time.
|
|
||||||
|
|
||||||
At the moment, we need to make some changes to the Riot release process before
|
|
||||||
we can support native Node modules at release time, so these features are
|
|
||||||
currently disabled by default until that is resolved. The following sections
|
|
||||||
explain the manual steps you can use with a custom build of Riot to enable
|
|
||||||
these features if you'd like to try them out.
|
|
||||||
|
|
||||||
## Adding Seshat for search in E2E encrypted rooms
|
|
||||||
|
|
||||||
Seshat is a native Node module that adds support for local event indexing and
|
|
||||||
full text search in E2E encrypted rooms.
|
|
||||||
|
|
||||||
Since Seshat is written in Rust, the Rust compiler and related tools need to be
|
|
||||||
installed before installing Seshat itself. To install Rust please consult the
|
|
||||||
official Rust [documentation](https://www.rust-lang.org/tools/install).
|
|
||||||
|
|
||||||
Seshat also depends on the SQLCipher library to store its data in encrypted form
|
|
||||||
on disk. You'll need to install it via your OS package manager.
|
|
||||||
|
|
||||||
After installing the Rust compiler and SQLCipher, Seshat support can be added
|
|
||||||
using yarn inside the `electron_app/` directory:
|
|
||||||
|
|
||||||
yarn add matrix-seshat
|
|
||||||
|
|
||||||
You will have to rebuild the native libraries against electron's version of
|
|
||||||
of node rather than your system node, using the `electron-build-env` tool.
|
|
||||||
This is also needed to when pulling in changes to Seshat using `yarn link`.
|
|
||||||
Again from the `electron_app/` directory:
|
|
||||||
|
|
||||||
yarn add electron-build-env
|
|
||||||
|
|
||||||
Recompiling Seshat itself can be done like so:
|
|
||||||
|
|
||||||
yarn run electron-build-env -- --electron 6.1.1 -- neon build matrix-seshat --release
|
|
||||||
|
|
||||||
Please make sure to include all the `--` as well as the `--release` command line
|
|
||||||
switch at the end. Modify your electron version accordingly depending on the
|
|
||||||
version that is installed on your system.
|
|
||||||
|
|
||||||
After this is done the Electron version of Riot can be run from the main folder
|
|
||||||
as usual using:
|
|
||||||
|
|
||||||
yarn electron
|
|
||||||
|
|
||||||
|
|
33
docs/pr-previews.md
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
# Pull Request Previews
|
||||||
|
|
||||||
|
Pull requests to the React SDK layer (and in the future other layers as well)
|
||||||
|
automatically set up a preview site with a full deployment of Element with the
|
||||||
|
changes from the pull request added in so that anyone can easily test and review
|
||||||
|
them. This is especially useful for checking visual and interactive changes.
|
||||||
|
|
||||||
|
To access the preview site, scroll down to the bottom of the PR where the
|
||||||
|
various CI results are displayed:
|
||||||
|
|
||||||
|
![Pull request: checks section](./img/pr-checks.png)
|
||||||
|
|
||||||
|
The checks section could be collapsed at first, so you may need to click "Show
|
||||||
|
all checks" to reveal them. Look for an entry that mentions `deploy-preview`. It
|
||||||
|
may be at the end of the list, so you may need scroll a bit to see it. To access
|
||||||
|
the preview site, click the "Details" link in the deploy preview row.
|
||||||
|
|
||||||
|
**Important:** Please always use test accounts when logging into preview sites,
|
||||||
|
as they may contain unreviewed and potentially dangerous code that could damage
|
||||||
|
your account, exfiltrate encryption keys, etc.
|
||||||
|
|
||||||
|
## FAQs
|
||||||
|
|
||||||
|
### Are preview sites created for pull requests from contributors?
|
||||||
|
|
||||||
|
Yes, they are created for all PRs from any author.
|
||||||
|
|
||||||
|
### Do preview sites expire after some time period?
|
||||||
|
|
||||||
|
No, there is no expiry date, so they should remain accessible indefinitely, but
|
||||||
|
of course they obviously aren't meant to live beyond the development workflow,
|
||||||
|
so please don't rely on them for anything important. They may disappear at any
|
||||||
|
time without notice.
|
|
@ -1,7 +1,7 @@
|
||||||
# Review Guidelines
|
# Review Guidelines
|
||||||
|
|
||||||
The following summarises review guidelines that we follow for pull requests in
|
The following summarises review guidelines that we follow for pull requests in
|
||||||
Riot Web and other supporting repos. These are just guidelines (not strict
|
Element Web and other supporting repos. These are just guidelines (not strict
|
||||||
rules) and may be updated over time.
|
rules) and may be updated over time.
|
||||||
|
|
||||||
## Code Review
|
## Code Review
|
||||||
|
@ -14,6 +14,7 @@ When reviewing code, here are some things we look for and also things we avoid:
|
||||||
* Performance
|
* Performance
|
||||||
* Accessibility
|
* Accessibility
|
||||||
* Security
|
* Security
|
||||||
|
* Quality via automated and manual testing
|
||||||
* Comments and documentation where needed
|
* Comments and documentation where needed
|
||||||
* Sharing knowledge of different areas among the team
|
* Sharing knowledge of different areas among the team
|
||||||
* Ensuring it's something we're comfortable maintaining for the long term
|
* Ensuring it's something we're comfortable maintaining for the long term
|
||||||
|
@ -34,6 +35,7 @@ When reviewing code, here are some things we look for and also things we avoid:
|
||||||
* Reviewers should be explicit about required versus optional changes
|
* Reviewers should be explicit about required versus optional changes
|
||||||
* Reviews are conversations and the PR author should feel comfortable
|
* Reviews are conversations and the PR author should feel comfortable
|
||||||
discussing and pushing back on changes before making them
|
discussing and pushing back on changes before making them
|
||||||
|
* Reviewers are encouraged to ask for tests where they believe it is reasonable
|
||||||
* Core team should lead by example through their tone and language
|
* Core team should lead by example through their tone and language
|
||||||
* Take the time to thank and point out good code changes
|
* Take the time to thank and point out good code changes
|
||||||
* Using softer language like "please" and "what do you think?" goes a long way
|
* Using softer language like "please" and "what do you think?" goes a long way
|
||||||
|
@ -41,7 +43,7 @@ When reviewing code, here are some things we look for and also things we avoid:
|
||||||
|
|
||||||
### Workflow
|
### Workflow
|
||||||
|
|
||||||
* Authors should request review from the riot-web team by default (if someone on
|
* Authors should request review from the element-web team by default (if someone on
|
||||||
the team is clearly the expert in an area, a direct review request to them may
|
the team is clearly the expert in an area, a direct review request to them may
|
||||||
be more appropriate)
|
be more appropriate)
|
||||||
* Reviewers should remove the team review request and request review from
|
* Reviewers should remove the team review request and request review from
|
||||||
|
@ -56,9 +58,46 @@ When reviewing code, here are some things we look for and also things we avoid:
|
||||||
* Assign issues only when in progress to indicate to others what can be picked
|
* Assign issues only when in progress to indicate to others what can be picked
|
||||||
up
|
up
|
||||||
|
|
||||||
|
## Code Quality
|
||||||
|
|
||||||
|
In the past, we have occasionally written different kinds of tests for
|
||||||
|
Element and the SDKs, but it hasn't been a consistent focus. Going forward, we'd
|
||||||
|
like to change that.
|
||||||
|
|
||||||
|
* For new features, code reviewers will expect some form of automated testing to
|
||||||
|
be included by default
|
||||||
|
* For bug fixes, regression tests are of course great to have, but we don't want
|
||||||
|
to block fixes on this, so we won't require them at this time
|
||||||
|
|
||||||
|
The above policy is not a strict rule, but instead it's meant to be a
|
||||||
|
conversation between the author and reviewer. As an author, try to think about
|
||||||
|
writing a test when making your next change. As a reviewer, try to think about
|
||||||
|
how you might test the area of code you are reviewing. If the reviewer agrees
|
||||||
|
it would be quite difficult to test some new feature, then it's okay for them to
|
||||||
|
accept the change without tests for now, but we'd eventually like to be more
|
||||||
|
strict about this further down the road.
|
||||||
|
|
||||||
|
If you do spot areas that are quite hard to test today, please let us know in
|
||||||
|
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org). We can
|
||||||
|
work on improving the app architecture and testing helpers so that future tests
|
||||||
|
are easier for everyone to write, but we won't know which parts are difficult
|
||||||
|
unless people shout when stumbling through them.
|
||||||
|
|
||||||
|
We recognise that this testing policy will slow things down a bit, but overall
|
||||||
|
it should encourage better long-term health of the app and give everyone more
|
||||||
|
confidence when making changes as coverage increases over time.
|
||||||
|
|
||||||
|
For changes guarded by a feature flag, we currently lean towards prioritising
|
||||||
|
our ability to evolve quickly using such flags and thus we will not currently
|
||||||
|
require tests to appear at the same time as the initial landing of features
|
||||||
|
guarded by flags, as long as (for new flagged features going forward) the
|
||||||
|
feature author understands that they are effectively deferring part of their
|
||||||
|
work (adding tests) until later and tests are expected to appear before the
|
||||||
|
feature can be enabled by default.
|
||||||
|
|
||||||
## Design and Product Review
|
## Design and Product Review
|
||||||
|
|
||||||
We want to ensure that all changes to Riot fit with our design and product
|
We want to ensure that all changes to Element fit with our design and product
|
||||||
vision. We often request review from those teams so they can provide their
|
vision. We often request review from those teams so they can provide their
|
||||||
perspective.
|
perspective.
|
||||||
|
|
||||||
|
@ -71,12 +110,11 @@ functionality is:
|
||||||
required (though may still be useful) since we can continue tweaking
|
required (though may still be useful) since we can continue tweaking
|
||||||
|
|
||||||
As it can be difficult to review design work from looking at just the changed
|
As it can be difficult to review design work from looking at just the changed
|
||||||
files in a PR, authors should be prepared for Design and / or Product teams to
|
files in a PR, a [preview site](./pr-previews.md) that includes your changes
|
||||||
request a link to an ad-hoc build of Riot (hosted anywhere) that can be used for
|
will be added automatically so that anyone who's interested can try them out
|
||||||
the review. In the future, we [hope to automate
|
easily.
|
||||||
this](https://github.com/vector-im/riot-web/issues/12624) for every PR.
|
|
||||||
|
|
||||||
Before starting work on a feature, it's best to ensure your plan aligns well
|
Before starting work on a feature, it's best to ensure your plan aligns well
|
||||||
with our vision for Riot. Please chat with the team in
|
with our vision for Element. Please chat with the team in
|
||||||
[#riot-dev:matrix.org](https://matrix.to/#/#riot-dev:matrix.org) before you
|
[#element-dev:matrix.org](https://matrix.to/#/#element-dev:matrix.org) before
|
||||||
start so we can ensure it's something we'd be willing to merge.
|
you start so we can ensure it's something we'd be willing to merge.
|
||||||
|
|
|
@ -5,14 +5,14 @@ matrix-react-sdk
|
||||||
- base CSS
|
- base CSS
|
||||||
- all the components needed to build a workable app (including the top layer)
|
- all the components needed to build a workable app (including the top layer)
|
||||||
|
|
||||||
riot-web: the riot skin
|
element-web: the Element skin
|
||||||
- riot-specific classes (e.g. login header/footer)
|
- Element-specific classes (e.g. login header/footer)
|
||||||
- riot-specific themes
|
- Element-specific themes
|
||||||
- light
|
- light
|
||||||
- dark
|
- dark
|
||||||
|
|
||||||
i.e. the only things which should go into riot-web are bits which apply vector-specific skinning
|
i.e. the only things which should go into element-web are bits which apply vector-specific skinning
|
||||||
specifically "Stuff that any other brand would not want to use. (e.g. riot logos, links, T&Cs)"
|
specifically "Stuff that any other brand would not want to use. (e.g. Element logos, links, T&Cs)"
|
||||||
- Questions:
|
- Questions:
|
||||||
- Electron app? (should probably be a separate repo in its own right? but might as well go here for now)
|
- Electron app? (should probably be a separate repo in its own right? but might as well go here for now)
|
||||||
- index.html & index.js? (should be in matrix-react-sdk, given the SDK is useless without them?)
|
- index.html & index.js? (should be in matrix-react-sdk, given the SDK is useless without them?)
|
||||||
|
@ -21,7 +21,7 @@ ideally matrix-react-sdk itself should ship with a default skin which actually w
|
||||||
|
|
||||||
status skin (can go in the same app for now)
|
status skin (can go in the same app for now)
|
||||||
- has status theme
|
- has status theme
|
||||||
- which inherits from riot light theme
|
- which inherits from Element light theme
|
||||||
- how do we share graphics between skins?
|
- how do we share graphics between skins?
|
||||||
- shove them into react-sdk, or...
|
- shove them into react-sdk, or...
|
||||||
- guess we do ../../vector/img
|
- guess we do ../../vector/img
|
||||||
|
@ -52,7 +52,7 @@ other changes:
|
||||||
- skins/vector/themes/foo/css
|
- skins/vector/themes/foo/css
|
||||||
- skins/vector/themes/foo/img
|
- skins/vector/themes/foo/img
|
||||||
- skins/vector/themes/foo/fonts
|
- skins/vector/themes/foo/fonts
|
||||||
- ideally riot-web would contain almost nothing but skins/vector directory.
|
- ideally element-web would contain almost nothing but skins/vector directory.
|
||||||
- ability to entirely replace CSS rather than override it for a given theme
|
- ability to entirely replace CSS rather than override it for a given theme
|
||||||
- e.g. if we replace `Login.js` with `StatusLogin.js`, then we should similarly be able to replace `_Login.scss` with `_StatusLogin.scss`.
|
- e.g. if we replace `Login.js` with `StatusLogin.js`, then we should similarly be able to replace `_Login.scss` with `_StatusLogin.scss`.
|
||||||
|
|
||||||
|
@ -64,5 +64,5 @@ random thoughts;
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
Immediate plan for Status:
|
Immediate plan for Status:
|
||||||
* Implement it as a theme for the riot skin
|
* Implement it as a theme for the Element skin
|
||||||
* Ideally move skins to a sensible level (possibly even including src?)
|
* Ideally move skins to a sensible level (possibly even including src?)
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
Theming Riot
|
Theming Element
|
||||||
============
|
============
|
||||||
|
|
||||||
Themes are a very basic way of providing simple alternative look & feels to the
|
Themes are a very basic way of providing simple alternative look & feels to the
|
||||||
riot-web app via CSS & custom imagery.
|
Element app via CSS & custom imagery.
|
||||||
|
|
||||||
They are *NOT* co be confused with 'skins', which describe apps which sit on top
|
They are *NOT* co be confused with 'skins', which describe apps which sit on top
|
||||||
of matrix-react-sdk - e.g. in theory Riot itself is a react-sdk skin.
|
of matrix-react-sdk - e.g. in theory Element itself is a react-sdk skin.
|
||||||
As of Jan 2017, skins are not fully supported; riot is the only available skin.
|
As of Jan 2017, skins are not fully supported; Element is the only available skin.
|
||||||
|
|
||||||
To define a theme for Riot:
|
To define a theme for Element:
|
||||||
|
|
||||||
1. Pick a name, e.g. `teal`. at time of writing we have `light` and `dark`.
|
1. Pick a name, e.g. `teal`. at time of writing we have `light` and `dark`.
|
||||||
2. Fork `src/skins/vector/css/themes/dark.scss` to be `teal.scss`
|
2. Fork `src/skins/vector/css/themes/dark.scss` to be `teal.scss`
|
||||||
|
@ -41,6 +41,16 @@ eg. in config.json:
|
||||||
{
|
{
|
||||||
"name": "Electric Blue",
|
"name": "Electric Blue",
|
||||||
"is_dark": false,
|
"is_dark": false,
|
||||||
|
"fonts": {
|
||||||
|
"faces": [
|
||||||
|
{
|
||||||
|
"font-family": "Inter",
|
||||||
|
"src": [{"url": "/fonts/Inter.ttf", "format": "ttf"}]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"general": "Inter, sans",
|
||||||
|
"monospace": "'Courier New'"
|
||||||
|
},
|
||||||
"colors": {
|
"colors": {
|
||||||
"accent-color": "#3596fc",
|
"accent-color": "#3596fc",
|
||||||
"primary-color": "#368bd6",
|
"primary-color": "#368bd6",
|
||||||
|
@ -54,7 +64,9 @@ eg. in config.json:
|
||||||
"timeline-background-color": "#ffffff",
|
"timeline-background-color": "#ffffff",
|
||||||
"timeline-text-color": "#2e2f32",
|
"timeline-text-color": "#2e2f32",
|
||||||
"timeline-text-secondary-color": "#61708b",
|
"timeline-text-secondary-color": "#61708b",
|
||||||
"timeline-highlights-color": "#f3f8fd"
|
"timeline-highlights-color": "#f3f8fd",
|
||||||
|
"username-colors": ["#ff0000", ...]
|
||||||
|
"avatar-background-colors": ["#cc0000", ...]
|
||||||
}
|
}
|
||||||
}, {
|
}, {
|
||||||
"name": "Deep Purple",
|
"name": "Deep Purple",
|
||||||
|
@ -78,3 +90,9 @@ eg. in config.json:
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`username-colors` is expected to contain 8 colors. `avatar-background-colors` is expected to contain 3 colors. Both values are optional and have fallbacks from the built-in theme.
|
||||||
|
|
||||||
|
These are exposed as `--username-colors_0`, ... and `--avatar-background-colors_0`, ... respectively in CSS.
|
||||||
|
|
||||||
|
All properties in `fonts` are optional, and will default to the standard Riot fonts.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# How to translate riot-web (Dev Guide)
|
# How to translate Element (Dev Guide)
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@
|
||||||
- Including up-to-date versions of matrix-react-sdk and matrix-js-sdk
|
- Including up-to-date versions of matrix-react-sdk and matrix-js-sdk
|
||||||
- Latest LTS version of Node.js installed
|
- 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 Element into
|
||||||
|
|
||||||
## Translating strings vs. marking strings for translation
|
## Translating strings vs. marking strings for translation
|
||||||
|
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
# How to translate riot-web
|
# How to translate Element
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
- Web Browser
|
- Web Browser
|
||||||
- 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 Element into
|
||||||
|
|
||||||
## Step 0: Join #riotweb-translations:matrix.org
|
## Step 0: Join #element-translations:matrix.org
|
||||||
|
|
||||||
1. Come and join https://matrix.to/#/#riotweb-translations:matrix.org
|
1. Come and join https://matrix.to/#/#element-translations:matrix.org
|
||||||
2. Read scrollback and/or ask if anyone else is working on your language, and co-ordinate if needed. In general little-or-no coordination is needed though :)
|
2. Read scrollback and/or ask if anyone else is working on your language, and co-ordinate if needed. In general little-or-no coordination is needed though :)
|
||||||
|
|
||||||
## Step 1: Preparing your Weblate Profile
|
## Step 1: Preparing your Weblate Profile
|
||||||
|
|
||||||
1. Head to https://translate.riot.im and register either via Github or email
|
1. Head to https://translate.element.io and register either via Github or email
|
||||||
2. After registering check if you got an email to verify your account and click the link (if there is none head to step 1.4)
|
2. After registering check if you got an email to verify your account and click the link (if there is none head to step 1.4)
|
||||||
3. Log into weblate
|
3. Log into weblate
|
||||||
4. Head to https://translate.riot.im/accounts/profile/ and select the languages you know and maybe another language you know too.
|
4. Head to https://translate.element.io/accounts/profile/ and select the languages you know and maybe another language you know too.
|
||||||
6. Head to https://translate.riot.im/accounts/profile/#subscriptions and select Riot Web as Project
|
6. Head to https://translate.element.io/accounts/profile/#subscriptions and select Element Web as Project
|
||||||
|
|
||||||
## How to check if your language already is being translated
|
## How to check if your language already is being translated
|
||||||
|
|
||||||
Go to https://translate.riot.im/projects/riot-web/ and visit the 2 sub-projects.
|
Go to https://translate.element.io/projects/element-web/ and visit the 2 sub-projects.
|
||||||
If your language is listed go to Step 2a and if not go to Step 2b
|
If your language is listed go to Step 2a and if not go to Step 2b
|
||||||
|
|
||||||
## Step 2a: Helping on existing languages.
|
## Step 2a: Helping on existing languages.
|
||||||
|
|
||||||
1. Head to one of the projects listed https://translate.riot.im/projects/riot-web/
|
1. Head to one of the projects listed https://translate.element.io/projects/element-web/
|
||||||
2. Click on the ``translate`` button on the right side of your language
|
2. Click on the ``translate`` button on the right side of your language
|
||||||
3. Fill in the translations in the writeable field. You will see the original English string and the string of your second language above.
|
3. Fill in the translations in the writeable field. You will see the original English string and the string of your second language above.
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ Head to the explanations under Steb 2b
|
||||||
|
|
||||||
## Step 2b: Adding a new language
|
## Step 2b: Adding a new language
|
||||||
|
|
||||||
1. Go to one of the projects listed https://translate.riot.im/projects/riot-web/
|
1. Go to one of the projects listed https://translate.element.io/projects/element-web/
|
||||||
2. Click the ``Start new translation`` button at the bottom
|
2. Click the ``Start new translation`` button at the bottom
|
||||||
3. Select a language
|
3. Select a language
|
||||||
4. Start translating like in 2a.3
|
4. Start translating like in 2a.3
|
||||||
|
@ -50,7 +50,7 @@ The yellow button has to be used if you are unsure about the translation but you
|
||||||
|
|
||||||
### What are "%(something)s"?
|
### What are "%(something)s"?
|
||||||
|
|
||||||
These things are variables that are expanded when displayed by Riot. They can be room names, usernames or similar. If you find one, you can move to the right place for your language, but not delete it as the variable will be missing if you do.
|
These things are variables that are expanded when displayed by Element. They can be room names, usernames or similar. If you find one, you can move to the right place for your language, but not delete it as the variable will be missing if you do.
|
||||||
|
|
||||||
A special case is `%(urlStart)s` and `%(urlEnd)s` which are used to mark the beginning of a hyperlink (i.e. `<a href="/somewhere">` and `</a>`. You must keep these markers surrounding the equivalent string in your language that needs to be hyperlinked.
|
A special case is `%(urlStart)s` and `%(urlEnd)s` which are used to mark the beginning of a hyperlink (i.e. `<a href="/somewhere">` and `</a>`. You must keep these markers surrounding the equivalent string in your language that needs to be hyperlinked.
|
||||||
|
|
||||||
|
|
|
@ -1,28 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<!-- Entitlements from electron-builder's defaults
|
|
||||||
(https://github.com/electron-userland/electron-builder/blob/master/packages/app-builder-lib/templates/entitlements.mac.plist)
|
|
||||||
nb. This does *not* include the app sandbox: at the time of adding this file,
|
|
||||||
we were using electron-builder 21.2.0 which does not have the sandbox entitlement.
|
|
||||||
Latest electron-builder does, but it appears to be causing issues:
|
|
||||||
(https://github.com/electron-userland/electron-builder/issues/4390)
|
|
||||||
-->
|
|
||||||
<!-- https://github.com/electron/electron-notarize#prerequisites -->
|
|
||||||
<key>com.apple.security.cs.allow-jit</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
|
||||||
<true/>
|
|
||||||
<!-- https://github.com/electron-userland/electron-builder/issues/3940 -->
|
|
||||||
<key>com.apple.security.cs.disable-library-validation</key>
|
|
||||||
<true/>
|
|
||||||
|
|
||||||
<!-- Our own additional entitlements (we need to access the camera and
|
|
||||||
mic for VoIP calls -->
|
|
||||||
<key>com.apple.security.device.camera</key>
|
|
||||||
<true/>
|
|
||||||
<key>com.apple.security.device.audio-input</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 13 KiB |
Before Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 3 KiB |
Before Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 5.4 KiB |
Before Width: | Height: | Size: 36 KiB |
Before Width: | Height: | Size: 13 KiB |
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
"name": "riot-web",
|
|
||||||
"productName": "Riot",
|
|
||||||
"main": "src/electron-main.js",
|
|
||||||
"version": "1.5.15",
|
|
||||||
"description": "A feature-rich client for Matrix.org",
|
|
||||||
"author": "New Vector Ltd.",
|
|
||||||
"dependencies": {
|
|
||||||
"auto-launch": "^5.0.1",
|
|
||||||
"electron-store": "^2.0.0",
|
|
||||||
"electron-window-state": "^4.1.0",
|
|
||||||
"minimist": "^1.2.0",
|
|
||||||
"png-to-ico": "^1.0.2"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,34 +0,0 @@
|
||||||
-----BEGIN CERTIFICATE-----
|
|
||||||
MIIF0jCCBLqgAwIBAgIRAISYBqZi3VvCUeSfHXF+cbwwDQYJKoZIhvcNAQELBQAw
|
|
||||||
gZExCzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
|
|
||||||
BgNVBAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTcwNQYD
|
|
||||||
VQQDEy5DT01PRE8gUlNBIEV4dGVuZGVkIFZhbGlkYXRpb24gQ29kZSBTaWduaW5n
|
|
||||||
IENBMB4XDTE3MDgyMzAwMDAwMFoXDTIwMDgyMjIzNTk1OVowgdgxETAPBgNVBAUT
|
|
||||||
CDEwODczNjYxMRMwEQYLKwYBBAGCNzwCAQMTAkdCMR0wGwYDVQQPExRQcml2YXRl
|
|
||||||
IE9yZ2FuaXphdGlvbjELMAkGA1UEBhMCR0IxETAPBgNVBBEMCFdDMVIgNEFHMQ8w
|
|
||||||
DQYDVQQIDAZMb25kb24xDzANBgNVBAcMBkxvbmRvbjEbMBkGA1UECQwSMjYgUmVk
|
|
||||||
IExpb24gU3F1YXJlMRcwFQYDVQQKDA5OZXcgVmVjdG9yIEx0ZDEXMBUGA1UEAwwO
|
|
||||||
TmV3IFZlY3RvciBMdGQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC7
|
|
||||||
X0HP3oM/SVr6PboD03ndtYTONZDcJ/GJ3EyYi6UNrcbKjuDHwPktx9hjAhNjcVkG
|
|
||||||
lmuTEPluPj9DbvjaTrers0cQsAS1vJ0RHjLfA93Flg1ys9Q6OThUMw77FtFPtiJU
|
|
||||||
z5cSYzfFAhn/4dv7BcgGptn+Mv/8CaTu+RUZJUgoSlRWcT1TREmxkzWotbblqsHO
|
|
||||||
zjDmUg20tL5/qpt6BSWsNespf5udKQFXMtqkczBcLvBLmql0vurVcQy8BibB+Q89
|
|
||||||
QKwRzwLgaIa7O8WEssFcW8uJe9s0SNtUy8ehbuoSxpA/DbHFwsiDbNA78vp7HrqM
|
|
||||||
qY6t6OIgLtDYBFCfe/btAgMBAAGjggHaMIIB1jAfBgNVHSMEGDAWgBTfj/MgDOnK
|
|
||||||
pgTYW1g3Kj2rRtyDSTAdBgNVHQ4EFgQUH+mDOdRkF3bYDxCWEaGB4lxiCxcwDgYD
|
|
||||||
VR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwEwYDVR0lBAwwCgYIKwYBBQUHAwMw
|
|
||||||
EQYJYIZIAYb4QgEBBAQDAgQQMEYGA1UdIAQ/MD0wOwYMKwYBBAGyMQECAQYBMCsw
|
|
||||||
KQYIKwYBBQUHAgEWHWh0dHBzOi8vc2VjdXJlLmNvbW9kby5jb20vQ1BTMFUGA1Ud
|
|
||||||
HwROMEwwSqBIoEaGRGh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL0NPTU9ET1JTQUV4
|
|
||||||
dGVuZGVkVmFsaWRhdGlvbkNvZGVTaWduaW5nQ0EuY3JsMIGGBggrBgEFBQcBAQR6
|
|
||||||
MHgwUAYIKwYBBQUHMAKGRGh0dHA6Ly9jcnQuY29tb2RvY2EuY29tL0NPTU9ET1JT
|
|
||||||
QUV4dGVuZGVkVmFsaWRhdGlvbkNvZGVTaWduaW5nQ0EuY3J0MCQGCCsGAQUFBzAB
|
|
||||||
hhhodHRwOi8vb2NzcC5jb21vZG9jYS5jb20wJgYDVR0RBB8wHaAbBggrBgEFBQcI
|
|
||||||
A6APMA0MC0dCLTEwODczNjYxMA0GCSqGSIb3DQEBCwUAA4IBAQBJ2aH4aixh0aiz
|
|
||||||
4WKlK+LMVLHpQ2POE3FZYNpAW7o1q2YDGEADXdGrygPE9NCGNBXKo0CAemCYNWfX
|
|
||||||
Ov/jdoiMfeqW3vrZ66oEy8OqbvJSwK1xmomWuYw3wYPWcPVG+YbWYD2CGdQu8jTz
|
|
||||||
fzAJCpvAuY3Wji3fQjiecAC7JCSB4fBHa0ALJOmiSqKQUUpkXs5kW7O0lPBnHzNF
|
|
||||||
2tQGltXMSIrq1QfFtcreMyKlwDOxPIh360dv5aHhaeSRDRKxq7uq5ikQF2gjKx4k
|
|
||||||
ieg2HRbAW6fVPpFr4zRS5umpeZV3i06i11VQQPS/mA/OBEXyaqzx4mr6B7U6ptrp
|
|
||||||
jMqiUv2w
|
|
||||||
-----END CERTIFICATE-----
|
|
|
@ -1,6 +0,0 @@
|
||||||
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 you're building the
|
|
||||||
official riot.im distribution, or you'll find your builds will replace
|
|
||||||
themselves with the riot.im build.
|
|
|
@ -1,39 +0,0 @@
|
||||||
{
|
|
||||||
"update_base_url": "https://packages.riot.im/desktop/update/",
|
|
||||||
"default_server_name": "matrix.org",
|
|
||||||
"brand": "Riot",
|
|
||||||
"integrations_ui_url": "https://scalar.vector.im/",
|
|
||||||
"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"
|
|
||||||
],
|
|
||||||
"hosting_signup_link": "https://modular.im/?utm_source=riot-web&utm_medium=web",
|
|
||||||
"bug_report_endpoint_url": "https://riot.im/bugreports/submit",
|
|
||||||
"roomDirectory": {
|
|
||||||
"servers": [
|
|
||||||
"matrix.org"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"piwik": {
|
|
||||||
"url": "https://piwik.riot.im/",
|
|
||||||
"siteId": 1,
|
|
||||||
"policyUrl": "https://matrix.org/legal/riot-im-cookie-policy"
|
|
||||||
},
|
|
||||||
"phasedRollOut": {
|
|
||||||
"feature_lazyloading": {
|
|
||||||
"offset": 1539684000000,
|
|
||||||
"period": 604800000
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"features": {
|
|
||||||
"feature_lazyloading": "enable"
|
|
||||||
},
|
|
||||||
"enable_presence_by_hs_url": {
|
|
||||||
"https://matrix.org": false,
|
|
||||||
"https://matrix-client.matrix.org": false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1 +0,0 @@
|
||||||
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 -verbose'
|
|
|
@ -1,641 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2016 Aviral Dasgupta
|
|
||||||
Copyright 2016 OpenMarket Ltd
|
|
||||||
Copyright 2018, 2019 New Vector Ltd
|
|
||||||
Copyright 2017, 2019 Michael Telatynski <7t3chguy@gmail.com>
|
|
||||||
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Squirrel on windows starts the app with various flags
|
|
||||||
// as hooks to tell us when we've been installed/uninstalled
|
|
||||||
// etc.
|
|
||||||
const checkSquirrelHooks = require('./squirrelhooks');
|
|
||||||
if (checkSquirrelHooks()) return;
|
|
||||||
|
|
||||||
const argv = require('minimist')(process.argv, {
|
|
||||||
alias: {help: "h"},
|
|
||||||
});
|
|
||||||
|
|
||||||
const {app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater, protocol} = require('electron');
|
|
||||||
const AutoLaunch = require('auto-launch');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const tray = require('./tray');
|
|
||||||
const vectorMenu = require('./vectormenu');
|
|
||||||
const webContentsHandler = require('./webcontents-handler');
|
|
||||||
const updater = require('./updater');
|
|
||||||
const protocolInit = require('./protocol');
|
|
||||||
|
|
||||||
const windowStateKeeper = require('electron-window-state');
|
|
||||||
const Store = require('electron-store');
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const afs = fs.promises;
|
|
||||||
|
|
||||||
let Seshat = null;
|
|
||||||
|
|
||||||
try {
|
|
||||||
Seshat = require('matrix-seshat');
|
|
||||||
} catch (e) {
|
|
||||||
if (e.code === "MODULE_NOT_FOUND") {
|
|
||||||
console.log("Seshat isn't installed, event indexing is disabled.");
|
|
||||||
} else {
|
|
||||||
console.warn("Seshat unexpected error:", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv["help"]) {
|
|
||||||
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://electronjs.org/docs/api/chrome-command-line-switches#supported-chrome-command-line-switches");
|
|
||||||
app.exit();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (argv['profile-dir']) {
|
|
||||||
app.setPath('userData', argv['profile-dir']);
|
|
||||||
} else if (argv['profile']) {
|
|
||||||
app.setPath('userData', `${app.getPath('userData')}-${argv['profile']}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
let vectorConfig = {};
|
|
||||||
try {
|
|
||||||
vectorConfig = require('../../webapp/config.json');
|
|
||||||
} catch (e) {
|
|
||||||
// it would be nice to check the error code here and bail if the config
|
|
||||||
// is unparseable, but we get MODULE_NOT_FOUND in the case of a missing
|
|
||||||
// file or invalid json, so node is just very unhelpful.
|
|
||||||
// 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'));
|
|
||||||
|
|
||||||
// If the local config has a homeserver defined, don't use the homeserver from the build
|
|
||||||
// config. This is to avoid a problem where Riot thinks there are multiple homeservers
|
|
||||||
// defined, and panics as a result.
|
|
||||||
const homeserverProps = ['default_is_url', 'default_hs_url', 'default_server_name', 'default_server_config'];
|
|
||||||
if (Object.keys(localConfig).find(k => homeserverProps.includes(k))) {
|
|
||||||
// Rip out all the homeserver options from the vector config
|
|
||||||
vectorConfig = Object.keys(vectorConfig)
|
|
||||||
.filter(k => !homeserverProps.includes(k))
|
|
||||||
.reduce((obj, key) => {obj[key] = vectorConfig[key]; return obj;}, {});
|
|
||||||
}
|
|
||||||
|
|
||||||
vectorConfig = Object.assign(vectorConfig, localConfig);
|
|
||||||
} catch (e) {
|
|
||||||
// Could not load local config, this is expected in most cases.
|
|
||||||
}
|
|
||||||
|
|
||||||
const eventStorePath = path.join(app.getPath('userData'), 'EventStore');
|
|
||||||
const store = new Store({ name: "electron-config" });
|
|
||||||
|
|
||||||
let eventIndex = null;
|
|
||||||
|
|
||||||
let mainWindow = null;
|
|
||||||
global.appQuitting = false;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
const trayConfig = {
|
|
||||||
icon_path: iconPath,
|
|
||||||
brand: vectorConfig.brand || 'Riot',
|
|
||||||
};
|
|
||||||
|
|
||||||
// handle uncaught errors otherwise it displays
|
|
||||||
// stack traces in popup dialogs, which is terrible (which
|
|
||||||
// it will do any time the auto update poke fails, and there's
|
|
||||||
// no other way to catch this error).
|
|
||||||
// Assuming we generally run from the console when developing,
|
|
||||||
// this is far preferable.
|
|
||||||
process.on('uncaughtException', function(error) {
|
|
||||||
console.log('Unhandled exception', error);
|
|
||||||
});
|
|
||||||
|
|
||||||
let focusHandlerAttached = false;
|
|
||||||
ipcMain.on('setBadgeCount', function(ev, count) {
|
|
||||||
app.setBadgeCount(count);
|
|
||||||
if (count === 0 && mainWindow) {
|
|
||||||
mainWindow.flashFrame(false);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('loudNotification', function() {
|
|
||||||
if (process.platform === 'win32' && mainWindow && !mainWindow.isFocused() && !focusHandlerAttached) {
|
|
||||||
mainWindow.flashFrame(true);
|
|
||||||
mainWindow.once('focus', () => {
|
|
||||||
mainWindow.flashFrame(false);
|
|
||||||
focusHandlerAttached = false;
|
|
||||||
});
|
|
||||||
focusHandlerAttached = true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let powerSaveBlockerId = null;
|
|
||||||
ipcMain.on('app_onAction', function(ev, payload) {
|
|
||||||
switch (payload.action) {
|
|
||||||
case 'call_state':
|
|
||||||
if (powerSaveBlockerId !== null && powerSaveBlocker.isStarted(powerSaveBlockerId)) {
|
|
||||||
if (payload.state === 'ended') {
|
|
||||||
powerSaveBlocker.stop(powerSaveBlockerId);
|
|
||||||
powerSaveBlockerId = null;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (powerSaveBlockerId === null && payload.state === 'connected') {
|
|
||||||
powerSaveBlockerId = powerSaveBlocker.start('prevent-display-sleep');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
autoUpdater.on('update-downloaded', (ev, releaseNotes, releaseName, releaseDate, updateURL) => {
|
|
||||||
if (!mainWindow) return;
|
|
||||||
// forward to renderer
|
|
||||||
mainWindow.webContents.send('update-downloaded', {
|
|
||||||
releaseNotes,
|
|
||||||
releaseName,
|
|
||||||
releaseDate,
|
|
||||||
updateURL,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('ipcCall', async function(ev, payload) {
|
|
||||||
if (!mainWindow) return;
|
|
||||||
|
|
||||||
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 = tray.hasTray();
|
|
||||||
break;
|
|
||||||
case 'setMinimizeToTrayEnabled':
|
|
||||||
if (args[0]) {
|
|
||||||
// Create trayIcon icon
|
|
||||||
tray.create(trayConfig);
|
|
||||||
} else {
|
|
||||||
tray.destroy();
|
|
||||||
}
|
|
||||||
store.set('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 '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,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on('seshat', async function(ev, payload) {
|
|
||||||
if (!mainWindow) return;
|
|
||||||
|
|
||||||
const sendError = (id, e) => {
|
|
||||||
const error = {
|
|
||||||
message: e.message
|
|
||||||
}
|
|
||||||
|
|
||||||
mainWindow.webContents.send('seshatReply', {
|
|
||||||
id:id,
|
|
||||||
error: error
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const args = payload.args || [];
|
|
||||||
let ret;
|
|
||||||
|
|
||||||
switch (payload.name) {
|
|
||||||
case 'supportsEventIndexing':
|
|
||||||
if (Seshat === null) ret = false;
|
|
||||||
else ret = true;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'initEventIndex':
|
|
||||||
if (eventIndex === null) {
|
|
||||||
try {
|
|
||||||
await afs.mkdir(eventStorePath, {recursive: true});
|
|
||||||
eventIndex = new Seshat(eventStorePath, {passphrase: "DEFAULT_PASSPHRASE"});
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'closeEventIndex':
|
|
||||||
eventIndex = null;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'deleteEventIndex':
|
|
||||||
const deleteFolderRecursive = async(p) => {
|
|
||||||
for (let entry of await afs.readdir(p)) {
|
|
||||||
const curPath = path.join(p, entry);
|
|
||||||
await afs.unlink(curPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
await deleteFolderRecursive(eventStorePath);
|
|
||||||
} catch (e) {
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'isEventIndexEmpty':
|
|
||||||
if (eventIndex === null) ret = true;
|
|
||||||
else ret = await eventIndex.isEmpty();
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'addEventToIndex':
|
|
||||||
try {
|
|
||||||
eventIndex.addEvent(args[0], args[1]);
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'commitLiveEvents':
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.commit();
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'searchEventIndex':
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.search(args[0]);
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'addHistoricEvents':
|
|
||||||
if (eventIndex === null) ret = false;
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.addHistoricEvents(
|
|
||||||
args[0], args[1], args[2]);
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'getStats':
|
|
||||||
if (eventIndex === null) ret = 0;
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.getStats();
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'removeCrawlerCheckpoint':
|
|
||||||
if (eventIndex === null) ret = false;
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.removeCrawlerCheckpoint(args[0]);
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'addCrawlerCheckpoint':
|
|
||||||
if (eventIndex === null) ret = false;
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.addCrawlerCheckpoint(args[0]);
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'loadFileEvents':
|
|
||||||
if (eventIndex === null) ret = [];
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.loadFileEvents(args[0]);
|
|
||||||
} catch (e) {
|
|
||||||
sendError(payload.id, e);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'loadCheckpoints':
|
|
||||||
if (eventIndex === null) ret = [];
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
ret = await eventIndex.loadCheckpoints();
|
|
||||||
} catch (e) {
|
|
||||||
ret = [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
mainWindow.webContents.send('seshatReply', {
|
|
||||||
id: payload.id,
|
|
||||||
error: "Unknown IPC Call: " + payload.name,
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mainWindow.webContents.send('seshatReply', {
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
// do this after we know we are the primary instance of the app
|
|
||||||
protocolInit();
|
|
||||||
|
|
||||||
const launcher = new AutoLaunch({
|
|
||||||
name: vectorConfig.brand || 'Riot',
|
|
||||||
isHidden: true,
|
|
||||||
mac: {
|
|
||||||
useLaunchAgent: true,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
// Register the scheme the app is served from as 'standard'
|
|
||||||
// which allows things like relative URLs and IndexedDB to
|
|
||||||
// work.
|
|
||||||
// Also mark it as secure (ie. accessing resources from this
|
|
||||||
// protocol and HTTPS won't trigger mixed content warnings).
|
|
||||||
protocol.registerSchemesAsPrivileged([{
|
|
||||||
scheme: 'vector',
|
|
||||||
privileges: {
|
|
||||||
standard: true,
|
|
||||||
secure: true,
|
|
||||||
supportFetchAPI: true,
|
|
||||||
},
|
|
||||||
}]);
|
|
||||||
|
|
||||||
app.on('ready', () => {
|
|
||||||
if (argv['devtools']) {
|
|
||||||
try {
|
|
||||||
const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer');
|
|
||||||
installExt(REACT_DEVELOPER_TOOLS)
|
|
||||||
.then((name) => console.log(`Added Extension: ${name}`))
|
|
||||||
.catch((err) => console.log('An error occurred: ', err));
|
|
||||||
installExt(REACT_PERF)
|
|
||||||
.then((name) => console.log(`Added Extension: ${name}`))
|
|
||||||
.catch((err) => console.log('An error occurred: ', err));
|
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
const parsedUrl = new URL(request.url);
|
|
||||||
if (parsedUrl.protocol !== 'vector:') {
|
|
||||||
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 (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 {
|
|
||||||
console.log('No update_base_url is defined: auto update is disabled');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load the previous window state with fallback to defaults
|
|
||||||
const mainWindowState = windowStateKeeper({
|
|
||||||
defaultWidth: 1024,
|
|
||||||
defaultHeight: 768,
|
|
||||||
});
|
|
||||||
|
|
||||||
const preloadScript = path.normalize(`${__dirname}/preload.js`);
|
|
||||||
mainWindow = global.mainWindow = new BrowserWindow({
|
|
||||||
icon: iconPath,
|
|
||||||
show: false,
|
|
||||||
autoHideMenuBar: store.get('autoHideMenuBar', true),
|
|
||||||
|
|
||||||
x: mainWindowState.x,
|
|
||||||
y: mainWindowState.y,
|
|
||||||
width: mainWindowState.width,
|
|
||||||
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('vector://vector/webapp/');
|
|
||||||
Menu.setApplicationMenu(vectorMenu);
|
|
||||||
|
|
||||||
// Create trayIcon icon
|
|
||||||
if (store.get('minimizeToTray', true)) tray.create(trayConfig);
|
|
||||||
|
|
||||||
mainWindow.once('ready-to-show', () => {
|
|
||||||
mainWindowState.manage(mainWindow);
|
|
||||||
|
|
||||||
if (!argv['hidden']) {
|
|
||||||
mainWindow.show();
|
|
||||||
} else {
|
|
||||||
// hide here explicitly because window manage above sometimes shows it
|
|
||||||
mainWindow.hide();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
mainWindow.on('closed', () => {
|
|
||||||
mainWindow = global.mainWindow = null;
|
|
||||||
});
|
|
||||||
mainWindow.on('close', (e) => {
|
|
||||||
// If we are not quitting and have a tray icon then minimize to tray
|
|
||||||
if (!global.appQuitting && (tray.hasTray() || process.platform === 'darwin')) {
|
|
||||||
// On Mac, closing the window just hides it
|
|
||||||
// (this is generally how single-window Mac apps
|
|
||||||
// behave, eg. Mail.app)
|
|
||||||
e.preventDefault();
|
|
||||||
mainWindow.hide();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
// Handle forward/backward mouse buttons in Windows
|
|
||||||
mainWindow.on('app-command', (e, cmd) => {
|
|
||||||
if (cmd === 'browser-backward' && mainWindow.webContents.canGoBack()) {
|
|
||||||
mainWindow.webContents.goBack();
|
|
||||||
} else if (cmd === 'browser-forward' && mainWindow.webContents.canGoForward()) {
|
|
||||||
mainWindow.webContents.goForward();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
webContentsHandler(mainWindow.webContents);
|
|
||||||
});
|
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
|
||||||
app.quit();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.on('activate', () => {
|
|
||||||
mainWindow.show();
|
|
||||||
});
|
|
||||||
|
|
||||||
app.on('before-quit', () => {
|
|
||||||
global.appQuitting = true;
|
|
||||||
if (mainWindow) {
|
|
||||||
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
|
|
||||||
// installer uses for the shortcut icon.
|
|
||||||
// This makes notifications work on windows 8.1 (and is
|
|
||||||
// a noop on other platforms).
|
|
||||||
app.setAppUserModelId('com.squirrel.riot-web.Riot');
|
|
|
@ -1,53 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const {app} = require('electron');
|
|
||||||
|
|
||||||
const processUrl = (url) => {
|
|
||||||
if (!global.mainWindow) return;
|
|
||||||
console.log("Handling link: ", url);
|
|
||||||
global.mainWindow.loadURL(url.replace("riot://", "vector://"));
|
|
||||||
};
|
|
||||||
|
|
||||||
module.exports = () => {
|
|
||||||
// get all args except `hidden` as it'd mean the app would not get focused
|
|
||||||
// XXX: passing args to protocol handlers only works on Windows,
|
|
||||||
// so unpackaged deep-linking and --profile passing won't work on Mac/Linux
|
|
||||||
const args = process.argv.slice(1).filter(arg => arg !== "--hidden" && arg !== "-hidden");
|
|
||||||
if (app.isPackaged) {
|
|
||||||
app.setAsDefaultProtocolClient('riot', process.execPath, args);
|
|
||||||
} else if (process.platform === 'win32') { // on Mac/Linux this would just cause the electron binary to open
|
|
||||||
// special handler for running without being packaged, e.g `electron .` by passing our app path to electron
|
|
||||||
app.setAsDefaultProtocolClient('riot', process.execPath, [app.getAppPath(), ...args]);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
// Protocol handler for macos
|
|
||||||
app.on('open-url', function(ev, url) {
|
|
||||||
ev.preventDefault();
|
|
||||||
processUrl(url);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// Protocol handler for win32/Linux
|
|
||||||
app.on('second-instance', (ev, commandLine) => {
|
|
||||||
const url = commandLine[commandLine.length - 1];
|
|
||||||
if (!url.startsWith("riot://")) return;
|
|
||||||
processUrl(url);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
|
@ -1,51 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 OpenMarket 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 path = require('path');
|
|
||||||
const spawn = require('child_process').spawn;
|
|
||||||
const {app} = require('electron');
|
|
||||||
|
|
||||||
function runUpdateExe(args, done) {
|
|
||||||
// Invokes Squirrel's Update.exe which will do things for us like create shortcuts
|
|
||||||
// Note that there's an Update.exe in the app-x.x.x directory and one in the parent
|
|
||||||
// directory: we need to run the one in the parent directory, because it discovers
|
|
||||||
// information about the app by inspecting the directory it's run from.
|
|
||||||
const updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe');
|
|
||||||
console.log(`Spawning '${updateExe}' with args '${args}'`);
|
|
||||||
spawn(updateExe, args, {
|
|
||||||
detached: true,
|
|
||||||
}).on('close', done);
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkSquirrelHooks() {
|
|
||||||
if (process.platform !== 'win32') return false;
|
|
||||||
|
|
||||||
const cmd = process.argv[1];
|
|
||||||
const target = path.basename(process.execPath);
|
|
||||||
if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
|
|
||||||
runUpdateExe(['--createShortcut=' + target + ''], app.quit);
|
|
||||||
return true;
|
|
||||||
} else if (cmd === '--squirrel-uninstall') {
|
|
||||||
runUpdateExe(['--removeShortcut=' + target + ''], app.quit);
|
|
||||||
return true;
|
|
||||||
} else if (cmd === '--squirrel-obsolete') {
|
|
||||||
app.quit();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = checkSquirrelHooks;
|
|
|
@ -1,106 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2017 Karl Glatz <karl@glatz.biz>
|
|
||||||
Copyright 2017 OpenMarket 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 {app, Tray, Menu, nativeImage} = require('electron');
|
|
||||||
const pngToIco = require('png-to-ico');
|
|
||||||
const path = require('path');
|
|
||||||
const fs = require('fs');
|
|
||||||
|
|
||||||
let trayIcon = null;
|
|
||||||
|
|
||||||
exports.hasTray = function hasTray() {
|
|
||||||
return (trayIcon !== null);
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.destroy = function() {
|
|
||||||
if (trayIcon) {
|
|
||||||
trayIcon.destroy();
|
|
||||||
trayIcon = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
exports.create = function(config) {
|
|
||||||
// no trays on darwin
|
|
||||||
if (process.platform === 'darwin' || trayIcon) return;
|
|
||||||
|
|
||||||
const toggleWin = function() {
|
|
||||||
if (global.mainWindow.isVisible() && !global.mainWindow.isMinimized()) {
|
|
||||||
global.mainWindow.hide();
|
|
||||||
} else {
|
|
||||||
if (global.mainWindow.isMinimized()) global.mainWindow.restore();
|
|
||||||
if (!global.mainWindow.isVisible()) global.mainWindow.show();
|
|
||||||
global.mainWindow.focus();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const contextMenu = Menu.buildFromTemplate([
|
|
||||||
{
|
|
||||||
label: `Show/Hide ${config.brand}`,
|
|
||||||
click: toggleWin,
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: 'Quit',
|
|
||||||
click: function() {
|
|
||||||
app.quit();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
|
|
||||||
const defaultIcon = nativeImage.createFromPath(config.icon_path);
|
|
||||||
|
|
||||||
trayIcon = new Tray(defaultIcon);
|
|
||||||
trayIcon.setToolTip(config.brand);
|
|
||||||
trayIcon.setContextMenu(contextMenu);
|
|
||||||
trayIcon.on('click', toggleWin);
|
|
||||||
|
|
||||||
let lastFavicon = null;
|
|
||||||
global.mainWindow.webContents.on('page-favicon-updated', async function(ev, favicons) {
|
|
||||||
if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) {
|
|
||||||
if (lastFavicon !== null) {
|
|
||||||
global.mainWindow.setIcon(defaultIcon);
|
|
||||||
trayIcon.setImage(defaultIcon);
|
|
||||||
lastFavicon = null;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No need to change, shortcut
|
|
||||||
if (favicons[0] === lastFavicon) return;
|
|
||||||
lastFavicon = favicons[0];
|
|
||||||
|
|
||||||
let newFavicon = nativeImage.createFromDataURL(favicons[0]);
|
|
||||||
|
|
||||||
// Windows likes ico's too much.
|
|
||||||
if (process.platform === 'win32') {
|
|
||||||
try {
|
|
||||||
const icoPath = path.join(app.getPath('temp'), 'win32_riot_icon.ico');
|
|
||||||
fs.writeFileSync(icoPath, await pngToIco(newFavicon.toPNG()));
|
|
||||||
newFavicon = nativeImage.createFromPath(icoPath);
|
|
||||||
} catch (e) {
|
|
||||||
console.error("Failed to make win32 ico", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
trayIcon.setImage(newFavicon);
|
|
||||||
global.mainWindow.setIcon(newFavicon);
|
|
||||||
});
|
|
||||||
|
|
||||||
global.mainWindow.webContents.on('page-title-updated', function(ev, title) {
|
|
||||||
trayIcon.setToolTip(title);
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,84 +0,0 @@
|
||||||
const { app, autoUpdater, ipcMain } = require('electron');
|
|
||||||
|
|
||||||
const UPDATE_POLL_INTERVAL_MS = 60 * 60 * 1000;
|
|
||||||
const INITIAL_UPDATE_DELAY_MS = 30 * 1000;
|
|
||||||
|
|
||||||
function installUpdate() {
|
|
||||||
// for some reason, quitAndInstall does not fire the
|
|
||||||
// before-quit event, so we need to set the flag here.
|
|
||||||
global.appQuitting = true;
|
|
||||||
autoUpdater.quitAndInstall();
|
|
||||||
}
|
|
||||||
|
|
||||||
function pollForUpdates() {
|
|
||||||
try {
|
|
||||||
autoUpdater.checkForUpdates();
|
|
||||||
} catch (e) {
|
|
||||||
console.log('Couldn\'t check for update', e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {};
|
|
||||||
module.exports.start = function startAutoUpdate(updateBaseUrl) {
|
|
||||||
if (updateBaseUrl.slice(-1) !== '/') {
|
|
||||||
updateBaseUrl = updateBaseUrl + '/';
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
let url;
|
|
||||||
// For reasons best known to Squirrel, the way it checks for updates
|
|
||||||
// is completely different between macOS and windows. On macOS, it
|
|
||||||
// hits a URL that either gives it a 200 with some json or
|
|
||||||
// 204 No Content. On windows it takes a base path and looks for
|
|
||||||
// files under that path.
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
// include the current version in the URL we hit. Electron doesn't add
|
|
||||||
// it anywhere (apart from the User-Agent) so it's up to us. We could
|
|
||||||
// (and previously did) just use the User-Agent, but this doesn't
|
|
||||||
// rely on NSURLConnection setting the User-Agent to what we expect,
|
|
||||||
// and also acts as a convenient cache-buster to ensure that when the
|
|
||||||
// app updates it always gets a fresh value to avoid update-looping.
|
|
||||||
url = `${updateBaseUrl}macos/?localVersion=${encodeURIComponent(app.getVersion())}`;
|
|
||||||
|
|
||||||
} else if (process.platform === 'win32') {
|
|
||||||
url = `${updateBaseUrl}win32/${process.arch}/`;
|
|
||||||
} else {
|
|
||||||
// Squirrel / electron only supports auto-update on these two platforms.
|
|
||||||
// I'm not even going to try to guess which feed style they'd use if they
|
|
||||||
// implemented it on Linux, or if it would be different again.
|
|
||||||
console.log('Auto update not supported on this platform');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (url) {
|
|
||||||
autoUpdater.setFeedURL(url);
|
|
||||||
// We check for updates ourselves rather than using 'updater' because we need to
|
|
||||||
// do it in the main process (and we don't really need to check every 10 minutes:
|
|
||||||
// every hour should be just fine for a desktop app)
|
|
||||||
// However, we still let the main window listen for the update events.
|
|
||||||
// We also wait a short time before checking for updates the first time because
|
|
||||||
// of squirrel on windows and it taking a small amount of time to release a
|
|
||||||
// lock file.
|
|
||||||
setTimeout(pollForUpdates, INITIAL_UPDATE_DELAY_MS);
|
|
||||||
setInterval(pollForUpdates, UPDATE_POLL_INTERVAL_MS);
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
// will fail if running in debug mode
|
|
||||||
console.log('Couldn\'t enable update checking', err);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ipcMain.on('install_update', installUpdate);
|
|
||||||
ipcMain.on('check_updates', pollForUpdates);
|
|
||||||
|
|
||||||
function ipcChannelSendUpdateStatus(status) {
|
|
||||||
if (global.mainWindow) {
|
|
||||||
global.mainWindow.webContents.send('check_updates', status);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
autoUpdater.on('update-available', function() {
|
|
||||||
ipcChannelSendUpdateStatus(true);
|
|
||||||
}).on('update-not-available', function() {
|
|
||||||
ipcChannelSendUpdateStatus(false);
|
|
||||||
}).on('error', function(error) {
|
|
||||||
ipcChannelSendUpdateStatus(error.message);
|
|
||||||
});
|
|
|
@ -1,144 +0,0 @@
|
||||||
/*
|
|
||||||
Copyright 2016 OpenMarket 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 {app, shell, Menu} = require('electron');
|
|
||||||
|
|
||||||
// Menu template from http://electron.atom.io/docs/api/menu/, edited
|
|
||||||
const template = [
|
|
||||||
{
|
|
||||||
label: '&Edit',
|
|
||||||
submenu: [
|
|
||||||
{ role: 'undo' },
|
|
||||||
{ role: 'redo' },
|
|
||||||
{ type: 'separator' },
|
|
||||||
{ role: 'cut' },
|
|
||||||
{ role: 'copy' },
|
|
||||||
{ role: 'paste' },
|
|
||||||
{ role: 'pasteandmatchstyle' },
|
|
||||||
{ role: 'delete' },
|
|
||||||
{ role: 'selectall' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '&View',
|
|
||||||
submenu: [
|
|
||||||
{ type: 'separator' },
|
|
||||||
{ role: 'resetzoom' },
|
|
||||||
{ role: 'zoomin', accelerator: 'CommandOrControl+=' },
|
|
||||||
{ role: 'zoomout' },
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: 'Preferences',
|
|
||||||
accelerator: 'Command+,', // Mac-only accelerator
|
|
||||||
click() { global.mainWindow.webContents.send('preferences'); },
|
|
||||||
},
|
|
||||||
{ role: 'togglefullscreen' },
|
|
||||||
{ role: 'toggledevtools' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '&Window',
|
|
||||||
role: 'window',
|
|
||||||
submenu: [
|
|
||||||
{ role: 'minimize' },
|
|
||||||
{ role: 'close' },
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: '&Help',
|
|
||||||
role: 'help',
|
|
||||||
submenu: [
|
|
||||||
{
|
|
||||||
label: 'Riot Help',
|
|
||||||
click() { shell.openExternal('https://about.riot.im/help'); },
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
// macOS has specific menu conventions...
|
|
||||||
if (process.platform === 'darwin') {
|
|
||||||
// first macOS menu is the name of the app
|
|
||||||
const name = app.getName();
|
|
||||||
template.unshift({
|
|
||||||
label: name,
|
|
||||||
submenu: [
|
|
||||||
{ role: 'about' },
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
role: 'services',
|
|
||||||
submenu: [],
|
|
||||||
},
|
|
||||||
{ type: 'separator' },
|
|
||||||
{ role: 'hide' },
|
|
||||||
{ role: 'hideothers' },
|
|
||||||
{ role: 'unhide' },
|
|
||||||
{ type: 'separator' },
|
|
||||||
{ role: 'quit' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
// Edit menu.
|
|
||||||
// This has a 'speech' section on macOS
|
|
||||||
template[1].submenu.push(
|
|
||||||
{ type: 'separator' },
|
|
||||||
{
|
|
||||||
label: 'Speech',
|
|
||||||
submenu: [
|
|
||||||
{ role: 'startspeaking' },
|
|
||||||
{ role: 'stopspeaking' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
|
|
||||||
// Window menu.
|
|
||||||
// This also has specific functionality on macOS
|
|
||||||
template[3].submenu = [
|
|
||||||
{
|
|
||||||
label: 'Close',
|
|
||||||
accelerator: 'CmdOrCtrl+W',
|
|
||||||
role: 'close',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Minimize',
|
|
||||||
accelerator: 'CmdOrCtrl+M',
|
|
||||||
role: 'minimize',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Zoom',
|
|
||||||
role: 'zoom',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
type: 'separator',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'Bring All to Front',
|
|
||||||
role: 'front',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
} else {
|
|
||||||
template.unshift({
|
|
||||||
label: '&File',
|
|
||||||
submenu: [
|
|
||||||
// For some reason, 'about' does not seem to work on windows.
|
|
||||||
/*{
|
|
||||||
role: 'about'
|
|
||||||
},*/
|
|
||||||
{ role: 'quit' },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = Menu.buildFromTemplate(template);
|
|
||||||
|
|
|
@ -1,191 +0,0 @@
|
||||||
const {clipboard, nativeImage, Menu, MenuItem, shell, dialog} = require('electron');
|
|
||||||
const url = require('url');
|
|
||||||
const fs = require('fs');
|
|
||||||
const request = require('request');
|
|
||||||
|
|
||||||
const MAILTO_PREFIX = "mailto:";
|
|
||||||
|
|
||||||
const PERMITTED_URL_SCHEMES = [
|
|
||||||
'http:',
|
|
||||||
'https:',
|
|
||||||
MAILTO_PREFIX,
|
|
||||||
];
|
|
||||||
|
|
||||||
function safeOpenURL(target) {
|
|
||||||
// openExternal passes the target to open/start/xdg-open,
|
|
||||||
// so put fairly stringent limits on what can be opened
|
|
||||||
// (for instance, open /bin/sh does indeed open a terminal
|
|
||||||
// with a shell, albeit with no arguments)
|
|
||||||
const parsedUrl = url.parse(target);
|
|
||||||
if (PERMITTED_URL_SCHEMES.indexOf(parsedUrl.protocol) > -1) {
|
|
||||||
// explicitly use the URL re-assembled by the url library,
|
|
||||||
// so we know the url parser has understood all the parts
|
|
||||||
// of the input string
|
|
||||||
const newTarget = url.format(parsedUrl);
|
|
||||||
shell.openExternal(newTarget);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function onWindowOrNavigate(ev, target) {
|
|
||||||
// always prevent the default: if something goes wrong,
|
|
||||||
// we don't want to end up opening it in the electron
|
|
||||||
// app, as we could end up opening any sort of random
|
|
||||||
// url in a window that has node scripting access.
|
|
||||||
ev.preventDefault();
|
|
||||||
safeOpenURL(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
function onLinkContextMenu(ev, params) {
|
|
||||||
let url = params.linkURL || params.srcURL;
|
|
||||||
|
|
||||||
if (url.startsWith('vector://vector/webapp')) {
|
|
||||||
url = "https://riot.im/app/" + url.substring(23);
|
|
||||||
}
|
|
||||||
|
|
||||||
const popupMenu = new Menu();
|
|
||||||
// No point trying to open blob: URLs in an external browser: it ain't gonna work.
|
|
||||||
if (!url.startsWith('blob:')) {
|
|
||||||
popupMenu.append(new MenuItem({
|
|
||||||
label: url,
|
|
||||||
click() {
|
|
||||||
safeOpenURL(url);
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
let addSaveAs = false;
|
|
||||||
if (params.mediaType && params.mediaType === 'image' && !url.startsWith('file://')) {
|
|
||||||
popupMenu.append(new MenuItem({
|
|
||||||
label: '&Copy image',
|
|
||||||
click() {
|
|
||||||
if (url.startsWith('data:')) {
|
|
||||||
clipboard.writeImage(nativeImage.createFromDataURL(url));
|
|
||||||
} else {
|
|
||||||
ev.sender.copyImageAt(params.x, params.y);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}));
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// No point offering to copy a blob: URL either
|
|
||||||
if (!url.startsWith('blob:')) {
|
|
||||||
// Special-case e-mail URLs to strip the `mailto:` like modern browsers do
|
|
||||||
if (url.startsWith(MAILTO_PREFIX)) {
|
|
||||||
popupMenu.append(new MenuItem({
|
|
||||||
label: 'Copy email &address',
|
|
||||||
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: 'Sa&ve 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();
|
|
||||||
}
|
|
||||||
|
|
||||||
function _CutCopyPasteSelectContextMenus(params) {
|
|
||||||
return [{
|
|
||||||
role: 'cut',
|
|
||||||
label: 'Cu&t',
|
|
||||||
enabled: params.editFlags.canCut,
|
|
||||||
}, {
|
|
||||||
role: 'copy',
|
|
||||||
label: '&Copy',
|
|
||||||
enabled: params.editFlags.canCopy,
|
|
||||||
}, {
|
|
||||||
role: 'paste',
|
|
||||||
label: '&Paste',
|
|
||||||
enabled: params.editFlags.canPaste,
|
|
||||||
}, {
|
|
||||||
role: 'pasteandmatchstyle',
|
|
||||||
enabled: params.editFlags.canPaste,
|
|
||||||
}, {
|
|
||||||
role: 'selectall',
|
|
||||||
label: "Select &All",
|
|
||||||
enabled: params.editFlags.canSelectAll,
|
|
||||||
}];
|
|
||||||
}
|
|
||||||
|
|
||||||
function onSelectedContextMenu(ev, params) {
|
|
||||||
const items = _CutCopyPasteSelectContextMenus(params);
|
|
||||||
const popupMenu = Menu.buildFromTemplate(items);
|
|
||||||
|
|
||||||
// popup() requires an options object even for no options
|
|
||||||
popupMenu.popup({});
|
|
||||||
ev.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
function onEditableContextMenu(ev, params) {
|
|
||||||
const items = [
|
|
||||||
{ role: 'undo' },
|
|
||||||
{ role: 'redo', enabled: params.editFlags.canRedo },
|
|
||||||
{ type: 'separator' },
|
|
||||||
].concat(_CutCopyPasteSelectContextMenus(params));
|
|
||||||
|
|
||||||
const popupMenu = Menu.buildFromTemplate(items);
|
|
||||||
|
|
||||||
// popup() requires an options object even for no options
|
|
||||||
popupMenu.popup({});
|
|
||||||
ev.preventDefault();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = (webContents) => {
|
|
||||||
webContents.on('new-window', onWindowOrNavigate);
|
|
||||||
webContents.on('will-navigate', (ev, target) => {
|
|
||||||
if (target.startsWith("vector://")) return;
|
|
||||||
return onWindowOrNavigate(ev, target);
|
|
||||||
});
|
|
||||||
|
|
||||||
webContents.on('context-menu', function(ev, params) {
|
|
||||||
if (params.linkURL || params.srcURL) {
|
|
||||||
onLinkContextMenu(ev, params);
|
|
||||||
} else if (params.selectionText) {
|
|
||||||
onSelectedContextMenu(ev, params);
|
|
||||||
} else if (params.isEditable) {
|
|
||||||
onEditableContextMenu(ev, params);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
};
|
|
|
@ -1,837 +0,0 @@
|
||||||
# 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.3"
|
|
||||||
resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.3.tgz#3db5c0765545ab8637be71f333a104a965a9ca3f"
|
|
||||||
integrity sha512-+bMdgqjMN/Z77a6NlY/I3U5LlRDbnmaAk6lDveAPKwSpcPM4tKAuYsvYF8xjhOPXhOYGe/73vVLVez5PW+jqhw==
|
|
||||||
|
|
||||||
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=
|
|
|
@ -1,11 +1,12 @@
|
||||||
This directory contains the config files and deployment scripts for the official
|
This directory contains the config files and deployment scripts for the official
|
||||||
riot.im distribution of Riot Web at https://riot.im.
|
element.io distribution of Element Web.
|
||||||
|
|
||||||
You probably do not want to build with this config unless you're building the
|
You probably do not want to build with this config unless you're building the
|
||||||
official riot.im distribution, but these files may be useful if you want to
|
official element.io distribution, but these files may be useful if you want to
|
||||||
inspect the configuration used there.
|
inspect the configuration used there.
|
||||||
|
|
||||||
Riot Desktop uses a separate config (see electron_app/riot.im/config.json).
|
Element Desktop uses a separate config (see
|
||||||
|
https://github.com/vector-im/element-desktop/tree/develop/element.io).
|
||||||
|
|
||||||
Deployment scripts (such as app/deploy.py) are meant to be run on the web server
|
Deployment scripts (such as app/deploy.py) are meant to be run on the web server
|
||||||
hosting the Riot installation.
|
hosting the Element installation.
|
52
element.io/app/config.json
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
{
|
||||||
|
"default_server_name": "matrix.org",
|
||||||
|
"brand": "Element",
|
||||||
|
"integrations_ui_url": "https://scalar.vector.im/",
|
||||||
|
"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"
|
||||||
|
],
|
||||||
|
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
|
||||||
|
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||||
|
"showLabsSettings": false,
|
||||||
|
"piwik": {
|
||||||
|
"url": "https://piwik.riot.im/",
|
||||||
|
"siteId": 1,
|
||||||
|
"policyUrl": "https://element.io/cookie-policy"
|
||||||
|
},
|
||||||
|
"roomDirectory": {
|
||||||
|
"servers": [
|
||||||
|
"matrix.org",
|
||||||
|
"gitter.im",
|
||||||
|
"libera.chat"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"enable_presence_by_hs_url": {
|
||||||
|
"https://matrix.org": false,
|
||||||
|
"https://matrix-client.matrix.org": false
|
||||||
|
},
|
||||||
|
"terms_and_conditions_links": [
|
||||||
|
{
|
||||||
|
"url": "https://element.io/privacy",
|
||||||
|
"text": "Privacy Policy"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://element.io/cookie-policy",
|
||||||
|
"text": "Cookie Policy"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"hostSignup": {
|
||||||
|
"brand": "Element Home",
|
||||||
|
"cookiePolicyUrl": "https://element.io/cookie-policy",
|
||||||
|
"domains": [
|
||||||
|
"matrix.org"
|
||||||
|
],
|
||||||
|
"privacyPolicyUrl": "https://element.io/privacy",
|
||||||
|
"termsOfServiceUrl": "https://element.io/terms-of-service",
|
||||||
|
"url": "https://ems.element.io/element-home/in-app-loader"
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
#
|
#
|
||||||
# download and unpack a riot-web tarball.
|
# download and unpack a element-web tarball.
|
||||||
#
|
#
|
||||||
# Allows `bundles` to be extracted to a common directory, and a link to
|
# Allows `bundles` to be extracted to a common directory, and a link to
|
||||||
# config.json to be added.
|
# config.json to be added.
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"default_server_name": "matrix.org",
|
"default_server_name": "matrix.org",
|
||||||
"brand": "Riot",
|
"brand": "Element",
|
||||||
"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": [
|
||||||
|
@ -10,18 +10,19 @@
|
||||||
"https://scalar-staging.vector.im/api",
|
"https://scalar-staging.vector.im/api",
|
||||||
"https://scalar-staging.riot.im/scalar/api"
|
"https://scalar-staging.riot.im/scalar/api"
|
||||||
],
|
],
|
||||||
"hosting_signup_link": "https://modular.im/?utm_source=riot-web&utm_medium=web",
|
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
|
||||||
"bug_report_endpoint_url": "https://riot.im/bugreports/submit",
|
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||||
"features": {
|
"showLabsSettings": true,
|
||||||
},
|
|
||||||
"piwik": {
|
"piwik": {
|
||||||
"url": "https://piwik.riot.im/",
|
"url": "https://piwik.riot.im/",
|
||||||
"siteId": 1,
|
"siteId": 1,
|
||||||
"policyUrl": "https://matrix.org/legal/riot-im-cookie-policy"
|
"policyUrl": "https://element.io/cookie-policy"
|
||||||
},
|
},
|
||||||
"roomDirectory": {
|
"roomDirectory": {
|
||||||
"servers": [
|
"servers": [
|
||||||
"matrix.org"
|
"matrix.org",
|
||||||
|
"gitter.im",
|
||||||
|
"libera.chat"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"enable_presence_by_hs_url": {
|
"enable_presence_by_hs_url": {
|
||||||
|
@ -30,12 +31,22 @@
|
||||||
},
|
},
|
||||||
"terms_and_conditions_links": [
|
"terms_and_conditions_links": [
|
||||||
{
|
{
|
||||||
"url": "https://riot.im/privacy",
|
"url": "https://element.io/privacy",
|
||||||
"text": "Privacy Policy"
|
"text": "Privacy Policy"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://matrix.org/legal/riot-im-cookie-policy",
|
"url": "https://element.io/cookie-policy",
|
||||||
"text": "Cookie Policy"
|
"text": "Cookie Policy"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"hostSignup": {
|
||||||
|
"brand": "Element Home",
|
||||||
|
"cookiePolicyUrl": "https://element.io/cookie-policy",
|
||||||
|
"domains": [
|
||||||
|
"matrix.org"
|
||||||
|
],
|
||||||
|
"privacyPolicyUrl": "https://element.io/privacy",
|
||||||
|
"termsOfServiceUrl": "https://element.io/terms-of-service",
|
||||||
|
"url": "https://ems.element.io/element-home/in-app-loader"
|
||||||
|
}
|
||||||
}
|
}
|
249
package.json
|
@ -1,13 +1,11 @@
|
||||||
{
|
{
|
||||||
"name": "riot-web",
|
"name": "element-web",
|
||||||
"productName": "Riot",
|
"version": "1.7.32",
|
||||||
"main": "electron_app/src/electron-main.js",
|
|
||||||
"version": "1.5.15",
|
|
||||||
"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": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/vector-im/riot-web"
|
"url": "https://github.com/vector-im/element-web"
|
||||||
},
|
},
|
||||||
"license": "Apache-2.0",
|
"license": "Apache-2.0",
|
||||||
"files": [
|
"files": [
|
||||||
|
@ -31,195 +29,150 @@
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"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",
|
"diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && matrix-gen-i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
|
||||||
"reskindex": "reskindex -h src/header",
|
"reskindex": "reskindex -h src/header",
|
||||||
"reskindex:watch": "reskindex -h src/header -w",
|
"reskindex:watch": "reskindex -h src/header -w",
|
||||||
"reskindex:watch-react": "node scripts/yarn-sub.js matrix-react-sdk reskindex:watch",
|
"reskindex:watch-react": "node scripts/yarn-sub.js matrix-react-sdk reskindex:watch",
|
||||||
"clean": "rimraf lib webapp electron_app/dist",
|
"clean": "rimraf lib webapp",
|
||||||
"build": "yarn clean && yarn build:genfiles && yarn build:compile && yarn build:types && yarn build:bundle",
|
"build": "yarn clean && yarn build:genfiles && yarn build:bundle",
|
||||||
"build-stats": "yarn clean && yarn build:genfiles && yarn build:compile && yarn build:types && yarn build:bundle-stats",
|
"build-stats": "yarn clean && yarn build:genfiles && yarn build:bundle-stats",
|
||||||
"build:jitsi": "scripts/build-jitsi.sh",
|
"build:jitsi": "node scripts/build-jitsi.js",
|
||||||
"build:res": "node scripts/copy-res.js",
|
"build:res": "node scripts/copy-res.js",
|
||||||
"build:genfiles": "yarn reskindex && yarn build:res && yarn build:jitsi",
|
"build:genfiles": "yarn reskindex && yarn build:res && yarn build:jitsi",
|
||||||
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
|
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
|
||||||
"build:compile": "babel -d lib --verbose --extensions \".ts,.js,.tsx\" src",
|
"build:bundle": "webpack --progress --bail --mode production",
|
||||||
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production",
|
"build:bundle-stats": "webpack --progress --bail --mode production --json > webpack-stats.json",
|
||||||
"build:bundle-stats": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production --json > webpack-stats.json",
|
|
||||||
"build:electron": "yarn build && yarn install:electron && electron-builder -wml --ia32 --x64",
|
|
||||||
"build:electron:linux": "yarn build && electron-builder -l --x64",
|
|
||||||
"build:electron:macos": "yarn build && electron-builder -m --x64",
|
|
||||||
"build:electron:windows": "yarn build && electron-builder -w --ia32 --x64",
|
|
||||||
"build:types": "tsc --emitDeclarationOnly --jsx react",
|
|
||||||
"install:electron": "electron-builder install-app-deps",
|
|
||||||
"dist": "scripts/package.sh",
|
"dist": "scripts/package.sh",
|
||||||
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n reskindex,reskindex-react,res,riot-js \"yarn reskindex:watch\" \"yarn reskindex:watch-react\" \"yarn start:res\" \"yarn start:js\"",
|
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n reskindex,reskindex-react,res,element-js \"yarn reskindex:watch\" \"yarn reskindex:watch-react\" \"yarn start:res\" \"yarn start:js\"",
|
||||||
|
"start:https": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n reskindex,reskindex-react,res,element-js \"yarn reskindex:watch\" \"yarn reskindex:watch-react\" \"yarn start:res\" \"yarn start:js --https\"",
|
||||||
"start:res": "yarn build:jitsi && node scripts/copy-res.js -w",
|
"start:res": "yarn build:jitsi && node scripts/copy-res.js -w",
|
||||||
"start:js": "webpack-dev-server --host=0.0.0.0 --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --progress --mode development",
|
"start:js": "webpack-dev-server --host=0.0.0.0 --output-filename=bundles/_dev_/[name].js --output-chunk-filename=bundles/_dev_/[name].js -w --progress --mode development --disable-host-check",
|
||||||
"electron": "yarn build && yarn install:electron && electron .",
|
"lint": "yarn lint:types && yarn lint:js && yarn lint:style",
|
||||||
"lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style",
|
|
||||||
"lint:js": "eslint src",
|
"lint:js": "eslint src",
|
||||||
"lint:ts": "echo 'We don't actually have a typescript linter at this layer because tslint is being removed from our stack. Presumably your TS is fine.'",
|
|
||||||
"lint:types": "tsc --noEmit --jsx react",
|
"lint:types": "tsc --noEmit --jsx react",
|
||||||
"lint:style": "stylelint 'res/css/**/*.scss'",
|
"lint:style": "stylelint 'res/css/**/*.scss'",
|
||||||
"test": "jest"
|
"test": "jest"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@matrix-org/olm": "https://gitlab.matrix.org/api/v4/projects/27/packages/npm/@matrix-org/olm/-/@matrix-org/olm-3.2.3.tgz",
|
||||||
"browser-request": "^0.3.3",
|
"browser-request": "^0.3.3",
|
||||||
"favico.js": "^0.3.10",
|
|
||||||
"gfm.css": "^1.1.2",
|
"gfm.css": "^1.1.2",
|
||||||
"highlight.js": "^9.13.1",
|
"highlight.js": "^10.5.0",
|
||||||
|
"jsrsasign": "^10.2.0",
|
||||||
|
"katex": "^0.12.0",
|
||||||
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
|
"matrix-js-sdk": "github:matrix-org/matrix-js-sdk#develop",
|
||||||
"matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop",
|
"matrix-react-sdk": "github:matrix-org/matrix-react-sdk#develop",
|
||||||
"olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz",
|
"matrix-widget-api": "^0.1.0-beta.15",
|
||||||
"postcss-easings": "^2.0.0",
|
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"react": "^16.9.0",
|
"react": "^17.0.2",
|
||||||
"react-dom": "^16.9.0",
|
"react-dom": "^17.0.2",
|
||||||
"sanitize-html": "^1.19.1",
|
"sanitize-html": "^2.3.2",
|
||||||
"ua-parser-js": "^0.7.19"
|
"ua-parser-js": "^0.7.24"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.7.5",
|
"@babel/core": "^7.12.10",
|
||||||
"@babel/core": "^7.7.5",
|
"@babel/eslint-parser": "^7.12.10",
|
||||||
"@babel/plugin-proposal-class-properties": "^7.7.4",
|
"@babel/eslint-plugin": "^7.12.10",
|
||||||
"@babel/plugin-proposal-decorators": "^7.7.4",
|
"@babel/plugin-proposal-class-properties": "^7.12.1",
|
||||||
"@babel/plugin-proposal-export-default-from": "^7.7.4",
|
"@babel/plugin-proposal-decorators": "^7.12.12",
|
||||||
"@babel/plugin-proposal-numeric-separator": "^7.7.4",
|
"@babel/plugin-proposal-export-default-from": "^7.12.1",
|
||||||
"@babel/plugin-proposal-object-rest-spread": "^7.7.4",
|
"@babel/plugin-proposal-nullish-coalescing-operator": "^7.12.1",
|
||||||
"@babel/plugin-syntax-dynamic-import": "^7.7.4",
|
"@babel/plugin-proposal-numeric-separator": "^7.12.7",
|
||||||
"@babel/plugin-transform-flow-comments": "^7.7.4",
|
"@babel/plugin-proposal-object-rest-spread": "^7.12.1",
|
||||||
"@babel/plugin-transform-runtime": "^7.7.6",
|
"@babel/plugin-proposal-optional-chaining": "^7.12.7",
|
||||||
"@babel/preset-env": "^7.7.6",
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
||||||
"@babel/preset-flow": "^7.7.4",
|
"@babel/plugin-transform-runtime": "^7.12.10",
|
||||||
"@babel/preset-react": "^7.7.4",
|
"@babel/preset-env": "^7.12.11",
|
||||||
"@babel/preset-typescript": "^7.7.4",
|
"@babel/preset-react": "^7.12.10",
|
||||||
"@babel/register": "^7.7.4",
|
"@babel/preset-typescript": "^7.12.7",
|
||||||
"@babel/runtime": "^7.7.6",
|
"@babel/register": "^7.12.10",
|
||||||
"@types/jest": "^25.2.1",
|
"@babel/runtime": "^7.12.5",
|
||||||
"@types/react": "16.9",
|
"@principalstudio/html-webpack-inject-preload": "^1.2.7",
|
||||||
"@types/react-dom": "^16.9.4",
|
"@types/flux": "^3.1.9",
|
||||||
"autoprefixer": "^9.7.3",
|
"@types/modernizr": "^3.5.3",
|
||||||
"babel-eslint": "^10.0.3",
|
"@types/node": "^14.14.22",
|
||||||
"babel-jest": "^24.9.0",
|
"@types/react": "^17.0.2",
|
||||||
"babel-loader": "^8.0.6",
|
"@types/react-dom": "^17.0.2",
|
||||||
"canvas": "^2.6.1",
|
"@types/sanitize-html": "^2.3.1",
|
||||||
"chokidar": "^3.3.1",
|
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||||
"concurrently": "^4.0.1",
|
"@typescript-eslint/parser": "^4.17.0",
|
||||||
"cpx": "^1.3.2",
|
"autoprefixer": "^9.8.6",
|
||||||
"cross-env": "^6.0.3",
|
"babel-jest": "^26.6.3",
|
||||||
"css-loader": "^3.3.2",
|
"babel-loader": "^8.2.2",
|
||||||
"electron-builder": "^22.3.2",
|
"chokidar": "^3.5.1",
|
||||||
"electron-builder-squirrel-windows": "^22.3.2",
|
"concurrently": "^5.3.0",
|
||||||
"electron-devtools-installer": "^2.2.4",
|
"cpx": "^1.5.0",
|
||||||
"electron-notarize": "^0.2.0",
|
"css-loader": "^3.6.0",
|
||||||
"eslint": "^5.8.0",
|
"eslint": "7.18.0",
|
||||||
"eslint-config-google": "^0.7.1",
|
"eslint-config-google": "^0.14.0",
|
||||||
"eslint-plugin-babel": "^4.1.2",
|
"eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main",
|
||||||
"eslint-plugin-flowtype": "^2.50.3",
|
"eslint-plugin-react": "^7.22.0",
|
||||||
"eslint-plugin-jest": "^23.0.4",
|
"eslint-plugin-react-hooks": "^4.2.0",
|
||||||
"eslint-plugin-react": "^7.11.1",
|
|
||||||
"eslint-plugin-react-hooks": "^2.2.0",
|
|
||||||
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
"extract-text-webpack-plugin": "^4.0.0-beta.0",
|
||||||
"fake-indexeddb": "^3.0.0",
|
"fake-indexeddb": "^3.1.2",
|
||||||
"file-loader": "^5.0.2",
|
"file-loader": "^5.1.0",
|
||||||
"fs-extra": "^0.30.0",
|
"fs-extra": "^0.30.0",
|
||||||
"html-webpack-plugin": "^3.2.0",
|
"html-webpack-plugin": "^4.5.2",
|
||||||
"jest": "^24.9.0",
|
"jest": "^26.6.3",
|
||||||
"jest-environment-jsdom-fourteen": "^1.0.1",
|
"jest-environment-jsdom-sixteen": "^1.0.3",
|
||||||
"json-loader": "^0.5.3",
|
"json-loader": "^0.5.7",
|
||||||
"loader-utils": "^1.2.3",
|
"loader-utils": "^1.4.0",
|
||||||
"matrix-mock-request": "^1.2.3",
|
"matrix-mock-request": "^1.2.3",
|
||||||
"matrix-react-test-utils": "^0.2.2",
|
"matrix-react-test-utils": "^0.2.3",
|
||||||
"mini-css-extract-plugin": "^0.8.0",
|
"matrix-web-i18n": "github:matrix-org/matrix-web-i18n",
|
||||||
"minimist": "^1.2.0",
|
"mini-css-extract-plugin": "^0.12.0",
|
||||||
"mkdirp": "^0.5.1",
|
"minimist": "^1.2.5",
|
||||||
"modernizr": "^3.6.0",
|
"mkdirp": "^1.0.4",
|
||||||
"optimize-css-assets-webpack-plugin": "^5.0.3",
|
"modernizr": "^3.11.7",
|
||||||
|
"node-fetch": "^2.6.1",
|
||||||
|
"optimize-css-assets-webpack-plugin": "^5.0.4",
|
||||||
|
"postcss-easings": "^2.0.0",
|
||||||
"postcss-extend": "^1.0.5",
|
"postcss-extend": "^1.0.5",
|
||||||
"postcss-hexrgba": "^2.0.0",
|
"postcss-hexrgba": "^2.0.1",
|
||||||
"postcss-import": "^12.0.1",
|
"postcss-import": "^12.0.1",
|
||||||
"postcss-loader": "^3.0.0",
|
"postcss-loader": "^3.0.0",
|
||||||
"postcss-mixins": "^6.2.3",
|
"postcss-mixins": "^6.2.3",
|
||||||
"postcss-nested": "^4.2.1",
|
"postcss-nested": "^4.2.3",
|
||||||
"postcss-preset-env": "^6.7.0",
|
"postcss-preset-env": "^6.7.0",
|
||||||
"postcss-scss": "^2.0.0",
|
"postcss-scss": "^2.1.1",
|
||||||
"postcss-simple-vars": "^5.0.2",
|
"postcss-simple-vars": "^5.0.2",
|
||||||
"postcss-strip-inline-comments": "^0.1.5",
|
"postcss-strip-inline-comments": "^0.1.5",
|
||||||
"rimraf": "^2.4.3",
|
"rimraf": "^3.0.2",
|
||||||
"shell-escape": "^0.2.0",
|
"shell-escape": "^0.2.0",
|
||||||
"stylelint": "^12.0.1",
|
"simple-proxy-agent": "^1.1.0",
|
||||||
"terser-webpack-plugin": "^2.3.0",
|
"stylelint": "^13.9.0",
|
||||||
"typescript": "^3.7.3",
|
"stylelint-config-standard": "^20.0.0",
|
||||||
"webpack": "^4.41.2",
|
"stylelint-scss": "^3.18.0",
|
||||||
"webpack-cli": "^3.3.10",
|
"terser-webpack-plugin": "^2.3.8",
|
||||||
"webpack-dev-server": "^3.9.0"
|
"typescript": "^4.1.3",
|
||||||
},
|
"webpack": "^4.46.0",
|
||||||
"build": {
|
"webpack-cli": "^3.3.12",
|
||||||
"appId": "im.riot.app",
|
"webpack-dev-server": "^3.11.2",
|
||||||
"electronVersion": "7.1.14",
|
"worker-loader": "^2.0.0"
|
||||||
"files": [
|
|
||||||
"node_modules/**",
|
|
||||||
"src/**"
|
|
||||||
],
|
|
||||||
"extraResources": [
|
|
||||||
{
|
|
||||||
"from": "electron_app/img",
|
|
||||||
"to": "img"
|
|
||||||
},
|
|
||||||
"webapp/**/*"
|
|
||||||
],
|
|
||||||
"linux": {
|
|
||||||
"target": "deb",
|
|
||||||
"category": "Network;InstantMessaging;Chat",
|
|
||||||
"maintainer": "support@riot.im",
|
|
||||||
"desktop": {
|
|
||||||
"StartupWMClass": "riot"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"mac": {
|
|
||||||
"category": "public.app-category.social-networking",
|
|
||||||
"darkModeSupport": true
|
|
||||||
},
|
|
||||||
"win": {
|
|
||||||
"target": {
|
|
||||||
"target": "squirrel"
|
|
||||||
},
|
|
||||||
"sign": "scripts/electron_winSign"
|
|
||||||
},
|
|
||||||
"directories": {
|
|
||||||
"buildResources": "electron_app/build",
|
|
||||||
"output": "electron_app/dist",
|
|
||||||
"app": "electron_app"
|
|
||||||
},
|
|
||||||
"afterSign": "scripts/electron_afterSign.js",
|
|
||||||
"protocols": [
|
|
||||||
{
|
|
||||||
"name": "riot",
|
|
||||||
"schemes": [
|
|
||||||
"riot"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"modulePathIgnorePatterns": [
|
"testEnvironment": "jest-environment-jsdom-sixteen",
|
||||||
"<rootDir>/electron_app"
|
|
||||||
],
|
|
||||||
"testEnvironment": "jest-environment-jsdom-fourteen",
|
|
||||||
"testMatch": [
|
"testMatch": [
|
||||||
"<rootDir>/test/**/*-test.*"
|
"<rootDir>/test/**/*-test.js"
|
||||||
],
|
],
|
||||||
"setupFilesAfterEnv": [
|
"setupFilesAfterEnv": [
|
||||||
"<rootDir>/node_modules/matrix-react-sdk/test/setupTests.js"
|
"<rootDir>/node_modules/matrix-react-sdk/test/setupTests.js"
|
||||||
],
|
],
|
||||||
"moduleNameMapper": {
|
"moduleNameMapper": {
|
||||||
|
"\\.(css|scss)$": "<rootDir>/__mocks__/cssMock.js",
|
||||||
"\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/imageMock.js",
|
"\\.(gif|png|svg|ttf|woff2)$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/imageMock.js",
|
||||||
"\\$webapp/i18n/languages.json": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/languages.json",
|
"\\$webapp/i18n/languages.json": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/languages.json",
|
||||||
"^browser-request$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/browser-request.js",
|
"^browser-request$": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/browser-request.js",
|
||||||
"^react$": "<rootDir>/node_modules/react",
|
"^react$": "<rootDir>/node_modules/react",
|
||||||
"^react-dom$": "<rootDir>/node_modules/react-dom",
|
"^react-dom$": "<rootDir>/node_modules/react-dom",
|
||||||
"^matrix-js-sdk$": "<rootDir>/node_modules/matrix-js-sdk/src",
|
"^matrix-js-sdk$": "<rootDir>/node_modules/matrix-js-sdk/src",
|
||||||
"^matrix-react-sdk$": "<rootDir>/node_modules/matrix-react-sdk/src"
|
"^matrix-react-sdk$": "<rootDir>/node_modules/matrix-react-sdk/src",
|
||||||
|
"decoderWorker\\.min\\.js": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||||
|
"decoderWorker\\.min\\.wasm": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||||
|
"waveWorker\\.min\\.js": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||||
|
"context-filter-polyfill": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/empty.js",
|
||||||
|
"FontManager.ts": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/FontManager.js",
|
||||||
|
"workers/(.+)\\.worker\\.ts": "<rootDir>/node_modules/matrix-react-sdk/__mocks__/workerMock.js"
|
||||||
},
|
},
|
||||||
"transformIgnorePatterns": [
|
"transformIgnorePatterns": [
|
||||||
"/node_modules/(?!matrix-js-sdk).+$",
|
"/node_modules/(?!matrix-js-sdk).+$",
|
||||||
|
|
18
release.sh
|
@ -1,6 +1,6 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# Script to perform a release of riot-web.
|
# Script to perform a release of element-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
|
||||||
|
@ -38,13 +38,13 @@ do
|
||||||
echo "Upgrading $i to $latestver..."
|
echo "Upgrading $i to $latestver..."
|
||||||
yarn add -E $i@$latestver
|
yarn add -E $i@$latestver
|
||||||
git add -u
|
git add -u
|
||||||
# The `-e` flag opens the editor and gives you a chance to check
|
git commit -m "Upgrade $i to $latestver"
|
||||||
# the upgrade for correctness.
|
|
||||||
git commit -m "Upgrade $i to $latestver" -e
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
./node_modules/matrix-js-sdk/release.sh -n -z "$orig_args"
|
||||||
|
|
||||||
release="${1#v}"
|
release="${1#v}"
|
||||||
tag="v${release}"
|
tag="v${release}"
|
||||||
prerelease=0
|
prerelease=0
|
||||||
|
@ -54,16 +54,6 @@ prerelease=0
|
||||||
# with a hyphen is a prerelease.
|
# with a hyphen is a prerelease.
|
||||||
echo $release | grep -q '-' && prerelease=1
|
echo $release | grep -q '-' && prerelease=1
|
||||||
|
|
||||||
# bump Electron's package.json first
|
|
||||||
echo "electron yarn version"
|
|
||||||
cd electron_app
|
|
||||||
yarn version --no-git-tag-version --new-version "$release"
|
|
||||||
git commit package.json -m "$tag"
|
|
||||||
|
|
||||||
cd ..
|
|
||||||
|
|
||||||
./node_modules/matrix-js-sdk/release.sh -u vector-im -z "$orig_args"
|
|
||||||
|
|
||||||
if [ $prerelease -eq 0 ]
|
if [ $prerelease -eq 0 ]
|
||||||
then
|
then
|
||||||
# For a release, reset SDK deps back to the `develop` branch.
|
# For a release, reset SDK deps back to the `develop` branch.
|
||||||
|
|
101
res/css/structures/ErrorView.scss
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
Copyright 2020 New Vector Ltd
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// import font-size variables manually, ideally this scss would get loaded by the theme which has all variables in context
|
||||||
|
@import "../../../node_modules/matrix-react-sdk/res/css/_font-sizes.scss";
|
||||||
|
|
||||||
|
.mx_ErrorView {
|
||||||
|
background: #c5e0f7;
|
||||||
|
background: -moz-linear-gradient(top, #c5e0f7 0%, #ffffff 100%);
|
||||||
|
background: -webkit-linear-gradient(top, #c5e0f7 0%, #ffffff 100%);
|
||||||
|
background: linear-gradient(to bottom, #c5e0f7 0%, #ffffff 100%);
|
||||||
|
filter: progid:dximagetransform.microsoft.gradient(startColorstr='#c5e0f7', endColorstr='#ffffff', GradientType=0);
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
|
||||||
|
width: 100%;
|
||||||
|
min-height: 100%;
|
||||||
|
height: auto;
|
||||||
|
color: #000;
|
||||||
|
|
||||||
|
.mx_ErrorView_container {
|
||||||
|
max-width: 680px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Button {
|
||||||
|
border: 0;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: $font-18px;
|
||||||
|
margin-left: 4px;
|
||||||
|
margin-right: 4px;
|
||||||
|
min-width: 80px;
|
||||||
|
background-color: #03b381;
|
||||||
|
color: #fff;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 12px 22px;
|
||||||
|
word-break: break-word;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Center {
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HomePage_header {
|
||||||
|
color: #2e2f32;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
font-size: $font-16px;
|
||||||
|
h1 {
|
||||||
|
font-size: $font-32px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: $font-24px;
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HomePage_col {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HomePage_row {
|
||||||
|
flex: 1 1 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_HomePage_logo {
|
||||||
|
margin: auto 20px auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2 {
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_Spacer {
|
||||||
|
margin-top: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mx_FooterLink {
|
||||||
|
color: #368bd6;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
107
res/decoder-ring/datatypes.js
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/*
|
||||||
|
* Quick-n-dirty algebraic datatypes.
|
||||||
|
*
|
||||||
|
* These let us handle the possibility of failure without having to constantly write code to check for it.
|
||||||
|
* We can apply all of the transformations we need as if the data is present using `map`.
|
||||||
|
* If there's a None, or a FetchError, or a Pending, those are left untouched.
|
||||||
|
*
|
||||||
|
* I've used perhaps an odd bit of terminology from scalaz in `fold`. This is basically a `switch` statement:
|
||||||
|
* You pass it a set of functions to handle the various different states of the datatype, and if it finds the
|
||||||
|
* function it'll call it on its value.
|
||||||
|
*
|
||||||
|
* It's handy to have this in functional style when dealing with React as we can dispatch different ways of rendering
|
||||||
|
* really simply:
|
||||||
|
* ```
|
||||||
|
* bundleFetchStatus.fold({
|
||||||
|
* some: (fetchStatus) => <ProgressBar fetchsStatus={fetchStatus} />,
|
||||||
|
* }),
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
class Optional {
|
||||||
|
static from(value) {
|
||||||
|
return value && Some.of(value) || None;
|
||||||
|
}
|
||||||
|
map(f) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
flatMap(f) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
fold({ none }) {
|
||||||
|
return none && none();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Some extends Optional {
|
||||||
|
constructor(value) {
|
||||||
|
super();
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
map(f) {
|
||||||
|
return Some.of(f(this.value));
|
||||||
|
}
|
||||||
|
flatMap(f) {
|
||||||
|
return f(this.value);
|
||||||
|
}
|
||||||
|
fold({ some }) {
|
||||||
|
return some && some(this.value);
|
||||||
|
}
|
||||||
|
static of(value) {
|
||||||
|
return new Some(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const None = new Optional();
|
||||||
|
|
||||||
|
class FetchStatus {
|
||||||
|
constructor(opt = {}) {
|
||||||
|
this.opt = { at: Date.now(), ...opt };
|
||||||
|
}
|
||||||
|
map(f) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
flatMap(f) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Success extends FetchStatus {
|
||||||
|
static of(value) {
|
||||||
|
return new Success(value);
|
||||||
|
}
|
||||||
|
constructor(value, opt) {
|
||||||
|
super(opt);
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
map(f) {
|
||||||
|
return new Success(f(this.value), this.opt);
|
||||||
|
}
|
||||||
|
flatMap(f) {
|
||||||
|
return f(this.value, this.opt);
|
||||||
|
}
|
||||||
|
fold({ success }) {
|
||||||
|
return success instanceof Function ? success(this.value, this.opt) : undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class Pending extends FetchStatus {
|
||||||
|
static of(opt) {
|
||||||
|
return new Pending(opt);
|
||||||
|
}
|
||||||
|
constructor(opt) {
|
||||||
|
super(opt);
|
||||||
|
}
|
||||||
|
fold({ pending }) {
|
||||||
|
return pending instanceof Function ? pending(this.opt) : undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class FetchError extends FetchStatus {
|
||||||
|
static of(reason, opt) {
|
||||||
|
return new FetchError(reason, opt);
|
||||||
|
}
|
||||||
|
constructor(reason, opt) {
|
||||||
|
super(opt);
|
||||||
|
this.reason = reason;
|
||||||
|
}
|
||||||
|
fold({ error }) {
|
||||||
|
return error instanceof Function ? error(this.reason, this.opt) : undefined;
|
||||||
|
}
|
||||||
|
}
|
336
res/decoder-ring/decoder.js
Normal file
|
@ -0,0 +1,336 @@
|
||||||
|
class StartupError extends Error {}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We need to know the bundle path before we can fetch the sourcemap files. In a production environment, we can guess
|
||||||
|
* it using this.
|
||||||
|
*/
|
||||||
|
async function getBundleName(baseUrl) {
|
||||||
|
const res = await fetch(new URL("index.html", baseUrl).toString());
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new StartupError(`Couldn't fetch index.html to prefill bundle; ${res.status} ${res.statusText}`);
|
||||||
|
}
|
||||||
|
const index = await res.text();
|
||||||
|
return index.split("\n").map((line) =>
|
||||||
|
line.match(/<script src="bundles\/([^/]+)\/bundle.js"/),
|
||||||
|
)
|
||||||
|
.filter((result) => result)
|
||||||
|
.map((result) => result[1])[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
function validateBundle(value) {
|
||||||
|
return value.match(/^[0-9a-f]{20}$/) ? Some.of(value) : None;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* A custom fetcher that abandons immediately upon getting a response.
|
||||||
|
* The purpose of this is just to validate that the user entered a real bundle, and provide feedback.
|
||||||
|
*/
|
||||||
|
const bundleCache = new Map();
|
||||||
|
function bundleSubject(baseUrl, bundle) {
|
||||||
|
if (!bundle.match(/^[0-9a-f]{20}$/)) throw new Error("Bad input");
|
||||||
|
if (bundleCache.has(bundle)) {
|
||||||
|
return bundleCache.get(bundle);
|
||||||
|
}
|
||||||
|
const fetcher = new rxjs.BehaviorSubject(Pending.of());
|
||||||
|
bundleCache.set(bundle, fetcher);
|
||||||
|
|
||||||
|
fetch(new URL(`bundles/${bundle}/bundle.js.map`, baseUrl).toString()).then((res) => {
|
||||||
|
res.body.cancel(); /* Bail on the download immediately - it could be big! */
|
||||||
|
const status = res.ok;
|
||||||
|
if (status) {
|
||||||
|
fetcher.next(Success.of());
|
||||||
|
} else {
|
||||||
|
fetcher.next(FetchError.of(`Failed to fetch: ${res.status} ${res.statusText}`));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return fetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Convert a ReadableStream of bytes into an Observable of a string
|
||||||
|
* The observable will emit a stream of Pending objects and will concatenate
|
||||||
|
* the number of bytes received with whatever pendingContext has been supplied.
|
||||||
|
* Finally, it will emit a Success containing the result.
|
||||||
|
* You'd use this on a Response.body.
|
||||||
|
*/
|
||||||
|
function observeReadableStream(readableStream, pendingContext = {}) {
|
||||||
|
let bytesReceived = 0;
|
||||||
|
let buffer = "";
|
||||||
|
const pendingSubject = new rxjs.BehaviorSubject(Pending.of({ ...pendingContext, bytesReceived }));
|
||||||
|
const throttledPending = pendingSubject.pipe(rxjs.operators.throttleTime(100));
|
||||||
|
const resultObservable = new rxjs.Subject();
|
||||||
|
const reader = readableStream.getReader();
|
||||||
|
const utf8Decoder = new TextDecoder("utf-8");
|
||||||
|
function readNextChunk() {
|
||||||
|
reader.read().then(({ done, value }) => {
|
||||||
|
if (done) {
|
||||||
|
pendingSubject.complete();
|
||||||
|
resultObservable.next(Success.of(buffer));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bytesReceived += value.length;
|
||||||
|
pendingSubject.next(Pending.of({...pendingContext, bytesReceived }));
|
||||||
|
/* string concatenation is apparently the most performant way to do this */
|
||||||
|
buffer += utf8Decoder.decode(value);
|
||||||
|
readNextChunk();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
readNextChunk();
|
||||||
|
return rxjs.concat(throttledPending, resultObservable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* A wrapper which converts the browser's `fetch()` mechanism into an Observable. The Observable then provides us with
|
||||||
|
* a stream of datatype values: first, a sequence of Pending objects that keep us up to date with the download progress,
|
||||||
|
* finally followed by either a Success or Failure object. React then just has to render each of these appropriately.
|
||||||
|
*/
|
||||||
|
const fetchCache = new Map();
|
||||||
|
function fetchAsSubject(endpoint) {
|
||||||
|
if (fetchCache.has(endpoint)) {
|
||||||
|
// TODO: expiry/retry logic here?
|
||||||
|
return fetchCache.get(endpoint);
|
||||||
|
}
|
||||||
|
const fetcher = new rxjs.BehaviorSubject(Pending.of());
|
||||||
|
fetchCache.set(endpoint, fetcher);
|
||||||
|
|
||||||
|
fetch(endpoint).then((res) => {
|
||||||
|
if (!res.ok) {
|
||||||
|
fetcher.next(FetchError.of(`Failed to fetch endpoint ${endpoint}: ${res.status} ${res.statusText}`));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentLength = res.headers.get("content-length");
|
||||||
|
const context = contentLength ? { length: parseInt(contentLength) } : {};
|
||||||
|
|
||||||
|
const streamer = observeReadableStream(res.body, context, endpoint);
|
||||||
|
streamer.subscribe((value) => {
|
||||||
|
fetcher.next(value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return fetcher;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ===================== */
|
||||||
|
/* ==== React stuff ==== */
|
||||||
|
/* ===================== */
|
||||||
|
/* Rather than importing an entire build infrastructure, for now we just use React without JSX */
|
||||||
|
const e = React.createElement;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Provides user feedback given a FetchStatus object.
|
||||||
|
*/
|
||||||
|
function ProgressBar({ fetchStatus }) {
|
||||||
|
return e('span', { className: "progress "},
|
||||||
|
fetchStatus.fold({
|
||||||
|
pending: ({ bytesReceived, length }) => {
|
||||||
|
if (!bytesReceived) {
|
||||||
|
return e('span', { className: "spinner" }, "\u29b5");
|
||||||
|
}
|
||||||
|
const kB = Math.floor(10 * bytesReceived / 1024) / 10;
|
||||||
|
if (!length) {
|
||||||
|
return e('span', null, `Fetching (${kB}kB)`);
|
||||||
|
}
|
||||||
|
const percent = Math.floor(100 * bytesReceived / length);
|
||||||
|
return e('span', null, `Fetching (${kB}kB) ${percent}%`);
|
||||||
|
},
|
||||||
|
success: () => e('span', null, "\u2713"),
|
||||||
|
error: (reason) => {
|
||||||
|
return e('span', { className: 'error'}, `\u2717 ${reason}`);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main component.
|
||||||
|
*/
|
||||||
|
function BundlePicker() {
|
||||||
|
const [baseUrl, setBaseUrl] = React.useState(new URL("..", window.location).toString());
|
||||||
|
const [bundle, setBundle] = React.useState("");
|
||||||
|
const [file, setFile] = React.useState("");
|
||||||
|
const [line, setLine] = React.useState("1");
|
||||||
|
const [column, setColumn] = React.useState("");
|
||||||
|
const [result, setResult] = React.useState(None);
|
||||||
|
const [bundleFetchStatus, setBundleFetchStatus] = React.useState(None);
|
||||||
|
const [fileFetchStatus, setFileFetchStatus] = React.useState(None);
|
||||||
|
|
||||||
|
/* On baseUrl change, try to fill in the bundle name for the user */
|
||||||
|
React.useEffect(() => {
|
||||||
|
console.log("DEBUG", baseUrl);
|
||||||
|
getBundleName(baseUrl).then((name) => {
|
||||||
|
console.log("DEBUG", name);
|
||||||
|
if (bundle === "" && validateBundle(name) !== None) {
|
||||||
|
setBundle(name);
|
||||||
|
}
|
||||||
|
}, console.log.bind(console));
|
||||||
|
}, [baseUrl]);
|
||||||
|
|
||||||
|
/* ------------------------- */
|
||||||
|
/* Follow user state changes */
|
||||||
|
/* ------------------------- */
|
||||||
|
const onBaseUrlChange = React.useCallback((event) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
setBaseUrl(value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onBundleChange = React.useCallback((event) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
setBundle(value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onFileChange = React.useCallback((event) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
setFile(value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onLineChange = React.useCallback((event) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
setLine(value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const onColumnChange = React.useCallback((event) => {
|
||||||
|
const value = event.target.value;
|
||||||
|
setColumn(value);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------------------------------ */
|
||||||
|
/* Plumb data-fetching observables through to React */
|
||||||
|
/* ------------------------------------------------ */
|
||||||
|
|
||||||
|
/* Whenever a valid bundle name is input, go see if it's a real bundle on the server */
|
||||||
|
React.useEffect(() =>
|
||||||
|
validateBundle(bundle).fold({
|
||||||
|
some: (value) => {
|
||||||
|
const subscription = bundleSubject(baseUrl, value)
|
||||||
|
.pipe(rxjs.operators.map(Some.of))
|
||||||
|
.subscribe(setBundleFetchStatus);
|
||||||
|
return () => subscription.unsubscribe();
|
||||||
|
},
|
||||||
|
none: () => setBundleFetchStatus(None),
|
||||||
|
}),
|
||||||
|
[baseUrl, bundle]);
|
||||||
|
|
||||||
|
/* Whenever a valid javascript file is input, see if it corresponds to a sourcemap file and initiate a fetch
|
||||||
|
* if so. */
|
||||||
|
React.useEffect(() => {
|
||||||
|
if (!file.match(/.\.js$/) || validateBundle(bundle) === None) {
|
||||||
|
setFileFetchStatus(None);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const observable = fetchAsSubject(new URL(`bundles/${bundle}/${file}.map`, baseUrl).toString())
|
||||||
|
.pipe(
|
||||||
|
rxjs.operators.map((fetchStatus) => fetchStatus.flatMap(value => {
|
||||||
|
try {
|
||||||
|
return Success.of(JSON.parse(value));
|
||||||
|
} catch (e) {
|
||||||
|
return FetchError.of(e);
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
rxjs.operators.map(Some.of),
|
||||||
|
);
|
||||||
|
const subscription = observable.subscribe(setFileFetchStatus);
|
||||||
|
return () => subscription.unsubscribe();
|
||||||
|
}, [baseUrl, bundle, file]);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whenever we have a valid fetched sourcemap, and a valid line, attempt to find the original position from the
|
||||||
|
* sourcemap.
|
||||||
|
*/
|
||||||
|
React.useEffect(() => {
|
||||||
|
// `fold` dispatches on the datatype, like a switch statement
|
||||||
|
fileFetchStatus.fold({
|
||||||
|
some: (fetchStatus) =>
|
||||||
|
// `fold` just returns null for all of the cases that aren't `Success` objects here
|
||||||
|
fetchStatus.fold({
|
||||||
|
success: (value) => {
|
||||||
|
if (!line) return setResult(None);
|
||||||
|
const pLine = parseInt(line);
|
||||||
|
const pCol = parseInt(column);
|
||||||
|
sourceMap.SourceMapConsumer.with(value, undefined, (consumer) =>
|
||||||
|
consumer.originalPositionFor({ line: pLine, column: pCol }),
|
||||||
|
).then((result) => setResult(Some.of(JSON.stringify(result))));
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
none: () => setResult(None),
|
||||||
|
});
|
||||||
|
}, [fileFetchStatus, line, column]);
|
||||||
|
|
||||||
|
|
||||||
|
/* ------ */
|
||||||
|
/* Render */
|
||||||
|
/* ------ */
|
||||||
|
return e('div', {},
|
||||||
|
e('div', { className: 'inputs' },
|
||||||
|
e('div', { className: 'baseUrl' },
|
||||||
|
e('label', { htmlFor: 'baseUrl'}, 'Base URL'),
|
||||||
|
e('input', {
|
||||||
|
name: 'baseUrl',
|
||||||
|
required: true,
|
||||||
|
pattern: ".+",
|
||||||
|
onChange: onBaseUrlChange,
|
||||||
|
value: baseUrl,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
e('div', { className: 'bundle' },
|
||||||
|
e('label', { htmlFor: 'bundle'}, 'Bundle'),
|
||||||
|
e('input', {
|
||||||
|
name: 'bundle',
|
||||||
|
required: true,
|
||||||
|
pattern: "[0-9a-f]{20}",
|
||||||
|
onChange: onBundleChange,
|
||||||
|
value: bundle,
|
||||||
|
}),
|
||||||
|
bundleFetchStatus.fold({
|
||||||
|
some: (fetchStatus) => e(ProgressBar, { fetchStatus }),
|
||||||
|
none: () => null,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
e('div', { className: 'file' },
|
||||||
|
e('label', { htmlFor: 'file' }, 'File'),
|
||||||
|
e('input', {
|
||||||
|
name: 'file',
|
||||||
|
required: true,
|
||||||
|
pattern: ".+\\.js",
|
||||||
|
onChange: onFileChange,
|
||||||
|
value: file,
|
||||||
|
}),
|
||||||
|
fileFetchStatus.fold({
|
||||||
|
some: (fetchStatus) => e(ProgressBar, { fetchStatus }),
|
||||||
|
none: () => null,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
e('div', { className: 'line' },
|
||||||
|
e('label', { htmlFor: 'line' }, 'Line'),
|
||||||
|
e('input', {
|
||||||
|
name: 'line',
|
||||||
|
required: true,
|
||||||
|
pattern: "[0-9]+",
|
||||||
|
onChange: onLineChange,
|
||||||
|
value: line,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
e('div', { className: 'column' },
|
||||||
|
e('label', { htmlFor: 'column' }, 'Column'),
|
||||||
|
e('input', {
|
||||||
|
name: 'column',
|
||||||
|
required: true,
|
||||||
|
pattern: "[0-9]+",
|
||||||
|
onChange: onColumnChange,
|
||||||
|
value: column,
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
e('div', null,
|
||||||
|
result.fold({
|
||||||
|
none: () => "Select a bundle, file and line",
|
||||||
|
some: (value) => e('pre', null, value),
|
||||||
|
}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Global stuff */
|
||||||
|
window.Decoder = {
|
||||||
|
BundlePicker,
|
||||||
|
};
|
79
res/decoder-ring/index.html
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Rageshake decoder ring</title>
|
||||||
|
<script crossorigin src="https://unpkg.com/source-map@0.7.3/dist/source-map.js"></script>
|
||||||
|
<script>
|
||||||
|
sourceMap.SourceMapConsumer.initialize({
|
||||||
|
"lib/mappings.wasm": "https://unpkg.com/source-map@0.7.3/lib/mappings.wasm"
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
<script crossorigin src="https://unpkg.com/react@16/umd/react.production.min.js"></script>
|
||||||
|
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.production.min.js"></script>
|
||||||
|
<!--<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
|
||||||
|
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>-->
|
||||||
|
<script crossorigin src="https://unpkg.com/rxjs/bundles/rxjs.umd.min.js"></script>
|
||||||
|
<script src="datatypes.js"></script>
|
||||||
|
<script src="decoder.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
@keyframes spin {
|
||||||
|
from {transform:rotate(0deg);}
|
||||||
|
to {transform:rotate(359deg);}
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans-serif
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
animation: spin 4s infinite linear;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
font-size: larger;
|
||||||
|
}
|
||||||
|
|
||||||
|
.progress {
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-right: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bundle input {
|
||||||
|
width: 24ex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.valid::after {
|
||||||
|
content: "✓"
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
width: 3em;
|
||||||
|
margin-right: 1em;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
input:valid {
|
||||||
|
border: 1px solid green;
|
||||||
|
}
|
||||||
|
|
||||||
|
.inputs > div {
|
||||||
|
margin-bottom: 0.5em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<header><h2>Decoder ring</h2></header>
|
||||||
|
<content id="main">Waiting for javascript to run...</content>
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
|
try {
|
||||||
|
ReactDOM.render(React.createElement(Decoder.BundlePicker), document.getElementById("main"))
|
||||||
|
} catch (e) {
|
||||||
|
const n = document.createElement("div");
|
||||||
|
n.innerText = `Error starting: ${e.message}`;
|
||||||
|
document.getElementById("main").appendChild(n);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -1,56 +1,85 @@
|
||||||
{
|
{
|
||||||
"name": "Riot - open team collaboration",
|
"name": "Element",
|
||||||
"short_name": "Riot",
|
"short_name": "Element",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"theme_color": "#76CFA6",
|
"theme_color": "#76CFA6",
|
||||||
"start_url": "index.html",
|
"start_url": "index.html",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "vector-icons/android-chrome-36x36.png",
|
"src": "/vector-icons/44.png",
|
||||||
"sizes": "36x36",
|
"sizes": "44x44",
|
||||||
"type": "image\/png",
|
"type": "image/png"
|
||||||
"density": "0.75"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "vector-icons/android-chrome-48x48.png",
|
"src": "/vector-icons/1240x600.png",
|
||||||
"sizes": "48x48",
|
"sizes": "1240x600",
|
||||||
"type": "image\/png",
|
"type": "image/png"
|
||||||
"density": "1.0"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "vector-icons/android-chrome-72x72.png",
|
"src": "/vector-icons/300.png",
|
||||||
"sizes": "72x72",
|
"sizes": "300x300",
|
||||||
"type": "image\/png",
|
"type": "image/png"
|
||||||
"density": "1.5"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "vector-icons/android-chrome-96x96.png",
|
"src": "/vector-icons/150.png",
|
||||||
"sizes": "96x96",
|
"sizes": "150x150",
|
||||||
"type": "image\/png",
|
"type": "image/png"
|
||||||
"density": "2.0"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "vector-icons/android-chrome-144x144.png",
|
"src": "/vector-icons/88.png",
|
||||||
"sizes": "144x144",
|
"sizes": "88x88",
|
||||||
"type": "image\/png",
|
"type": "image/png"
|
||||||
"density": "3.0"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"src": "vector-icons/android-chrome-192x192.png",
|
"src": "/vector-icons/24.png",
|
||||||
"sizes": "192x192",
|
"sizes": "24x24",
|
||||||
"type": "image\/png",
|
"type": "image/png"
|
||||||
"density": "4.0"
|
},
|
||||||
|
{
|
||||||
|
"src": "/vector-icons/50.png",
|
||||||
|
"sizes": "50x50",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/vector-icons/620x300.png",
|
||||||
|
"sizes": "620x300",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/vector-icons/1024.png",
|
||||||
|
"sizes": "1024x1024",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/vector-icons/180.png",
|
||||||
|
"sizes": "180x180",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/vector-icons/152.png",
|
||||||
|
"sizes": "152x152",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/vector-icons/120.png",
|
||||||
|
"sizes": "120x120",
|
||||||
|
"type": "image/png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"src": "/vector-icons/76.png",
|
||||||
|
"sizes": "76x76",
|
||||||
|
"type": "image/png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"related_applications": [
|
"related_applications": [
|
||||||
{
|
{
|
||||||
"platform": "play",
|
"platform": "play",
|
||||||
"url": "https://play.google.com/store/apps/details?id=im.vector.alpha",
|
"url": "https://play.google.com/store/apps/details?id=im.vector.app",
|
||||||
"id": "im.vector.alpha"
|
"id": "im.vector.app"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"platform": "itunes",
|
"platform": "itunes",
|
||||||
"url": "https://itunes.apple.com/gb/app/riot-open-source-team-collaboration-via-matrix/id1083446067"
|
"url": "https://apps.apple.com/app/vector/id1083446067"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
self.addEventListener('fetch',() => {});
|
self.addEventListener('fetch', () => {});
|
||||||
|
|
BIN
res/themes/element/img/backgrounds/lake.jpg
Normal file
After Width: | Height: | Size: 596 KiB |
97
res/themes/element/img/download/apple.svg
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
<svg width="144px" height="48px" viewBox="0 0 120 40" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<desc>Download on the App Store.</desc>
|
||||||
|
<defs />
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="App-Store-badge" fill-rule="nonzero">
|
||||||
|
<g id="Group">
|
||||||
|
<g id="Shape">
|
||||||
|
<path
|
||||||
|
d="M110.13477,0 L9.53468,0 C9.16798,0 8.80568,0 8.43995,0.002 C8.1338,0.004 7.83009,0.00981 7.521,0.0147 C6.84951368,0.0226018036 6.17960647,0.0816762599 5.5171,0.19141 C4.85552408,0.303532628 4.21467252,0.51491574 3.61622,0.81841 C3.01849941,1.12447171 2.47234502,1.52216753 1.99757,1.99707 C1.5203025,2.47063699 1.12246318,3.01801638 0.81935,3.61816 C0.515400242,4.21710912 0.304640498,4.8589383 0.19435,5.52148 C0.0830109412,6.18318491 0.0230983806,6.85252054 0.01515,7.52348 C0.00587,7.83008 0.00489,8.1377 0,8.44434 L0,31.5586 C0.00489,31.8691 0.00587,32.1699 0.01515,32.4805 C0.023100818,33.1514262 0.0830133796,33.8207284 0.19435,34.4824 C0.304335953,35.145329 0.515108158,35.7875266 0.81935,36.3867 C1.12232555,36.9849029 1.52022081,37.5300662 1.99757,38.001 C2.47054482,38.478014 3.01705224,38.8759804 3.61622,39.1797 C4.21466797,39.4840065 4.85545044,39.6966478 5.5171,39.8105 C6.1797191,39.9193547 6.84955741,39.9784532 7.521,39.9873 C7.83009,39.9941 8.1338,39.998 8.43995,39.998 C8.80567,40 9.168,40 9.53468,40 L110.13477,40 C110.49417,40 110.85937,40 111.21877,39.998 C111.52347,39.998 111.83597,39.9941 112.14067,39.9873 C112.810843,39.9789237 113.47942,39.9198215 114.14067,39.8105 C114.804454,39.6958464 115.447534,39.4832614 116.04887,39.1797 C116.647497,38.8758046 117.1935,38.4778491 117.66607,38.001 C118.142188,37.5282218 118.540932,36.9834573 118.84767,36.3867 C119.149629,35.7870908 119.358395,35.1449445 119.46677,34.4824 C119.578285,33.8206376 119.640323,33.1514843 119.65237,32.4805 C119.65627,32.1699 119.65627,31.8691 119.65627,31.5586 C119.66407,31.1953 119.66407,30.834 119.66407,30.4648 L119.66407,9.53613 C119.66407,9.16992 119.66407,8.80664 119.65627,8.44434 C119.65627,8.1377 119.65627,7.83008 119.65237,7.52344 C119.640326,6.85242244 119.578287,6.18323567 119.46677,5.52144 C119.358093,4.8592816 119.149339,4.21750328 118.84767,3.61812 C118.230394,2.41519608 117.251573,1.4360254 116.04887,0.81832 C115.447532,0.51556738 114.804383,0.30424041 114.14067,0.19132 C113.479535,0.0811027831 112.810888,0.0220077649 112.14067,0.01456 C111.83597,0.00968 111.52347,0.00382 111.21877,0.00187 C110.85937,-0.00013 110.49417,-0.00013 110.13477,-0.00013 L110.13477,0 Z"
|
||||||
|
fill="#A6A6A6" />
|
||||||
|
<path
|
||||||
|
d="M8.44483,39.125 C8.14015,39.125 7.84283,39.1211 7.54054,39.1143 C6.91432177,39.1061407 6.28956717,39.051625 5.6714,38.9512 C5.0949903,38.8519282 4.53660424,38.6672645 4.01466,38.4033 C3.4975017,38.1415227 3.02581177,37.7982729 2.61766,37.3867 C2.20360033,36.9799753 1.85887673,36.508244 1.59715,35.9902 C1.33253926,35.4687891 1.14941288,34.9098996 1.05415,34.333 C0.951274358,33.7131149 0.895614374,33.0863132 0.88765,32.458 C0.88131,32.2471 0.87301,31.5449 0.87301,31.5449 L0.87301,8.44434 C0.87301,8.44434 0.88185,7.75293 0.8877,7.5498 C0.895325827,6.92248205 0.950662148,6.2966531 1.05323,5.67773 C1.14866872,5.09925008 1.33193687,4.53874887 1.59669,4.01563 C1.85745482,3.49794385 2.20026458,3.02586029 2.61183,2.61768 C3.02293283,2.20562142 3.49613161,1.86060412 4.01417,1.59521 C4.53491467,1.3320936 5.09224545,1.14873255 5.66749,1.05127 C6.28768733,0.949836139 6.91461084,0.894996084 7.543,0.88721 L8.44532,0.875 L111.21387,0.875 L112.12697,0.8877 C112.749643,0.895099198 113.370872,0.949450006 113.98537,1.05029 C114.566438,1.14897507 115.129577,1.33361553 115.65627,1.59814 C116.694088,2.13298605 117.538542,2.97916295 118.07127,4.01807 C118.331797,4.53757756 118.512239,5.09350676 118.60647,5.66699 C118.710259,6.29099138 118.768347,6.92173834 118.78027,7.5542 C118.78317,7.8374 118.78317,8.1416 118.78317,8.44434 C118.79107,8.81934 118.79107,9.17627 118.79107,9.53613 L118.79107,30.4648 C118.79107,30.8281 118.79107,31.1826 118.78317,31.54 C118.78317,31.8652 118.78317,32.1631 118.77927,32.4697 C118.767605,33.0908757 118.710486,33.7103642 118.60837,34.3232 C118.51506,34.9042612 118.33293,35.4675131 118.06837,35.9932 C117.804793,36.5056211 117.462049,36.9732662 117.05277,37.3789 C116.644251,37.7926846 116.171729,38.1379427 115.65337,38.4014 C115.128136,38.6673937 114.565826,38.8527403 113.98537,38.9512 C113.36725,39.052161 112.742435,39.1066802 112.11617,39.1143 C111.82327,39.1211 111.51657,39.125 111.21877,39.125 L110.13477,39.127 L8.44483,39.125 Z"
|
||||||
|
fill="#000000" />
|
||||||
|
</g>
|
||||||
|
<g id="_Group_" transform="translate(9.000000, 8.000000)" fill="#FFFFFF">
|
||||||
|
<g id="_Group_2">
|
||||||
|
<g id="_Group_3">
|
||||||
|
<path
|
||||||
|
d="M15.76888,12.30068 C15.790737,10.6042091 16.6801229,9.03718611 18.12544,8.14862 C17.2095126,6.84051277 15.730392,6.04087835 14.13428,5.99094 C12.45504,5.81468 10.82709,6.99577 9.97138,6.99577 C9.09911,6.99577 7.78161,6.00844 6.36288,6.03763 C4.49620126,6.09793842 2.79813717,7.13352548 1.88996,8.7655 C-0.04404,12.11392 1.39855,17.03497 3.25116,19.74158 C4.17806,21.06693 5.26134,22.54738 6.67879,22.49488 C8.06585,22.43735 8.58389,21.6104 10.25819,21.6104 C11.91695,21.6104 12.40298,22.49488 13.84919,22.4615 C15.33757,22.43734 16.27532,21.13026 17.1697,19.79236 C17.8356761,18.8479997 18.3481437,17.8042759 18.68812,16.69985 C16.9203766,15.9521813 15.7709432,14.2200343 15.76888,12.30068 Z"
|
||||||
|
id="_Path_" />
|
||||||
|
<path
|
||||||
|
d="M13.03725,4.21089 C13.8487766,3.23668191 14.248585,1.98450245 14.15177,0.72027 C12.9119378,0.850490487 11.7666802,1.44304968 10.94419,2.37988 C10.1320187,3.30418903 9.72057463,4.51343268 9.80048,5.74127 C11.0569368,5.75420677 12.2499161,5.19015322 13.03725,4.21089 Z"
|
||||||
|
id="_Path_2" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="Group" transform="translate(25.000000, 9.000000)">
|
||||||
|
<path
|
||||||
|
d="M8.30227,10.13965 L3.56887,10.13965 L2.43215,13.4961 L0.42727,13.4961 L4.91067,1.0781 L6.99367,1.0781 L11.47707,13.4961 L9.438,13.4961 L8.30227,10.13965 Z M4.0591,8.59082 L7.8111,8.59082 L5.96149,3.14355 L5.90973,3.14355 L4.0591,8.59082 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M21.15969,8.96973 C21.15969,11.78321 19.65383,13.59082 17.38137,13.59082 C16.2067553,13.6522646 15.1003324,13.0370307 14.53274,12.00682 L14.48974,12.00682 L14.48974,16.4912 L12.63134,16.4912 L12.63134,4.44238 L14.4302,4.44238 L14.4302,5.94824 L14.46438,5.94824 C15.0571883,4.92448792 16.1648043,4.30951884 17.34719,4.34765 C19.645,4.34766 21.15969,6.16406 21.15969,8.96973 Z M19.24953,8.96973 C19.24953,7.13673 18.30226,5.93164 16.85695,5.93164 C15.43703,5.93164 14.48195,7.16211 14.48195,8.96973 C14.48195,10.79395 15.43703,12.01563 16.85695,12.01563 C18.30227,12.01563 19.24953,10.81934 19.24953,8.96973 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M31.12453,8.96973 C31.12453,11.78321 29.61867,13.59082 27.34621,13.59082 C26.1715953,13.6522646 25.0651724,13.0370307 24.49758,12.00682 L24.45458,12.00682 L24.45458,16.4912 L22.59618,16.4912 L22.59618,4.44238 L24.395,4.44238 L24.395,5.94824 L24.42918,5.94824 C25.0219926,4.92448854 26.1296128,4.30952307 27.312,4.34766 C29.60988,4.34766 31.12453,6.16406 31.12453,8.96973 Z M29.21437,8.96973 C29.21437,7.13673 28.2671,5.93164 26.82179,5.93164 C25.40187,5.93164 24.44679,7.16211 24.44679,8.96973 C24.44679,10.79395 25.40187,12.01563 26.82179,12.01563 C28.26711,12.01563 29.21438,10.81934 29.21438,8.96973 L29.21437,8.96973 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M37.71047,10.03613 C37.84817,11.26758 39.04447,12.07613 40.67922,12.07613 C42.24563,12.07613 43.37258,11.26754 43.37258,10.15718 C43.37258,9.19331 42.69289,8.61618 41.08352,8.22066 L39.47415,7.83296 C37.19388,7.28218 36.13528,6.21577 36.13528,4.4853 C36.13528,2.34272 38.00247,0.87104 40.65383,0.87104 C43.27783,0.87104 45.07668,2.34272 45.13723,4.4853 L43.26123,4.4853 C43.14893,3.24604 42.12451,2.498 40.62744,2.498 C39.13037,2.498 38.10596,3.25484 38.10596,4.3564 C38.10596,5.23433 38.76026,5.75093 40.36084,6.1464 L41.729,6.48234 C44.27685,7.08488 45.33545,8.10834 45.33545,9.92472 C45.33545,12.24796 43.48486,13.70304 40.5415,13.70304 C37.78759,13.70304 35.92822,12.28214 35.8081,10.03604 L37.71047,10.03613 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M49.34621,2.2998 L49.34621,4.44238 L51.06789,4.44238 L51.06789,5.91406 L49.34621,5.91406 L49.34621,10.90527 C49.34621,11.68066 49.69094,12.04199 50.44777,12.04199 C50.6521614,12.0384259 50.8562221,12.0240726 51.0591,11.99899 L51.0591,13.46188 C50.7188283,13.5254596 50.3729708,13.5542545 50.02687,13.54782 C48.19387,13.54782 47.47902,12.85934 47.47902,11.10348 L47.47902,5.91406 L46.16262,5.91406 L46.16262,4.44238 L47.479,4.44238 L47.479,2.2998 L49.34621,2.2998 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M52.065,8.96973 C52.065,6.1211 53.74273,4.33106 56.35895,4.33106 C58.98395,4.33106 60.65387,6.12106 60.65387,8.96973 C60.65387,11.82618 58.99274,13.6084 56.35895,13.6084 C53.72609,13.6084 52.065,11.82617 52.065,8.96973 Z M58.76031,8.96973 C58.76031,7.01563 57.8648,5.86231 56.35894,5.86231 C54.85308,5.86231 53.95855,7.02442 53.95855,8.96973 C53.95855,10.93164 54.85308,12.07618 56.35894,12.07618 C57.8648,12.07618 58.76027,10.93164 58.76027,8.96973 L58.76031,8.96973 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M62.18606,4.44238 L63.95852,4.44238 L63.95852,5.98338 L64.00152,5.98338 C64.248696,4.99136841 65.1576526,4.30863156 66.17925,4.34764 C66.393414,4.34689223 66.6069872,4.37015075 66.81597,4.41698 L66.81597,6.15526 C66.545601,6.07264332 66.2635596,6.03471129 65.98097,6.04296 C65.4346182,6.02079544 64.9058709,6.23853473 64.5335615,6.63900597 C64.161252,7.03947722 63.9825766,7.58267074 64.04445,8.12596 L64.04445,13.49608 L62.18605,13.49608 L62.18606,4.44238 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M75.3843,10.83691 C75.1343,12.48046 73.53371,13.60839 71.48586,13.60839 C68.85207,13.60839 67.21731,11.84374 67.21731,9.01269 C67.21731,6.17285 68.86086,4.33105 71.40774,4.33105 C73.91262,4.33105 75.48782,6.05175 75.48782,8.79687 L75.48782,9.43359 L69.09329,9.43359 L69.09329,9.54589 C69.0335874,10.2199216 69.2663316,10.8871194 69.7323199,11.3777699 C70.1983083,11.8684204 70.8526275,12.1352333 71.52884,12.11034 C72.4306823,12.1948396 73.2809431,11.6769777 73.61966,10.8369 L75.3843,10.83691 Z M69.1020624,8.13477 L73.62844,8.13476 C73.6621655,7.52909749 73.4416965,6.93682308 73.0201501,6.50063155 C72.5986036,6.06444001 72.0142008,5.82388041 71.40774,5.83691 C70.7964818,5.83326223 70.2090907,6.07393463 69.7761255,6.50543324 C69.3431603,6.93693186 69.1004963,7.52350292 69.1020624,8.13477 Z"
|
||||||
|
id="Shape" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="_Group_4" transform="translate(35.000000, 8.000000)" fill="#FFFFFF">
|
||||||
|
<g id="Group">
|
||||||
|
<path
|
||||||
|
d="M2.82619,0.731 C3.61513656,0.674384181 4.38789226,0.974547428 4.93176129,1.54887182 C5.47563032,2.12319621 5.73328587,2.91114479 5.63381,3.69584 C5.63381,5.60209 4.60354,6.69784 2.82619,6.69784 L0.67092,6.69784 L0.67092,0.731 L2.82619,0.731 Z M1.59767,5.854 L2.72267,5.854 C3.28649194,5.88770201 3.83548652,5.66555901 4.21721851,5.24925179 C4.5989505,4.83294457 4.77277961,4.26679442 4.69044,3.708 C4.76678901,3.15152453 4.59045658,2.59004622 4.20967108,2.17713398 C3.82888557,1.76422175 3.28349567,1.5430863 2.72267,1.57421 L1.59767,1.57421 L1.59767,5.854 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M6.68068,4.44434 C6.60346713,3.63722505 6.99048366,2.85611193 7.67941593,2.42859737 C8.36834819,2.0010828 9.24008181,2.0010828 9.92901407,2.42859737 C10.6179463,2.85611193 11.0049629,3.63722505 10.92775,4.44434 C11.0064319,5.25232226 10.6197687,6.03495038 9.93022554,6.4633853 C9.24068243,6.89182022 8.36774757,6.89182022 7.67820446,6.4633853 C6.98866134,6.03495038 6.60199806,5.25232226 6.68068,4.44434 Z M10.01368,4.44434 C10.01368,3.46827 9.5752,2.89747 8.80568,2.89747 C8.03322,2.89747 7.59868,3.46827 7.59868,4.44435 C7.59868,5.42824 8.03325,5.99464 8.80568,5.99464 C9.57522,5.99463 10.01369,5.42432 10.01369,4.44434 L10.01368,4.44434 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="16.57326 6.69775 15.65139 6.69775 14.72073 3.38134 14.65042 3.38134 13.72366 6.69775 12.81057 6.69775 11.56936 2.19482 12.47073 2.19482 13.27737 5.63082 13.34378 5.63082 14.26956 2.19482 15.1221 2.19482 16.04788 5.63082 16.11819 5.63082 16.92092 2.19482 17.80959 2.19482" />
|
||||||
|
<path
|
||||||
|
d="M18.85354,2.19482 L19.709,2.19482 L19.709,2.91015 L19.77541,2.91015 C20.0063449,2.38347794 20.5459729,2.06130747 21.11916,2.1079 C21.5629768,2.07453177 21.9978859,2.2447899 22.3010908,2.57060207 C22.6042957,2.89641424 22.7428931,3.34242376 22.67775,3.7827 L22.67775,6.6977 L21.78908,6.6977 L21.78908,4.00586 C21.78908,3.28223 21.47463,2.92236 20.8174,2.92236 C20.5163658,2.90833912 20.2242202,3.02648257 20.0175546,3.24581678 C19.810889,3.465151 19.710315,3.76380101 19.7422,4.06347 L19.7422,6.69775 L18.85353,6.69775 L18.85354,2.19482 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="24.09377 0.437 24.98244 0.437 24.98244 6.69774 24.09377 6.69774" />
|
||||||
|
<path
|
||||||
|
d="M26.21779,4.44434 C26.1406364,3.63717225 26.527714,2.85603936 27.2166974,2.4285182 C27.9056808,2.00099704 28.7774592,2.00099704 29.4664426,2.4285182 C30.155426,2.85603936 30.5425036,3.63717225 30.46535,4.44434 C30.543932,5.25235119 30.1571979,6.03495719 29.4676205,6.46337324 C28.7780432,6.89178929 27.9050968,6.89178929 27.2155195,6.46337324 C26.5259421,6.03495719 26.139208,5.25235119 26.21779,4.44434 Z M29.55079,4.44434 C29.55079,3.46827 29.11231,2.89747 28.34279,2.89747 C27.57033,2.89747 27.13579,3.46827 27.13579,4.44435 C27.13579,5.42824 27.57036,5.99464 28.34279,5.99464 C29.11232,5.99463 29.5508,5.42432 29.5508,4.44434 L29.55079,4.44434 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M31.4009,5.42432 C31.4009,4.61377 32.00442,4.14649 33.0757,4.08008 L34.29543,4.00977 L34.29543,3.6211 C34.29543,3.14551 33.98098,2.87696 33.37356,2.87696 C32.87747,2.87696 32.53372,3.05909 32.43508,3.37745 L31.57473,3.37745 C31.66555,2.60401 32.39309,2.10792 33.41457,2.10792 C34.54348,2.10792 35.1802,2.66992 35.1802,3.6211 L35.1802,6.69776 L34.32473,6.69776 L34.32473,6.06495 L34.25442,6.06495 C33.9638686,6.52707633 33.4471736,6.79716323 32.90188,6.77195 C32.5196161,6.81171181 32.1383711,6.68791066 31.8523958,6.43115244 C31.5664205,6.17439423 31.4024061,5.80864331 31.4009,5.42432 Z M34.29543,5.03955 L34.29543,4.66309 L33.19582,4.7334 C32.5757,4.7749 32.29445,4.98584 32.29445,5.38281 C32.29445,5.78808 32.64601,6.02392 33.12945,6.02392 C33.4156361,6.05288986 33.7013264,5.96447505 33.9211204,5.77891559 C34.1409144,5.59335613 34.2759916,5.32654106 34.29543,5.03955 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M36.34816,4.44434 C36.34816,3.02149 37.07961,2.12012 38.2173,2.12012 C38.7917768,2.09365013 39.3298275,2.40147287 39.59816,2.91012 L39.66457,2.91012 L39.66457,0.437 L40.55324,0.437 L40.55324,6.69774 L39.70168,6.69774 L39.70168,5.98631 L39.63137,5.98631 C39.3427542,6.49073698 38.7980745,6.79335648 38.21731,6.77195 C37.0718,6.772 36.34816,5.87061 36.34816,4.44434 Z M37.26616,4.44434 C37.26616,5.39942 37.71636,5.97413 38.46929,5.97413 C39.21829,5.97413 39.6812,5.39113 39.6812,4.44825 C39.6812,3.50977 39.21343,2.91846 38.46929,2.91846 C37.72121,2.91846 37.26613,3.49707 37.26613,4.44434 L37.26616,4.44434 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M44.23,4.44434 C44.1527871,3.63722505 44.5398037,2.85611193 45.2287359,2.42859737 C45.9176682,2.0010828 46.7894018,2.0010828 47.4783341,2.42859737 C48.1672663,2.85611193 48.5542829,3.63722505 48.47707,4.44434 C48.5557519,5.25232226 48.1690887,6.03495038 47.4795455,6.4633853 C46.7900024,6.89182022 45.9170676,6.89182022 45.2275245,6.4633853 C44.5379813,6.03495038 44.1513181,5.25232226 44.23,4.44434 Z M47.563,4.44434 C47.563,3.46827 47.12452,2.89747 46.355,2.89747 C45.58254,2.89747 45.148,3.46827 45.148,4.44435 C45.148,5.42824 45.58257,5.99464 46.355,5.99464 C47.12453,5.99463 47.563,5.42432 47.563,4.44434 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M49.66945,2.19482 L50.52492,2.19482 L50.52492,2.91015 L50.59133,2.91015 C50.8222649,2.38347794 51.3618929,2.06130747 51.93508,2.1079 C52.3788968,2.07453177 52.8138059,2.2447899 53.1170108,2.57060207 C53.4202157,2.89641424 53.5588131,3.34242376 53.49367,3.7827 L53.49367,6.6977 L52.605,6.6977 L52.605,4.00586 C52.605,3.28223 52.29055,2.92236 51.63332,2.92236 C51.3322858,2.90833912 51.0401402,3.02648257 50.8334746,3.24581678 C50.626809,3.465151 50.526235,3.76380101 50.55812,4.06347 L50.55812,6.69775 L49.66945,6.69775 L49.66945,2.19482 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M58.51516,1.07373 L58.51516,2.21533 L59.49075,2.21533 L59.49075,2.96387 L58.51516,2.96387 L58.51516,5.2793 C58.51516,5.75098 58.7095,5.95752 59.15188,5.95752 C59.2651356,5.95715754 59.3782775,5.95030966 59.49075,5.93701 L59.49075,6.67724 C59.3311595,6.70579072 59.1694656,6.72098004 59.00735,6.72265 C58.01907,6.72265 57.62551,6.37499 57.62551,5.50683 L57.62551,2.96383 L56.91067,2.96383 L56.91067,2.21529 L57.62551,2.21529 L57.62551,1.07373 L58.51516,1.07373 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M60.70461,0.437 L61.58547,0.437 L61.58547,2.91845 L61.65578,2.91845 C61.8978078,2.38716856 62.4468801,2.06458754 63.02878,2.11181 C63.4700766,2.08779728 63.8990983,2.26180371 64.1989893,2.58643385 C64.4988802,2.91106399 64.6384049,3.35250564 64.57956,3.79052 L64.57956,6.69775 L63.69,6.69775 L63.69,4.00975 C63.69,3.29051 63.355,2.92625 62.72711,2.92625 C62.417939,2.90089367 62.1133391,3.01329096 61.8947423,3.2333935 C61.6761456,3.45349605 61.5658419,3.75886031 61.59332,4.06785 L61.59332,6.69773 L60.70465,6.69773 L60.70461,0.437 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M69.76125,5.48193 C69.512057,6.33130948 68.6900989,6.88010304 67.81008,6.78466 C67.2096439,6.8005102 66.6325914,6.5516307 66.2320282,6.10405516 C65.8314651,5.65647963 65.6478864,5.05545594 65.73,4.46045 C65.6500674,3.86379048 65.8329582,3.26180373 66.2312908,2.81044696 C66.6296234,2.35909018 67.204202,2.10277675 67.80617,2.10791 C69.0591,2.10791 69.81496,2.96391 69.81496,4.37791 L69.81496,4.688 L66.63527,4.688 L66.63527,4.7378 C66.607132,5.07194014 66.7212507,5.40244775 66.9495608,5.6480407 C67.1778709,5.89363365 67.4991879,6.03152392 67.83449,6.0278 C68.2692619,6.07999468 68.6924825,5.86433304 68.90578,5.4819 L69.76125,5.48193 Z M66.63525,4.03076 L68.90966,4.03076 C68.9323129,3.72516044 68.8248585,3.42420507 68.6137769,3.20205909 C68.4026954,2.97991311 68.1076175,2.85723623 67.80126,2.86426 C67.490752,2.86035891 67.191828,2.98202124 66.9722963,3.20164888 C66.7527647,3.42127653 66.6312331,3.72025374 66.63527,4.03076 L66.63525,4.03076 Z"
|
||||||
|
id="Shape" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 20 KiB |
135
res/themes/element/img/download/fdroid.svg
Normal file
|
@ -0,0 +1,135 @@
|
||||||
|
<svg width="164px" height="48px" viewBox="0 0 157 46" version="1.1" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<desc>Get it on F-Droid.</desc>
|
||||||
|
<defs>
|
||||||
|
<radialGradient cx="0.55528181%" cy="0.456156968%" fx="0.55528181%"
|
||||||
|
fy="0.456156968%"
|
||||||
|
r="99.5501799%"
|
||||||
|
gradientTransform="translate(0.005553,0.004562),scale(0.985441,1.000000),rotate(90.000001),translate(-0.005553,-0.004562)"
|
||||||
|
id="radialGradient-1">
|
||||||
|
<stop stop-color="#FFFFFF" stop-opacity="0.098039" offset="0%" />
|
||||||
|
<stop stop-color="#FFFFFF" stop-opacity="0" offset="100%" />
|
||||||
|
</radialGradient>
|
||||||
|
</defs>
|
||||||
|
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
|
<g id="F-Droid-badge">
|
||||||
|
<rect id="Rectangle-path" fill="#000000" fill-rule="nonzero" x="0" y="0"
|
||||||
|
width="157"
|
||||||
|
height="46" rx="5.6097561" />
|
||||||
|
<g id="Group" transform="translate(49.623214, 5.890244)" fill="#FFFFFF"
|
||||||
|
fill-rule="nonzero">
|
||||||
|
<path
|
||||||
|
d="M5.68003571,6.29863415 L5.68003571,4.42449878 L4.13843589,4.42449878 L4.13843589,3.64866951 L6.61432589,3.64866951 L6.61432589,6.64455976 C6.24995506,6.90316951 5.84820327,7.09946423 5.40907054,7.2334439 C4.96995649,7.36430642 4.50125542,7.42973768 4.00296732,7.42973768 C2.91295744,7.42973768 2.0596344,7.1119263 1.44299821,6.47630354 C0.829483333,5.83757671 0.522725893,4.94958037 0.522725893,3.81231451 C0.522725893,2.67194459 0.829483333,1.78394825 1.44299821,1.14832549 C2.0596344,0.509598659 2.91295744,0.190235244 4.00296732,0.190235244 C4.45765054,0.190235244 4.88898,0.24631878 5.29695571,0.358485854 C5.70805274,0.470652927 6.08644143,0.635785447 6.43212179,0.853883415 L6.43212179,1.85873098 C6.08332012,1.56274154 5.71271601,1.33995943 5.32030946,1.19038463 C4.92790292,1.04082854 4.51525458,0.966050488 4.08236446,0.966050488 C3.22903208,0.966050488 2.58748149,1.20440902 2.15771268,1.6811261 C1.73104649,2.15784317 1.51771339,2.86824398 1.51771339,3.81232854 C1.51771339,4.75329033 1.73104649,5.46212976 2.15771268,5.93884683 C2.58748149,6.4155639 3.22903208,6.65392244 4.08236446,6.65392244 C4.41559696,6.65392244 4.71301851,6.6258802 4.97462911,6.56979573 C5.2362397,6.51059598 5.47136589,6.4202387 5.68000768,6.2987239 L5.68003571,6.29863415 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="8.34342857 0.316390244 12.7531661 0.316390244 12.7531661 1.1109 9.28683036 1.1109 9.28683036 3.17666463 12.6082214 3.17666463 12.6082214 3.97117439 9.28683036 3.97117439 9.28683036 6.49963171 12.8372732 6.49963171 12.8372732 7.29414146 8.34342857 7.29414146 8.34342857 0.316446341" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="13.4319107 0.316390244 19.3320268 0.316390244 19.3320268 1.1109 16.8561368 1.1109 16.8561368 7.29425366 15.9078287 7.29425366 15.9078287 1.1109 13.4319387 1.1109 13.4319387 0.316390244" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="23.2920714 0.316390244 24.2356975 0.316390244 24.2356975 7.29408537 23.2920714 7.29408537" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="25.1480357 0.316390244 31.0481518 0.316390244 31.0481518 1.1109 28.5722618 1.1109 28.5722618 7.29425366 27.6239537 7.29425366 27.6239537 1.1109 25.1480637 1.1109 25.1480637 0.316390244" />
|
||||||
|
<path
|
||||||
|
d="M37.8398036,0.956463415 C37.1546481,0.956463415 36.6096432,1.21195976 36.2047887,1.72295244 C35.803037,2.23394512 35.6021611,2.93032154 35.6021611,3.81208171 C35.6021611,4.69071911 35.803037,5.38553415 36.2047887,5.89652683 C36.6096432,6.40751951 37.1546481,6.66301585 37.8398036,6.66301585 C38.524959,6.66301585 39.066852,6.40751951 39.4654825,5.89652683 C39.8672343,5.38553415 40.0681102,4.69071911 40.0681102,3.81208171 C40.0681102,2.93032154 39.8672343,2.23394512 39.4654825,1.72295244 C39.0673754,1.21209065 38.5253515,0.956659756 37.8394111,0.956659756 L37.8398036,0.956463415 Z M37.8398036,0.18997439 C38.817708,0.18997439 39.5993998,0.518687398 40.1848789,1.17611341 C40.7703768,1.83043537 41.0631257,2.70908211 41.0631257,3.81205366 C41.0631257,4.91192114 40.7703768,5.79056789 40.1848789,6.4479939 C39.5993811,7.10231585 38.8176893,7.42947683 37.8398036,7.42947683 C36.8587965,7.42947683 36.0739835,7.10231585 35.4853643,6.4479939 C34.8998664,5.79369065 34.6071175,4.9150439 34.6071175,3.81205366 C34.6071175,2.70906341 34.8998664,1.83041667 35.4853643,1.17611341 C36.0739648,0.518687398 36.8587779,0.18997439 37.8398036,0.18997439 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="42.5385893 0.316390244 43.8092239 0.316390244 46.9018436 6.15390244 46.9018436 0.316390244 47.817462 0.316390244 47.817462 7.29408537 46.5468273 7.29408537 43.4542077 1.45657317 43.4542077 7.29408537 42.5385893 7.29408537" />
|
||||||
|
<path
|
||||||
|
d="M14.4888571,14.6357134 L14.4888571,19.7020244 L13.8851641,19.7020244 C13.7044646,18.9049341 13.5319795,18.3009504 13.3677089,17.8900732 C13.2034365,17.4791959 12.981674,17.1176285 12.7024214,16.8053707 C11.9303365,15.9260976 10.3984651,15.486461 8.10680714,15.486461 C7.46615369,15.486461 7.03493637,15.5686346 6.81315518,15.7329817 C6.5995978,15.8891143 6.49281911,16.201372 6.49281911,16.6697549 L6.49281911,22.5369988 C7.74949196,22.5369988 8.64887768,22.269937 9.19097625,21.7358134 C9.73307482,21.2016898 10.1191173,20.2114744 10.3491036,18.7651671 L10.97744,18.7651671 L10.97744,27.3071427 L10.3491036,27.3071427 C10.1684059,25.8444362 9.80290431,24.8336516 9.25259875,24.274789 C8.70229506,23.7077923 7.78236851,23.4119618 6.49281911,23.3872976 L6.49281911,29.2668829 C6.49281911,29.9653724 6.66530417,30.4296545 7.01027429,30.6597293 C7.3552444,30.8815951 8.10678845,31.0171829 9.26490643,31.0664927 L9.26490643,31.695122 L0.184699286,31.695122 L0.184699286,31.0664927 C1.12105476,30.9678844 1.72475714,30.8076417 1.99580643,30.5857646 C2.26685571,30.3638988 2.40238036,29.9242622 2.40238036,29.2668549 L2.40238036,17.051611 C2.40238036,16.4024313 2.25042679,15.9545858 1.94651964,15.7080744 C1.6426125,15.4615443 1.05533905,15.3136337 0.184699286,15.2643427 L0.184699286,14.6357134 L14.4888571,14.6357134 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<polygon id="Shape"
|
||||||
|
points="21.6099286 24.4473171 21.6099286 27.380939 15.4743125 27.380939 15.4743125 24.4473171" />
|
||||||
|
<path
|
||||||
|
d="M25.1956964,29.4035366 L25.1956964,16.9540854 C25.1956964,16.378861 25.0478548,15.9720976 24.7521714,15.7337951 C24.4564881,15.4954927 23.9061751,15.3393638 23.1012323,15.2654085 L23.1012323,14.6367793 L30.7891859,14.6367793 C33.7050871,14.6367793 35.9926145,15.3804553 37.651768,16.8678073 C39.3191267,18.3469504 40.1528061,20.3848813 40.1528061,22.9816 C40.1528061,25.5948114 39.3191267,27.7025837 37.651768,29.3049171 C35.9844093,30.8990976 33.7913623,31.6961878 31.072627,31.6961878 L23.1012323,31.6961878 L23.1012323,31.0675585 C23.8322355,31.0429074 24.3620171,30.8991013 24.690577,30.6361402 C25.027342,30.3731923 25.1957245,29.9623244 25.1957245,29.4035366 L25.1956964,29.4035366 Z M29.2737714,16.374878 L29.2737714,29.3541707 C29.2737714,29.9211675 29.3764382,30.3073898 29.5817718,30.5128378 C29.7871054,30.7100581 30.1731478,30.8086683 30.7398991,30.8086683 C32.3497659,30.8086683 33.585954,30.2293394 34.4484634,29.0706817 C34.8591492,28.503685 35.179476,27.7107085 35.4094436,26.6917524 C35.647635,25.6727963 35.7667307,24.5634671 35.7667307,23.3637646 C35.7667307,21.194285 35.4217606,19.4275858 34.7318204,18.0636671 C33.8776095,16.3462215 32.5552583,15.4874988 30.7647668,15.4874988 C29.7709194,15.4874988 29.2739957,15.7833293 29.2739957,16.3749902 L29.2737714,16.374878 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M46.4748036,20.0576829 L46.4748036,22.1284683 C47.0661889,21.2820683 47.6247164,20.6739801 48.1503861,20.3042037 C48.6842608,19.9344272 49.2633198,19.749539 49.887563,19.749539 C50.4789484,19.749539 50.9676576,19.9385411 51.3536907,20.3165451 C51.7397238,20.6863215 51.9327404,21.1547175 51.9327404,21.7217329 C51.9327404,22.2147744 51.7848987,22.6215378 51.4892154,22.9420232 C51.193532,23.2542809 50.8116015,23.4104098 50.3434237,23.4104098 C50.0148826,23.4104098 49.7397307,23.3446709 49.5179682,23.2131932 C49.2962057,23.0817136 49.0662287,22.8475156 48.8280373,22.5105993 C48.556988,22.1161586 48.3228992,21.9189383 48.1257707,21.9189383 C47.7068798,21.9189383 47.3454807,22.1572407 47.0415736,22.6338456 C46.7376664,23.1022415 46.5857129,23.6651338 46.5857129,24.3225224 L46.5857129,29.0927785 C46.5857129,29.8734322 46.6965941,30.3911285 46.9183566,30.6458676 C47.1483429,30.8923976 47.6493692,31.0403082 48.4214354,31.0895993 L48.4214354,31.6935737 L41.706879,31.6935737 L41.7068818,31.0895993 C42.2654093,30.990991 42.6309109,30.8430804 42.8033866,30.6458676 C42.9840843,30.4486472 43.0744331,30.0911936 43.0744331,29.5735066 L43.0744331,22.1532017 C43.0744331,21.6437237 42.9799808,21.28627 42.7910761,21.0808407 C42.6103766,20.8754115 42.2489776,20.7357192 41.706879,20.6617639 L41.706879,20.0577895 L46.4749129,20.0577895 L46.4748036,20.0576829 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M58.2021429,19.7519512 C59.8284386,19.7519512 61.1795731,20.3394984 62.2555464,21.5145927 C63.3397436,22.6814593 63.8818421,24.1482236 63.8818421,25.9148854 C63.8818421,27.673413 63.3397436,29.1361569 62.2555464,30.3031171 C61.1795731,31.4699837 59.8284386,32.0534171 58.2021429,32.0534171 C56.5512131,32.0534171 55.1877429,31.4699837 54.1117321,30.3031171 C53.0357588,29.1362504 52.4977721,27.6489171 52.4977721,25.8411171 C52.4977721,24.1236715 53.0480852,22.6814967 54.1487113,21.5145927 C55.2493373,20.3394984 56.6004718,19.7519512 58.2021148,19.7519512 L58.2021429,19.7519512 Z M58.2267862,20.5408232 C57.6929115,20.5408232 57.282235,20.7174931 56.9947568,21.0708329 C56.7155024,21.4159638 56.5142714,21.9952927 56.3910637,22.8088195 C56.2678599,23.6223463 56.2062579,24.7851553 56.2062579,26.2972463 C56.2062579,28.1461659 56.349997,29.4363163 56.6374752,30.1676976 C56.9331586,30.8990415 57.4547257,31.2647134 58.2021765,31.2647134 C58.9331797,31.2647134 59.4424204,30.8826049 59.7298986,30.1183878 C60.025582,29.3541707 60.1734236,28.0024065 60.1734236,26.0630951 C60.1734236,23.9923472 60.0296845,22.5542862 59.7422063,21.7489122 C59.4629519,20.943613 58.9578138,20.5409634 58.2267919,20.5409634 L58.2267862,20.5408232 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M69.7332321,20.0576829 L69.7332321,29.6472805 C69.7332321,30.1238854 69.8194747,30.4690163 69.9919597,30.6826732 C70.1644448,30.8881024 70.4724545,31.0236902 70.9159888,31.0894366 L70.9159888,31.693411 L64.891383,31.693411 L64.8913942,31.0894366 C65.4663506,30.9497406 65.8318522,30.7936117 65.987899,30.62105 C66.1439589,30.4402663 66.2219888,30.0910215 66.2219888,29.5733159 L66.2219888,22.153011 C66.2219888,21.6353053 66.1398526,21.2860606 65.9755801,21.1052768 C65.8113077,20.9244931 65.4499086,20.7765825 64.891383,20.6615451 L64.891383,20.0575707 L69.7334312,20.0575707 L69.7332321,20.0576829 Z M66.5792143,14.8313537 C66.9652474,14.4451407 67.4293132,14.2520341 67.9714118,14.2520341 C68.5135104,14.2520341 68.9693617,14.4451407 69.3389659,14.8313537 C69.7167939,15.2175667 69.9057079,15.6818488 69.9057079,16.2242 C69.9057079,16.7747602 69.7167939,17.2349378 69.3389659,17.6047329 C68.9693617,17.9745093 68.5052959,18.1593976 67.9467684,18.1593976 C67.3882409,18.1593976 66.9241751,17.9745093 66.5545709,17.6047329 C66.1849667,17.2349565 66.0001646,16.7665606 66.0001646,16.1995451 C66.0001646,15.6654215 66.1931812,15.2093577 66.5792143,14.8313537 Z"
|
||||||
|
id="Shape" />
|
||||||
|
<path
|
||||||
|
d="M80.0335536,32.0289024 L80.0335536,30.3895354 C79.4421682,31.0140508 78.9041815,31.4495736 78.4195936,31.6961037 C77.9349869,31.9344061 77.3559279,32.0535573 76.6824166,32.0535573 C75.360028,32.0535573 74.2676632,31.4947695 73.405322,30.3771939 C72.542906,29.2514093 72.111698,27.8298037 72.111698,26.1123768 C72.111698,24.2881028 72.5716613,22.7719728 73.4915879,21.5639866 C74.4115144,20.3560191 75.5655579,19.7520354 76.9537182,19.7520354 C77.5286746,19.7520354 78.0379154,19.8670821 78.4814404,20.0971756 C78.9249654,20.3272691 79.4177771,20.7340325 79.9598757,21.3174659 L79.9598757,16.6953073 C79.9598757,16.1200829 79.8489945,15.7502972 79.627232,15.58595 C79.4136746,15.421601 78.883893,15.3065542 78.0378873,15.2408098 L78.0378873,14.6368354 L83.4712087,14.6368354 L83.4712087,29.1447866 C83.4712087,29.6789102 83.5738755,30.0486959 83.7792091,30.2541439 C83.9927665,30.4595732 84.3870234,30.5787244 84.9619798,30.6115976 L84.9619798,31.1909171 L83.3972786,31.3881337 C82.1734636,31.5196133 81.0523154,31.7332702 80.0338339,32.0291044 L80.0335536,32.0289024 Z M79.9596318,28.8734146 L79.9596318,22.734939 C79.7789323,22.2583341 79.507883,21.8803301 79.1464839,21.6009268 C78.7933087,21.3133146 78.4072663,21.1695085 77.9883566,21.1695085 C77.2573534,21.1695085 76.7152548,21.5557309 76.3620609,22.3281756 C76.0170908,23.0923927 75.8446057,24.2880187 75.8446057,25.9150537 C75.8446057,27.5174431 76.0047738,28.7048415 76.3251098,29.4772488 C76.6454459,30.2496935 77.1423696,30.6359159 77.8158809,30.6359159 C78.3744084,30.6359159 78.90419,30.3483037 79.4052256,29.7730793 C79.553071,29.6087302 79.6803811,29.4361648 79.7871561,29.2553829 C79.9021474,29.0746011 79.959643,28.9472315 79.959643,28.8732744 L79.9596318,28.8734146 Z"
|
||||||
|
id="Shape" />
|
||||||
|
</g>
|
||||||
|
<path d="M40.46675,6.67476829 L37.3323571,10.7342683" id="Shape"
|
||||||
|
stroke="#769616"
|
||||||
|
stroke-width="1.84532927" fill="#8AB000" fill-rule="nonzero"
|
||||||
|
stroke-linecap="round" />
|
||||||
|
<path
|
||||||
|
d="M40.4527321,5.75 C40.7872823,5.75886341 41.014708,5.88950341 41.1763059,6.08111585 C39.6808809,7.85918415 39.428952,8.14166341 37.3875595,10.6732622 C36.6353612,11.6468354 35.8517911,11.1436683 36.6039893,10.1700951 L39.7395036,6.11031463 C39.9084496,5.88474354 40.1711695,5.75748902 40.4527882,5.7498878 L40.4527321,5.75 Z"
|
||||||
|
id="Shape" fill-opacity="0.29804" fill="#FFFFFF"
|
||||||
|
fill-rule="nonzero" />
|
||||||
|
<path
|
||||||
|
d="M41.1816607,6.09023171 C41.2730684,6.19940037 41.5956921,6.68413659 41.1982579,7.23888537 L38.0627436,11.2986659 C37.3105454,12.272239 37.2143829,10.8467159 37.2143829,10.8467159 C37.2143829,10.8467159 39.9695927,7.51788659 41.1817168,6.09020366 L41.1816607,6.09023171 Z"
|
||||||
|
id="Shape" fill-opacity="0.2" fill="#263238" fill-rule="nonzero" />
|
||||||
|
<path
|
||||||
|
d="M40.6545893,5.92334146 C40.9778691,5.92334146 41.3627714,6.02785963 41.2626839,6.51281463 C41.1862782,6.88305854 37.8241036,10.9964122 37.8241036,10.9964122 C37.0719054,11.9699854 35.9844561,11.4955963 36.7366543,10.5221634 L39.8606739,6.48257805 C40.0526737,6.26852098 40.3096379,5.93371951 40.6546454,5.92322927 L40.6545893,5.92334146 Z"
|
||||||
|
id="Shape" fill="#8AB000" fill-rule="nonzero" />
|
||||||
|
<path d="M8.87470536,6.67476829 L12.0105,10.7342683" id="Shape"
|
||||||
|
stroke="#769616"
|
||||||
|
stroke-width="1.84532927" fill="#8AB000" fill-rule="nonzero"
|
||||||
|
stroke-linecap="round" />
|
||||||
|
<path
|
||||||
|
d="M8.89124643,5.75 C8.55669625,5.75886341 8.32927054,5.88950341 8.16767268,6.08111585 C9.66309768,7.85918415 9.91502661,8.14166341 11.9564191,10.6732622 C12.7086173,11.6468354 13.4921875,11.1436683 12.7399893,10.1700951 L9.604475,6.11087561 C9.43552898,5.88530451 9.17280911,5.75805 8.89119036,5.75044878 L8.89124643,5.75 Z"
|
||||||
|
id="Shape" fill-opacity="0.29804" fill="#FFFFFF"
|
||||||
|
fill-rule="nonzero" />
|
||||||
|
<path
|
||||||
|
d="M8.16147679,6.09023171 C8.07006914,6.19940037 7.74744536,6.68413659 8.14487964,7.23888537 L11.2803939,11.2986659 C12.0325921,12.272239 12.1287546,10.8467159 12.1287546,10.8467159 C12.1287546,10.8467159 9.37354482,7.51788659 8.16142071,6.09020366 L8.16147679,6.09023171 Z"
|
||||||
|
id="Shape" fill-opacity="0.2" fill="#263238" fill-rule="nonzero" />
|
||||||
|
<path
|
||||||
|
d="M8.68966964,5.92334146 C8.36638982,5.92334146 7.9814875,6.02785963 8.081575,6.51281463 C8.15798073,6.88305854 11.5201554,10.9964122 11.5201554,10.9964122 C12.2723536,11.9699854 13.3598029,11.4955963 12.6076046,10.5221634 L9.483585,6.48257805 C9.29154036,6.26856585 9.03445286,5.93366341 8.68961357,5.92328537 L8.68966964,5.92334146 Z"
|
||||||
|
id="Shape" fill="#8AB000" fill-rule="nonzero" />
|
||||||
|
<rect id="Rectangle-path" fill="#AEEA00" fill-rule="nonzero" x="10.6535714"
|
||||||
|
y="9.25609756" width="28.0357143" height="9.53658537"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<rect id="Rectangle-path" fill-opacity="0.2" fill="#263238"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
x="10.6535714" y="11.4113659" width="28.0357143" height="7.38131707"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<rect id="Rectangle-path" fill-opacity="0.29804" fill="#FFFFFF"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
x="10.6535714" y="9.25806098" width="28.0357143" height="7.38131707"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<rect id="Rectangle-path" fill="#AEEA00" fill-rule="nonzero" x="10.6535714"
|
||||||
|
y="10.098122" width="28.0357143" height="7.85421951"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<rect id="Rectangle-path" fill="#1976D2" fill-rule="nonzero" x="10.6535714"
|
||||||
|
y="19.6341463" width="28.0357143" height="19.0731707"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<rect id="Rectangle-path" fill-opacity="0.2" fill="#263238"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
x="10.6535714" y="29.1118293" width="28.0357143" height="9.5954878"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<rect id="Rectangle-path" fill-opacity="0.2" fill="#FFFFFF"
|
||||||
|
fill-rule="nonzero"
|
||||||
|
x="10.6535714" y="19.5752439" width="28.0357143" height="9.5954878"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<rect id="Rectangle-path" fill="#1976D2" fill-rule="nonzero" x="10.6535714"
|
||||||
|
y="20.4756098" width="28.0357143" height="17.3902439"
|
||||||
|
rx="2.21439512" />
|
||||||
|
<path
|
||||||
|
d="M24.6714286,24.5735366 C22.5461252,24.5735366 20.7467089,26.0384683 20.2201982,28.0061463 L22.5906179,28.0061463 C22.9995748,27.2788415 23.767473,26.7879598 24.6714005,26.7879598 C26.0087882,26.7879598 27.0692111,27.8488768 27.0692111,29.1868598 C27.0692111,30.5248427 26.0087882,31.5857598 24.6714005,31.5857598 C23.7068318,31.5857598 22.8924223,31.0301695 22.5099311,30.2205134 L20.1827425,30.2205134 C20.6565741,32.2619878 22.49339,33.8000988 24.6715407,33.8000988 C27.2051002,33.8000988 29.2825746,31.7215439 29.2825746,29.1869159 C29.2825746,26.6521756 27.204988,24.5737329 24.6715407,24.5737329 L24.6714286,24.5735366 Z"
|
||||||
|
id="Shape" fill="#0D47A1" fill-rule="nonzero" />
|
||||||
|
<ellipse id="Oval" stroke="#0D47A1" stroke-width="1.40243902"
|
||||||
|
stroke-linecap="round"
|
||||||
|
cx="24.6714286" cy="29.187561" rx="7.04593571"
|
||||||
|
ry="7.04921951" />
|
||||||
|
<ellipse id="Oval" fill-opacity="0.2" fill="#263238" fill-rule="nonzero"
|
||||||
|
cx="17.5699821" cy="14.1480854" rx="2.49002"
|
||||||
|
ry="2.86013415" />
|
||||||
|
<ellipse id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="17.5699821"
|
||||||
|
cy="14.5172073" rx="2.49002" ry="2.49118049" />
|
||||||
|
<ellipse id="Oval" fill-opacity="0.2" fill="#263238" fill-rule="nonzero"
|
||||||
|
cx="31.9579107" cy="14.1480854" rx="2.49002"
|
||||||
|
ry="2.86013415" />
|
||||||
|
<ellipse id="Oval" fill="#FFFFFF" fill-rule="nonzero" cx="31.9579107"
|
||||||
|
cy="14.5172073" rx="2.49002" ry="2.49118049" />
|
||||||
|
<path
|
||||||
|
d="M8.89152679,5.74242683 C8.53321466,5.73295225 8.20186636,5.93202601 8.04184972,6.25291205 C7.88183308,6.57379808 7.92213189,6.95837436 8.14518804,7.23908171 L10.8014598,10.6784232 C10.7075486,10.9245568 10.6536163,11.19065 10.6536163,11.4705768 L10.6536163,16.5785402 C10.6536163,17.8053098 11.6406977,18.7928512 12.8668957,18.7928512 L36.4760511,18.7928512 C37.7022491,18.7928512 38.6893306,17.8052817 38.6893306,16.5785402 L38.6893306,11.4705768 C38.6893306,11.1904873 38.6360487,10.9241305 38.5420337,10.6778622 L41.1977728,7.23908171 C41.4136365,6.96742572 41.4588967,6.59756916 41.3149131,6.28183678 C41.1709296,5.96610439 40.8620538,5.75789519 40.5154957,5.74295976 C40.2117646,5.72988939 39.9211038,5.86740249 39.7384859,6.11056707 L37.2114307,9.3827378 C36.9843414,9.30055488 36.7376271,9.25483537 36.4796986,9.25483537 L12.8705432,9.25483537 C12.6122305,9.25483537 12.3657882,9.30072317 12.1356991,9.38138305 L9.60687766,6.10921232 C9.43781797,5.88409848 9.17527379,5.74853032 8.89392945,5.74107207 L8.89152679,5.74242683 Z M12.8669911,19.6341463 C11.640793,19.6341463 10.6537116,20.6216878 10.6537116,21.8484573 L10.6537116,36.4930061 C10.6537116,37.7197756 11.640793,38.7073171 12.8669911,38.7073171 L36.4761464,38.7073171 C37.7023445,38.7073171 38.6894259,37.7197756 38.6894259,36.4930061 L38.6894259,21.8484573 C38.6922295,20.6232866 37.7053723,19.635689 36.4802116,19.635689 L12.8710562,19.635689 L12.8669911,19.6341463 Z"
|
||||||
|
id="Shape" fill="url(#radialGradient-1)" fill-rule="nonzero" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 21 KiB |
70
res/themes/element/img/download/google.svg
Normal file
After Width: | Height: | Size: 12 KiB |
6
res/themes/element/img/logos/element-logo.svg
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M414 204C414 180.804 432.804 162 456 162C610.64 162 736 287.36 736 442C736 465.196 717.196 484 694 484C670.804 484 652 465.196 652 442C652 333.752 564.248 246 456 246C432.804 246 414 227.196 414 204Z" fill="#0DBD8B"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M610 820C610 843.196 591.196 862 568 862C413.36 862 288 736.64 288 582C288 558.804 306.804 540 330 540C353.196 540 372 558.804 372 582C372 690.248 459.752 778 568 778C591.196 778 610 796.804 610 820Z" fill="#0DBD8B"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M204 610C180.804 610 162 591.196 162 568C162 413.36 287.36 288 442 288C465.196 288 484 306.804 484 330C484 353.196 465.196 372 442 372C333.752 372 246 459.752 246 568C246 591.196 227.196 610 204 610Z" fill="#0DBD8B"/>
|
||||||
|
<path fill-rule="evenodd" clip-rule="evenodd" d="M820 414C843.196 414 862 432.804 862 456C862 610.64 736.64 736 582 736C558.804 736 540 717.196 540 694C540 670.804 558.804 652 582 652C690.248 652 778 564.248 778 456C778 432.804 796.804 414 820 414Z" fill="#0DBD8B"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.2 KiB |
BIN
res/themes/element/img/logos/opengraph.png
Normal file
After Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 530 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 8.8 KiB |
Before Width: | Height: | Size: 21 KiB |
Before Width: | Height: | Size: 8.8 KiB |
|
@ -1,6 +0,0 @@
|
||||||
<svg width="42" height="50" viewBox="0 0 42 50" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.04021 42.174C1.04021 45.944 4.27657 49 8.26822 49C12.2603 49 15.4962 45.944 15.4962 42.174V35.2587L22.8119 35.2518C23.2234 35.2518 23.6386 35.2385 24.0415 35.2122C33.5209 34.6096 40.9465 27.1046 40.9465 18.1261C40.9465 8.68273 32.8114 1 22.8119 1H8.26822C4.27657 1 1.04021 4.05637 1.04021 7.82645V27.7141C1.01327 27.9548 0.999582 28.1987 1.00001 28.4459C1.00001 28.6887 1.01412 28.9286 1.04021 29.1645V42.174ZM15.4963 21.6066V14.6525H22.812C24.8405 14.6525 26.4901 16.2103 26.4901 18.1261C26.4901 19.9469 24.9881 21.4692 23.0665 21.5916C22.9822 21.5969 22.8975 21.5993 22.8047 21.5993L15.4963 21.6066Z" fill="#A2DDEF"/>
|
|
||||||
<path d="M15.4963 14.6525V14.0405H14.8844V14.6525H15.4963ZM15.4963 21.6066H14.8844V22.2191L15.4969 22.2185L15.4963 21.6066ZM22.8047 21.5993V20.9874H22.8041L22.8047 21.5993ZM23.0665 21.5916L23.1045 22.2024L23.1053 22.2023L23.0665 21.5916ZM1.04021 29.1645H1.65214V29.1308L1.64843 29.0972L1.04021 29.1645ZM1.00001 28.4459H1.61194L1.61193 28.4449L1.00001 28.4459ZM1.04021 27.7141L1.64834 27.7821L1.65214 27.7482V27.7141H1.04021ZM24.0415 35.2122L24.0027 34.6015L24.0017 34.6016L24.0415 35.2122ZM22.8119 35.2518V34.6399H22.8113L22.8119 35.2518ZM15.4962 35.2587L15.4957 34.6467L14.8843 34.6473V35.2587H15.4962ZM14.8844 14.6525V21.6066H16.1082V14.6525H14.8844ZM15.4969 22.2185L22.8053 22.2112L22.8041 20.9874L15.4957 20.9946L15.4969 22.2185ZM22.8047 22.2112C22.9085 22.2112 23.006 22.2085 23.1045 22.2024L23.0284 20.9809C22.9584 20.9852 22.8865 20.9874 22.8047 20.9874V22.2112ZM23.1053 22.2023C25.3203 22.0612 27.1021 20.2979 27.1021 18.1261H25.8782C25.8782 19.5959 24.6559 20.8772 23.0276 20.9809L23.1053 22.2023ZM27.1021 18.1261C27.1021 15.8399 25.145 14.0405 22.812 14.0405V15.2644C24.536 15.2644 25.8782 16.5808 25.8782 18.1261H27.1021ZM22.812 14.0405H15.4963V15.2644H22.812V14.0405ZM8.26822 48.3881C4.58104 48.3881 1.65214 45.5735 1.65214 42.174H0.428288C0.428288 46.3145 3.97209 49.6119 8.26822 49.6119V48.3881ZM1.65214 42.174V29.1645H0.428288V42.174H1.65214ZM1.64843 29.0972C1.62467 28.8824 1.61193 28.665 1.61193 28.4459H0.388085C0.388085 28.7124 0.403576 28.9748 0.431997 29.2318L1.64843 29.0972ZM1.61193 28.4449C1.61155 28.221 1.62394 28.0001 1.64834 27.7821L0.432085 27.646C0.402599 27.9094 0.387617 28.1765 0.388085 28.447L1.61193 28.4449ZM1.65214 27.7141V7.82645H0.428288V27.7141H1.65214ZM1.65214 7.82645C1.65214 4.42682 4.58109 1.61193 8.26822 1.61193V0.388075C3.97204 0.388075 0.428288 3.68592 0.428288 7.82645H1.65214ZM8.26822 1.61193H22.8119V0.388075H8.26822V1.61193ZM22.8119 1.61193C32.5069 1.61193 40.3346 9.05321 40.3346 18.1261H41.5584C41.5584 8.31226 33.1159 0.388075 22.8119 0.388075V1.61193ZM40.3346 18.1261C40.3346 26.7525 33.1898 34.0175 24.0027 34.6015L24.0804 35.8229C33.8521 35.2017 41.5584 27.4566 41.5584 18.1261H40.3346ZM24.0017 34.6016C23.6124 34.6269 23.2104 34.6399 22.8119 34.6399V35.8637C23.2363 35.8637 23.6649 35.85 24.0813 35.8228L24.0017 34.6016ZM22.8113 34.6399L15.4957 34.6467L15.4968 35.8706L22.8125 35.8637L22.8113 34.6399ZM14.8843 35.2587V42.174H16.1082V35.2587H14.8843ZM14.8843 42.174C14.8843 45.5736 11.9558 48.3881 8.26822 48.3881V49.6119C12.5648 49.6119 16.1082 46.3145 16.1082 42.174H14.8843Z" fill="#368BD6"/>
|
|
||||||
<path d="M8.26823 42.174V7.82642H22.8119C28.8351 7.82642 33.7181 12.4378 33.7181 18.1261C33.7181 23.5784 29.232 28.0412 23.5561 28.4019C23.3098 28.4176 23.0621 28.4257 22.8119 28.4257L8.22803 28.4395" stroke="#368BD6" stroke-width="1.22385" stroke-linecap="round"/>
|
|
||||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M15.4227 9.0113C15.758 7.21673 15.3325 5.4048 14.2243 3.91155C11.9366 0.828522 7.41753 0.0768486 4.15037 2.23574C2.56747 3.28105 1.51106 4.84579 1.17575 6.64116C0.84001 8.43653 1.26557 10.2481 2.37372 11.7413C4.66146 14.8243 9.18092 15.576 12.4481 13.4171C14.0306 12.3714 15.087 10.8071 15.4227 9.0113ZM27.852 46.0868C29.2587 47.9824 31.4998 48.9962 33.7777 48.9962C35.21 48.9962 36.6569 48.5951 37.9195 47.7594C41.1883 45.5965 41.9817 41.3397 39.6905 38.2522L29.4751 24.4846C27.1843 21.3972 22.6769 20.6475 19.408 22.8121C16.1392 24.975 15.3458 29.2318 17.6365 32.3192L27.852 46.0868Z" fill="#368BD6"/>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 4.1 KiB |
BIN
res/vector-icons/1024.png
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
res/vector-icons/120.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
res/vector-icons/1240x600.png
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
res/vector-icons/150.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
res/vector-icons/152.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
res/vector-icons/180.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
res/vector-icons/24.png
Normal file
After Width: | Height: | Size: 434 B |
BIN
res/vector-icons/300.png
Normal file
After Width: | Height: | Size: 3.9 KiB |
BIN
res/vector-icons/44.png
Normal file
After Width: | Height: | Size: 629 B |
BIN
res/vector-icons/50.png
Normal file
After Width: | Height: | Size: 732 B |