...
 
Commits (202)
......@@ -3,7 +3,6 @@ test/
webapp/
lib/
node_modules/
electron_app/
karma-reports/
.idea/
.tmp/
......
......@@ -4,9 +4,6 @@
/key.pem
/lib
/node_modules
/electron_app/node_modules
/electron_app/dist
/electron_app/pub
/packages/
/webapp
/.npmrc
......
Changes in [1.6.1](https://github.com/vector-im/riot-web/releases/tag/v1.6.1) (2020-05-19)
==========================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.6.1-rc.1...v1.6.1)
* Upgrade to React SDK 2.6.0 and JS SDK 6.1.0
Changes in [1.6.1-rc.1](https://github.com/vector-im/riot-web/releases/tag/v1.6.1-rc.1) (2020-05-14)
====================================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.6.0...v1.6.1-rc.1)
* Upgrade to React SDK 2.6.0-rc.1 and JS SDK 6.1.0-rc.1
* Update from Weblate
[\#13673](https://github.com/vector-im/riot-web/pull/13673)
* Add notranslate class to matrixchat to prevent translation by Google
Translate
[\#13669](https://github.com/vector-im/riot-web/pull/13669)
* Added Anchor Link to the development of matrix sdk
[\#13638](https://github.com/vector-im/riot-web/pull/13638)
* Prefetch the formatting button mask svg images
[\#13631](https://github.com/vector-im/riot-web/pull/13631)
* use a different image in previews
[\#13488](https://github.com/vector-im/riot-web/pull/13488)
* Update from Weblate
[\#13625](https://github.com/vector-im/riot-web/pull/13625)
* Remove electron_app as we now have riot-desktop repo
[\#13544](https://github.com/vector-im/riot-web/pull/13544)
* add new images for PWA icons
[\#13556](https://github.com/vector-im/riot-web/pull/13556)
* Remove unused feature flag from config
[\#13504](https://github.com/vector-im/riot-web/pull/13504)
* Update from Weblate
[\#13486](https://github.com/vector-im/riot-web/pull/13486)
* Developer tool: convert rageshake error locations back to sourcecode
locations
[\#13357](https://github.com/vector-im/riot-web/pull/13357)
* App load tweaks, improve error pages
[\#13329](https://github.com/vector-im/riot-web/pull/13329)
* Tweak default device name to be more compact
[\#13465](https://github.com/vector-im/riot-web/pull/13465)
* Tweak default device name on macOS
[\#13460](https://github.com/vector-im/riot-web/pull/13460)
* Update docs with custom theming changes
[\#13406](https://github.com/vector-im/riot-web/pull/13406)
* Update from Weblate
[\#13395](https://github.com/vector-im/riot-web/pull/13395)
* Remove docs and config for invite only padlocks
[\#13374](https://github.com/vector-im/riot-web/pull/13374)
* Revert "Add font scaling labs setting."
[\#13351](https://github.com/vector-im/riot-web/pull/13351)
* Expand feature flag docs to cover additional release channels
[\#13341](https://github.com/vector-im/riot-web/pull/13341)
* Optimized image assets by recompressing without affecting quality.
[\#13034](https://github.com/vector-im/riot-web/pull/13034)
* Add font scaling labs setting.
[\#13199](https://github.com/vector-im/riot-web/pull/13199)
* Remove encrypted message search feature flag
[\#13325](https://github.com/vector-im/riot-web/pull/13325)
* Fix `default_federate` settting description
[\#13312](https://github.com/vector-im/riot-web/pull/13312)
* Clarify that the .well-known method for Jitsi isn't available yet
[\#13314](https://github.com/vector-im/riot-web/pull/13314)
* add config option to tsc resolveJsonModule
[\#13296](https://github.com/vector-im/riot-web/pull/13296)
* Fix dispatcher import to be extension agnostic
[\#13297](https://github.com/vector-im/riot-web/pull/13297)
* Document more config options in config.md (fixes #13089)
[\#13260](https://github.com/vector-im/riot-web/pull/13260)
* Fix tests post-js-sdk-filters change
[\#13295](https://github.com/vector-im/riot-web/pull/13295)
* Make Jitsi download script a JS script
[\#13227](https://github.com/vector-im/riot-web/pull/13227)
* Use matrix-react-sdk type extensions as a base
[\#13271](https://github.com/vector-im/riot-web/pull/13271)
* Allow Riot Web to randomly pick welcome backgrounds
[\#13235](https://github.com/vector-im/riot-web/pull/13235)
* Update cross-signing feature docs and document fallback procedures
[\#13224](https://github.com/vector-im/riot-web/pull/13224)
Changes in [1.6.0](https://github.com/vector-im/riot-web/releases/tag/v1.6.0) (2020-05-05)
==========================================================================================
[Full Changelog](https://github.com/vector-im/riot-web/compare/v1.6.0-rc.6...v1.6.0)
......
......@@ -108,40 +108,7 @@ Riot 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,
build it yourself.
To build it yourself, follow the instructions below.
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/`
To build it yourself, follow the instructions at https://github.com/vector-im/riot-desktop.
Many thanks to @aviraldg for the initial work on the Electron integration.
......@@ -220,7 +187,7 @@ Development
===========
Before attempting to develop on Riot 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.
Before starting work on a feature, it's best to ensure your plan aligns well
......@@ -310,7 +277,7 @@ 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.
**Note**: The build script uses inotify by default on Linux to monitor directories
**Note**: The build script uses inotify by default on Linux to monitor directories
for changes. If the inotify watch limit is too low your build will silently fail.
To avoid this issue, we recommend a limit of at least 128M.
......
module.exports = "css-file-stub";
......@@ -32,7 +32,7 @@ For a good example, see https://riot.im/develop/config.json.
homeserver know what email template to use when talking to you.
1. `branding`: Configures various branding and logo details, such as:
1. `welcomeBackgroundUrl`: An image to use as a wallpaper outside the app
during authentication flows
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
authentication flows
1. `authFooterLinks`: a list of links to show in the authentication page footer:
......@@ -89,6 +89,18 @@ For a good example, see https://riot.im/develop/config.json.
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
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 configurd, 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).
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
......@@ -124,24 +136,11 @@ If none of these sources have an identity server set, then Riot will prompt the
user to set an identity server first when attempting to use features that
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
decentralised.
Desktop app configuration
=========================
To run multiple instances of the desktop app for different accounts, you can
launch the executable with the `--profile` argument followed by a unique
identifier, e.g `riot-web --profile Work` for it to run a separate profile and
not interfere with the default one.
Alternatively, a custom location for the profile data can be specified using the
`--profile-dir` flag followed by the desired path.
+ `%APPDATA%\$NAME\config.json` on Windows
+ `$XDG_CONFIG_HOME\$NAME\config.json` or `~/.config/$NAME/config.json` on Linux
+ `~Library/Application Support/$NAME/config.json` on macOS
In the paths above, `$NAME` is typically `Riot`, unless you use `--profile
$PROFILE` in which case it becomes `Riot-$PROFILE`.
See https://github.com/vector-im/riot-desktop#user-specified-configjson
......@@ -49,7 +49,9 @@ When starting work on a feature, we should create a matching feature flag:
```js
SettingsStore.isFeatureEnabled("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. Add the feature to the set of labs on
[develop](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json)
and [nightly](https://github.com/vector-im/riot-desktop/blob/develop/riot.im/nightly/config.json):
```json
"features": {
"feature_cats": "labs"
......@@ -58,14 +60,18 @@ When starting work on a feature, we should create a matching feature flag:
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
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.
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 `enable` in the
[develop](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json)
and
[nightly](https://github.com/vector-im/riot-desktop/blob/develop/riot.im/nightly/config.json)
configs:
```json
"features": {
......@@ -73,10 +79,21 @@ Set the feature to `enable` in the [develop config](https://github.com/vector-im
},
```
## Enabling by default on staging and app
## Enabling by default on staging, app, and release
Set the feature to `enable` in the
[staging / app](https://github.com/vector-im/riot-web/blob/develop/riot.im/app/config.json)
and
[release](https://github.com/vector-im/riot-desktop/blob/develop/riot.im/release/config.json)
configs.
Set the feature to `enable` in the [app
config](https://github.com/vector-im/riot-web/blob/develop/riot.im/app/config.json).
**Warning:** While this does mean the feature is enabled by default for
https://riot.im and official Riot Desktop builds, it will not be enabled by
default for self-hosted installs, custom desktop builds, etc. To cover those
cases as well, the best options at the moment are converting to a regular
setting defaulted on or to remove the flag. Simply enabling the existing flag by
default in `Settings.js`
[does not work currently](https://github.com/vector-im/riot-web/issues/10360).
## Feature deployed successfully
......@@ -86,8 +103,11 @@ Once we're confident that a feature is working well, we should remove the flag:
2. Remove all `isFeatureEnabled` lines that test for the feature's 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)
[develop](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json),
[nightly](https://github.com/vector-im/riot-desktop/blob/develop/riot.im/nightly/config.json),
[staging / app](https://github.com/vector-im/riot-web/blob/develop/riot.im/app/config.json),
and
[release](https://github.com/vector-im/riot-desktop/blob/develop/riot.im/release/config.json)
configs
5. Celebrate! 🥳
......@@ -107,6 +127,9 @@ regular setting:
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)
[develop](https://github.com/vector-im/riot-web/blob/develop/riot.im/develop/config.json),
[nightly](https://github.com/vector-im/riot-desktop/blob/develop/riot.im/nightly/config.json),
[staging / app](https://github.com/vector-im/riot-web/blob/develop/riot.im/app/config.json),
and
[release](https://github.com/vector-im/riot-desktop/blob/develop/riot.im/release/config.json)
configs
......@@ -40,7 +40,8 @@ should start a new conference on your Jitsi server.
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
default, set the following on your homeserver's `/.well-known/matrix/client` config:
default, and you are using riot-web 1.6 or newer, set the following on your homeserver's
`/.well-known/matrix/client` config:
```json
{
"im.vector.riot.jitsi": {
......
......@@ -67,13 +67,24 @@ 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.
## Cross-signing (in development) (`feature_cross_signing`)
## Cross-signing
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.
The feature is enabled by default and does not follow a traditional labs flag
at the moment. If something goes wrong, add this to your config to disable it:
```json
{
"settingDefaults": {
"feature_cross_signing": false
}
}
```
The setting will be removed in a future release, enabling it non-optionally for
all users.
## Bridge info tab (`feature_bridge_state`)
......
......@@ -54,7 +54,9 @@ eg. in config.json:
"timeline-background-color": "#ffffff",
"timeline-text-color": "#2e2f32",
"timeline-text-secondary-color": "#61708b",
"timeline-highlights-color": "#f3f8fd"
"timeline-highlights-color": "#f3f8fd",
"username-colors": ["#ff0000", ...]
"avatar-background-colors": ["#cc0000", ...]
}
}, {
"name": "Deep Purple",
......@@ -78,3 +80,7 @@ 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.
<?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>
{
"name": "riot-web",
"productName": "Riot",
"main": "src/electron-main.js",
"version": "1.6.0",
"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"
}
}
-----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-----
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.
{
"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"
},
"features": {
"feature_cross_signing": "enable"
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,
"https://matrix-client.matrix.org": false
}
}
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'
This diff is collapsed.
/*
Copyright 2018, 2019 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
const { ipcRenderer } = require('electron');
// expose ipcRenderer to the renderer process
window.ipcRenderer = ipcRenderer;
/*
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 path = require("path");
const fs = require("fs");
const PROTOCOL = "riot://";
const SEARCH_PARAM = "riot-desktop-ssoid";
const STORE_FILE_NAME = "sso-sessions.json";
// we getPath userData before electron-main changes it, so this is the default value
const storePath = path.join(app.getPath("userData"), STORE_FILE_NAME);
const processUrl = (url) => {
if (!global.mainWindow) return;
console.log("Handling link: ", url);
global.mainWindow.loadURL(url.replace(PROTOCOL, "vector://"));
};
const readStore = () => {
try {
const s = fs.readFileSync(storePath, { encoding: "utf8" });
const o = JSON.parse(s);
return typeof o === "object" ? o : {};
} catch (e) {
return {};
}
};
const writeStore = (data) => {
fs.writeFileSync(storePath, JSON.stringify(data));
};
module.exports = {
recordSSOSession: (sessionID) => {
const userDataPath = app.getPath('userData');
const store = readStore();
for (const key in store) {
// ensure each instance only has one (the latest) session ID to prevent the file growing unbounded
if (store[key] === userDataPath) {
delete store[key];
break;
}
}
store[sessionID] = userDataPath;
writeStore(store);
},
getProfileFromDeeplink: (args) => {
// check if we are passed a profile in the SSO callback url
const deeplinkUrl = args.find(arg => arg.startsWith('riot://'));
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
const parsedUrl = new URL(deeplinkUrl);
if (parsedUrl.protocol === 'riot:') {
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM);
const store = readStore();
console.log("Forwarding to profile: ", store[ssoID]);
return store[ssoID];
}
}
},
protocolInit: () => {
// 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
// --profile/--profile-dir are passed via the SEARCH_PARAM var in the callback url
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(PROTOCOL)) return;
processUrl(url);
});
}
},
};
/*
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;
/*
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);
});
};
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);
});
/*
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);
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);
}
});
};
This diff is collapsed.
{
"name": "riot-web",
"productName": "Riot",
"main": "electron_app/src/electron-main.js",
"version": "1.6.0",
"version": "1.6.1",
"description": "A feature-rich client for Matrix.org",
"author": "New Vector Ltd.",
"repository": {
......@@ -35,27 +34,21 @@
"reskindex": "reskindex -h src/header",
"reskindex:watch": "reskindex -h src/header -w",
"reskindex:watch-react": "node scripts/yarn-sub.js matrix-react-sdk reskindex:watch",
"clean": "rimraf lib webapp electron_app/dist",
"clean": "rimraf lib webapp",
"build": "yarn clean && yarn build:genfiles && yarn build:compile && yarn build:types && yarn build:bundle",
"build-stats": "yarn clean && yarn build:genfiles && yarn build:compile && yarn build:types && 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:genfiles": "yarn reskindex && yarn build:res && yarn build:jitsi",
"build:modernizr": "modernizr -c .modernizr.json -d src/vector/modernizr.js",
"build:compile": "babel -d lib --verbose --extensions \".ts,.js,.tsx\" src",
"build:bundle": "cross-env NODE_ENV=production webpack -p --progress --bail --mode production",
"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",
"start": "concurrently --kill-others-on-fail --prefix \"{time} [{name}]\" -n reskindex,reskindex-react,res,riot-js \"yarn reskindex:watch\" \"yarn reskindex:watch-react\" \"yarn start:res\" \"yarn start:js\"",
"start:res": "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",
"electron": "yarn build && yarn install:electron && electron .",
"lint": "yarn lint:types && yarn lint:ts && yarn lint:js && yarn lint:style",
"lint:js": "eslint src",
"lint:ts": "echo 'We don't actually have a typescript linter at this layer because tslint is being removed from our stack. Presumably your TS is fine.'",
......@@ -68,8 +61,8 @@
"favico.js": "^0.3.10",
"gfm.css": "^1.1.2",
"highlight.js": "^9.13.1",
"matrix-js-sdk": "6.0.0",
"matrix-react-sdk": "2.5.0",
"matrix-js-sdk": "6.1.0",
"matrix-react-sdk": "2.6.0",
"olm": "https://packages.matrix.org/npm/olm/olm-3.1.4.tgz",
"postcss-easings": "^2.0.0",
"prop-types": "^15.7.2",
......@@ -109,10 +102,6 @@
"cpx": "^1.3.2",
"cross-env": "^6.0.3",
"css-loader": "^3.3.2",
"electron-builder": "^22.3.2",
"electron-builder-squirrel-windows": "^22.3.2",
"electron-devtools-installer": "^2.2.4",
"electron-notarize": "^0.2.0",
"eslint": "^5.8.0",
"eslint-config-google": "^0.7.1",
"eslint-plugin-babel": "^4.1.2",
......@@ -135,6 +124,7 @@
"minimist": "^1.2.0",
"mkdirp": "^0.5.1",
"modernizr": "^3.6.0",
"node-fetch": "^2.6.0",
"optimize-css-assets-webpack-plugin": "^5.0.3",
"postcss-extend": "^1.0.5",
"postcss-hexrgba": "^2.0.0",
......@@ -155,57 +145,7 @@
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
},
"build": {
"appId": "im.riot.app",
"electronVersion": "7.1.14",
"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"