Compare commits
147 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
53d46343b8 | ||
|
|
aaddcef169 | ||
|
|
0cdf85e20b | ||
|
|
6e455f6bd4 | ||
|
|
f344d8cac4 | ||
|
|
3decdb060e | ||
|
|
92f48eced9 | ||
|
|
045f6f8b42 | ||
|
|
358e3b8f7d | ||
|
|
c6ab88508f | ||
|
|
a4cbe3acab | ||
|
|
4c7bdb35dd | ||
|
|
5735a0abdd | ||
|
|
0e882b80d2 | ||
|
|
6b75b83c00 | ||
|
|
d9e8fa34e7 | ||
|
|
300eac197d | ||
|
|
d49625e253 | ||
|
|
94086f247a | ||
|
|
422a827b82 | ||
|
|
f21c1bee11 | ||
|
|
a6c86b131d | ||
|
|
777003d9a3 | ||
|
|
72334b8cd4 | ||
|
|
5ae86cd728 | ||
|
|
adf4453903 | ||
|
|
180710f54c | ||
|
|
afa40de885 | ||
|
|
96c9b85e11 | ||
|
|
9d15c1bbd0 | ||
|
|
9004ce4fa5 | ||
|
|
174aaa684e | ||
|
|
583caa0aaa | ||
|
|
62736b86f1 | ||
|
|
16c6f9839b | ||
|
|
e3e79fdfe1 | ||
|
|
764835a43c | ||
|
|
769d4cf647 | ||
|
|
b06bba2c69 | ||
|
|
80746c1f22 | ||
|
|
c2a39a4a8e | ||
|
|
e7190e3168 | ||
|
|
78a601fbeb | ||
|
|
6c3edb9a13 | ||
|
|
def85eef19 | ||
|
|
b25479093b | ||
|
|
b839264d9f | ||
|
|
5f01bbd9e0 | ||
|
|
71c8ea417d | ||
|
|
c2cfed72df | ||
|
|
da58f1d3d1 | ||
|
|
735ba9ce75 | ||
|
|
ed9a0a60de | ||
|
|
3a253fe742 | ||
|
|
a00d98a95a | ||
|
|
2cc25f699b | ||
|
|
0978a5042c | ||
|
|
3e80cdedd8 | ||
|
|
358fe6f878 | ||
|
|
8c9352dff0 | ||
|
|
483860fb00 | ||
|
|
7f6a2c6a50 | ||
|
|
94b2ac703a | ||
|
|
332d52cfdc | ||
|
|
e88ef97b87 | ||
|
|
c7683d70b4 | ||
|
|
53950e69ad | ||
|
|
9d650eacbb | ||
|
|
d9047d7960 | ||
|
|
5e2876649d | ||
|
|
bed2eb2c41 | ||
|
|
4a488c9ab2 | ||
|
|
6cc225059a | ||
|
|
2862870bb5 | ||
|
|
4f844d9a64 | ||
|
|
d91034a938 | ||
|
|
46d5e0508b | ||
|
|
ed3a07e61b | ||
|
|
197f1dc451 | ||
|
|
fdb02b93e5 | ||
|
|
c048dff4de | ||
|
|
85dd2504db | ||
|
|
6d5ada7e3f | ||
|
|
72c88c8c87 | ||
|
|
ff84841b52 | ||
|
|
3a2176443c | ||
|
|
5b2139a048 | ||
|
|
386e0be08d | ||
|
|
466a871094 | ||
|
|
1ea9a9d8be | ||
|
|
c859c78621 | ||
|
|
c057dde907 | ||
|
|
4ca58eebf9 | ||
|
|
b337f41a93 | ||
|
|
60d01d1a33 | ||
|
|
fb6c87200e | ||
|
|
9c92b57193 | ||
|
|
910cd9824b | ||
|
|
e368f44ebb | ||
|
|
fda652deaf | ||
|
|
891e7ca234 | ||
|
|
6c04a56579 | ||
|
|
a11feaca32 | ||
|
|
b23cc417e1 | ||
|
|
2da6bc6a1e | ||
|
|
141107c678 | ||
|
|
503442e189 | ||
|
|
43e9c19f8d | ||
|
|
ef94a61b5d | ||
|
|
dde4e2da9b | ||
|
|
c1e20617f5 | ||
|
|
748f4dccb4 | ||
|
|
069f009d85 | ||
|
|
c1646e882a | ||
|
|
0168182f5b | ||
|
|
9cf829730f | ||
|
|
ab2a1e5fdd | ||
|
|
3597f43b73 | ||
|
|
17cbc88d39 | ||
|
|
a95e40506b | ||
|
|
a9b4110d65 | ||
|
|
e10582749b | ||
|
|
d0d14e80ce | ||
|
|
f9d928a534 | ||
|
|
8f4ef2d332 | ||
|
|
a5b809ab06 | ||
|
|
2891019044 | ||
|
|
0beda0bb19 | ||
|
|
193dd0f9e3 | ||
|
|
2c6000c49e | ||
|
|
c2ecef12f2 | ||
|
|
303a7f0bd0 | ||
|
|
861c90c3d8 | ||
|
|
799ccc6197 | ||
|
|
1ca51ced9c | ||
|
|
50bb0b3694 | ||
|
|
edb8b671f3 | ||
|
|
2f0b6ee984 | ||
|
|
ece9040247 | ||
|
|
ffe9121589 | ||
|
|
2203f4628a | ||
|
|
f841622e81 | ||
|
|
b4af8d9ce5 | ||
|
|
188190888b | ||
|
|
b366dbb460 | ||
|
|
19edcd436e | ||
|
|
3da78268d8 |
26
.eslintrc.js
@@ -1,5 +1,3 @@
|
||||
const jsSdkEslintCfg = require('matrix-js-sdk/.eslintrc');
|
||||
|
||||
module.exports = {
|
||||
parserOptions: {
|
||||
ecmaVersion: 8,
|
||||
@@ -10,17 +8,15 @@ module.exports = {
|
||||
// we also have some browser code (ie. the preload script)
|
||||
browser: true,
|
||||
},
|
||||
extends: ["eslint:recommended", "google"],
|
||||
rules: jsSdkEslintCfg.rules,
|
||||
extends: ["matrix-org"],
|
||||
rules: {
|
||||
// js-sdk uses a babel rule which we can't use because we
|
||||
// don't use babel, so remove it & put the original back
|
||||
"babel/no-invalid-this": "off",
|
||||
"no-invalid-this": "error",
|
||||
"quotes": "off",
|
||||
"indent": "off",
|
||||
"prefer-promise-reject-errors": "off",
|
||||
"no-async-promise-executor": "off",
|
||||
}
|
||||
}
|
||||
|
||||
// js-sdk uses a babel rule which we can't use because we
|
||||
// don't use babel, so remove it & put the original back
|
||||
delete module.exports.rules["babel/no-invalid-this"];
|
||||
module.exports.rules["no-invalid-this"] = "error";
|
||||
|
||||
// also override the line length to be consistent with
|
||||
// vector-web / react-sdk rather than js-sdk
|
||||
module.exports.rules["max-len"] = ["warn", {
|
||||
code: 120,
|
||||
}];
|
||||
|
||||
125
CHANGELOG.md
@@ -1,7 +1,132 @@
|
||||
Changes in [1.7.3](https://github.com/vector-im/element-desktop/releases/tag/v1.7.3) (2020-08-05)
|
||||
=================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/element-desktop/compare/v1.7.3-rc.1...v1.7.3)
|
||||
|
||||
* No changes since 1.7.3-rc.1
|
||||
|
||||
Changes in [1.7.3-rc.1](https://github.com/vector-im/riot-desktop/releases/tag/v1.7.3-rc.1) (2020-07-31)
|
||||
========================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.7.2...v1.7.3-rc.1)
|
||||
|
||||
* Clean up linting
|
||||
[\#126](https://github.com/vector-im/riot-desktop/pull/126)
|
||||
* Update renaming workaround for 'Element' name
|
||||
[\#125](https://github.com/vector-im/riot-desktop/pull/125)
|
||||
|
||||
Changes in [1.7.2](https://github.com/vector-im/riot-desktop/releases/tag/v1.7.2) (2020-07-27)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.7.1...v1.7.2)
|
||||
|
||||
* Catch exceptions from main method in fetch script
|
||||
[\#124](https://github.com/vector-im/riot-desktop/pull/124)
|
||||
* Use new eslint package
|
||||
[\#122](https://github.com/vector-im/riot-desktop/pull/122)
|
||||
* Remove ' (Riot)' from app name
|
||||
[\#123](https://github.com/vector-im/riot-desktop/pull/123)
|
||||
|
||||
Changes in [1.7.1](https://github.com/vector-im/riot-desktop/releases/tag/v1.7.1) (2020-07-16)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.7.0...v1.7.1)
|
||||
|
||||
* Bump lodash from 4.17.15 to 4.17.19
|
||||
[\#121](https://github.com/vector-im/riot-desktop/pull/121)
|
||||
* Don't forget nightly when computing userData path
|
||||
[\#120](https://github.com/vector-im/riot-desktop/pull/120)
|
||||
* Fix hosting link
|
||||
[\#119](https://github.com/vector-im/riot-desktop/pull/119)
|
||||
* New macOS icon
|
||||
[\#117](https://github.com/vector-im/riot-desktop/pull/117)
|
||||
* Update README.md
|
||||
[\#118](https://github.com/vector-im/riot-desktop/pull/118)
|
||||
* More icon updates
|
||||
[\#115](https://github.com/vector-im/riot-desktop/pull/115)
|
||||
* Don't forget to yarn install
|
||||
[\#114](https://github.com/vector-im/riot-desktop/pull/114)
|
||||
|
||||
Changes in [1.7.0](https://github.com/vector-im/riot-desktop/releases/tag/v1.7.0) (2020-07-15)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.8...v1.7.0)
|
||||
|
||||
* Fix lint error
|
||||
[\#113](https://github.com/vector-im/riot-desktop/pull/113)
|
||||
* Delabs font-scaling
|
||||
[\#112](https://github.com/vector-im/riot-desktop/pull/112)
|
||||
* Remove room list labs flag from config
|
||||
[\#109](https://github.com/vector-im/riot-desktop/pull/109)
|
||||
* Remove the irc layout setting from labs
|
||||
[\#111](https://github.com/vector-im/riot-desktop/pull/111)
|
||||
* Update npm to ^6.14.6
|
||||
[\#108](https://github.com/vector-im/riot-desktop/pull/108)
|
||||
|
||||
Changes in [1.6.8](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.8) (2020-07-03)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.8-rc.1...v1.6.8)
|
||||
|
||||
* No changes since rc.1
|
||||
|
||||
Changes in [1.6.8-rc.1](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.8-rc.1) (2020-07-01)
|
||||
========================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.7...v1.6.8-rc.1)
|
||||
|
||||
* Show expiring toast on completed downloads to prompt user to open
|
||||
[\#106](https://github.com/vector-im/riot-desktop/pull/106)
|
||||
* Upgrade to Electron 9.0.5
|
||||
[\#107](https://github.com/vector-im/riot-desktop/pull/107)
|
||||
* Add new spinner labs option to config.json
|
||||
[\#105](https://github.com/vector-im/riot-desktop/pull/105)
|
||||
* electron-main: Skip the reindex if we're going to delete the db anyways.
|
||||
[\#104](https://github.com/vector-im/riot-desktop/pull/104)
|
||||
* riot-desktop: Bump the required seshat version.
|
||||
[\#103](https://github.com/vector-im/riot-desktop/pull/103)
|
||||
* main: Add an event index IPC method to check if a room is being indexed.
|
||||
[\#100](https://github.com/vector-im/riot-desktop/pull/100)
|
||||
* electron-main: Add support to set and get the user version.
|
||||
[\#102](https://github.com/vector-im/riot-desktop/pull/102)
|
||||
* Upgrade to Electron 9
|
||||
[\#94](https://github.com/vector-im/riot-desktop/pull/94)
|
||||
|
||||
Changes in [1.6.7](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.7) (2020-06-29)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.6...v1.6.7)
|
||||
|
||||
* No changes since 1.6.6
|
||||
|
||||
Changes in [1.6.6](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.6) (2020-06-23)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.6-rc.1...v1.6.6)
|
||||
|
||||
* No changes since rc.1
|
||||
|
||||
Changes in [1.6.6-rc.1](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.6-rc.1) (2020-06-17)
|
||||
========================================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.5...v1.6.6-rc.1)
|
||||
|
||||
* Upgrade needle to avoid bugs with modern Node
|
||||
[\#101](https://github.com/vector-im/riot-desktop/pull/101)
|
||||
* Fix riot-desktop manual update check getting stuck on Downloading...
|
||||
[\#99](https://github.com/vector-im/riot-desktop/pull/99)
|
||||
* Electron recall latest downloaded update for when the user manually asks
|
||||
[\#98](https://github.com/vector-im/riot-desktop/pull/98)
|
||||
* use keytar to store pickle keys
|
||||
[\#95](https://github.com/vector-im/riot-desktop/pull/95)
|
||||
|
||||
Changes in [1.6.5](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.5) (2020-06-16)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.4...v1.6.5)
|
||||
|
||||
* No changes since 1.6.4
|
||||
|
||||
Changes in [1.6.4](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.4) (2020-06-05)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.3...v1.6.4)
|
||||
|
||||
* No changes since 1.6.3
|
||||
|
||||
Changes in [1.6.3](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.3) (2020-06-04)
|
||||
==============================================================================================
|
||||
[Full Changelog](https://github.com/vector-im/riot-desktop/compare/v1.6.3-rc.1...v1.6.3)
|
||||
|
||||
* No changes since rc.1
|
||||
|
||||
Changes in [1.6.3-rc.1](https://github.com/vector-im/riot-desktop/releases/tag/v1.6.3-rc.1) (2020-06-02)
|
||||
========================================================================================================
|
||||
|
||||
63
README.md
@@ -1,23 +1,31 @@
|
||||
Riot Desktop
|
||||
============
|
||||
Element Desktop
|
||||
===============
|
||||
|
||||
This is Riot desktop app as of release 1.6.
|
||||
Element Desktop is a Matrix client for desktop platforms with Element Web at its core.
|
||||
|
||||
Fetching Riot
|
||||
=============
|
||||
Since this package is just the Electron wrapper for Riot, it doesn't contain any of the Riot code,
|
||||
so the first step is to get a working copy of Riot. There are a few ways of doing this:
|
||||
First Steps
|
||||
===========
|
||||
Before you do anything else, fetch the dependencies:
|
||||
|
||||
```
|
||||
# Fetch the prebuilt release Riot package from the riot.im GitHub releases page. The version
|
||||
# fetched will be the same as the local riot-desktop package.
|
||||
# We're explicitly asking for no config, so the package Riot will have no config.json.
|
||||
yarn install
|
||||
```
|
||||
|
||||
Fetching Element
|
||||
================
|
||||
Since this package is just the Electron wrapper for Element Web, it doesn't contain any of the Element Web code,
|
||||
so the first step is to get a working copy of Element Web. There are a few ways of doing this:
|
||||
|
||||
```
|
||||
# Fetch the prebuilt release Element package from the riot.im GitHub releases page. The version
|
||||
# fetched will be the same as the local element-desktop package.
|
||||
# We're explicitly asking for no config, so the packaged Element will have no config.json.
|
||||
yarn run fetch --noverify --cfgdir ''
|
||||
```
|
||||
|
||||
...or if you'd like to use GPG to verify the downloaded package:
|
||||
```
|
||||
# Fetch the Riot public key from the riot.im web server over a secure connection and import
|
||||
# Fetch the Element public key from the element.io web server over a secure connection and import
|
||||
# it into your local GPG keychain (you'll need GPG installed). You only need to to do this
|
||||
# once.
|
||||
yarn run fetch --importkey
|
||||
@@ -25,10 +33,10 @@ yarn run fetch --importkey
|
||||
yarn run fetch --cfgdir ''
|
||||
```
|
||||
|
||||
...or either of the above, but fetching a specific version of Riot:
|
||||
...or either of the above, but fetching a specific version of Element:
|
||||
```
|
||||
# Fetch the prebuilt release Riot package from the riot.im GitHub releases page. The version
|
||||
# fetched will be the same as the local riot-desktop package.
|
||||
# Fetch the prebuilt release Element package from the riot.im GitHub releases page. The version
|
||||
# fetched will be the same as the local element-desktop package.
|
||||
yarn run fetch --noverify --cfgdir '' v1.5.6
|
||||
```
|
||||
|
||||
@@ -44,15 +52,15 @@ ln -s ../riot-web/webapp ./
|
||||
|
||||
Building
|
||||
========
|
||||
Now you have a copy of Riot, you're ready to build packages. If you'd just like to
|
||||
run Riot locally, skip to the next section.
|
||||
Now you have a copy of Element, you're ready to build packages. If you'd just like to
|
||||
run Element locally, skip to the next section.
|
||||
|
||||
```
|
||||
yarn run build
|
||||
```
|
||||
This will do a couple of things:
|
||||
* Run the `setversion` script to set the local package version to match whatever
|
||||
version of Riot you installed above.
|
||||
version of Element you installed above.
|
||||
* Run electron-builder to build a package. The package built will match the operating system
|
||||
you're running the build process on.
|
||||
|
||||
@@ -102,7 +110,7 @@ yarn start
|
||||
|
||||
Config
|
||||
======
|
||||
If you'd like the packaged Riot to have a configuration file, you can create a
|
||||
If you'd like the packaged Element to have a configuration file, you can create a
|
||||
config directory and place `config.json` in there, then specify this directory
|
||||
with the `--cfgdir` option to `yarn run fetch`, eg:
|
||||
```
|
||||
@@ -110,15 +118,15 @@ mkdir myconfig
|
||||
cp /path/to/my/config.json myconfig/
|
||||
yarn run fetch --cfgdir myconfig
|
||||
```
|
||||
The config dir for the official Riot.im app is in `riot.im`. If you use this,
|
||||
your app will auto-update itself using builds from Riot.im.
|
||||
The config dir for the official Element.im app is in `riot.im`. If you use this,
|
||||
your app will auto-update itself using builds from element.io.
|
||||
|
||||
Profiles
|
||||
========
|
||||
|
||||
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-desktop --profile Work` for it to run a separate profile and
|
||||
identifier, e.g `element-desktop --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
|
||||
@@ -131,5 +139,14 @@ User-specified config.json
|
||||
+ `$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`.
|
||||
In the paths above, `$NAME` is typically `Element`, unless you use `--profile
|
||||
$PROFILE` in which case it becomes `Element-$PROFILE`, or it is using one of
|
||||
the above created by a pre-1.7 install, in which case it will be `Riot` or
|
||||
`Riot-$PROFILE`.
|
||||
|
||||
Report bugs & give feedback
|
||||
==========================
|
||||
|
||||
If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.
|
||||
|
||||
To help avoid duplicate issues, please [view existing issues](https://github.com/vector-im/riot-web/issues?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc) first (and add a +1) or [create a new issue](https://github.com/vector-im/riot-web/issues/new) if you can't find it. Please note that this issue tracker is associated with the [Riot-Web](https://github.com/vector-im/riot-web) repo, but is also applied to the code in this repo as well.
|
||||
|
||||
BIN
build/icon.icns
BIN
build/icon.ico
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 2.7 KiB |
|
Before Width: | Height: | Size: 702 B After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 4.4 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 8.1 KiB |
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 256 KiB |
51
build/rebrand_stub/rebrand_stub.c
Normal file
@@ -0,0 +1,51 @@
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <tchar.h>
|
||||
|
||||
/*
|
||||
* This just runs 'Element.exe' with the same args as
|
||||
* this process was invoked with. This gets around the fact that
|
||||
* squirrel always tries to run an executable with the same name,
|
||||
* so fails to restart if the app's name has changed.
|
||||
*/
|
||||
void _tmain( int argc, TCHAR *argv[] )
|
||||
{
|
||||
LPSTR myCmdLine = GetCommandLineA();
|
||||
char cmdLine[32767];
|
||||
|
||||
LPSTR cmdLinePos = cmdLine;
|
||||
LPSTR toRun = "\"Element.exe\" ";
|
||||
strncpy(cmdLinePos, toRun, strlen(toRun));
|
||||
cmdLinePos += strlen(toRun);
|
||||
|
||||
if (myCmdLine[0] == '"') ++myCmdLine;
|
||||
myCmdLine += strlen(argv[0]);
|
||||
if (myCmdLine[0] == '"') ++myCmdLine;
|
||||
if (myCmdLine[0] == ' ') ++myCmdLine;
|
||||
|
||||
strncpy(cmdLinePos, myCmdLine, (cmdLine + 32767) - cmdLinePos);
|
||||
|
||||
STARTUPINFO si;
|
||||
PROCESS_INFORMATION pi;
|
||||
|
||||
ZeroMemory(&si, sizeof(si));
|
||||
si.cb = sizeof(si);
|
||||
ZeroMemory(&pi, sizeof(pi));
|
||||
|
||||
if (!CreateProcess(NULL,
|
||||
cmdLine, // Command line
|
||||
NULL, // Process handle not inheritable
|
||||
NULL, // Thread handle not inheritable
|
||||
FALSE, // Set handle inheritance to FALSE
|
||||
0, // No creation flags
|
||||
NULL, // Use parent's environment block
|
||||
NULL, // Use parent's starting directory
|
||||
&si, // Pointer to STARTUPINFO structure
|
||||
&pi ) // Pointer to PROCESS_INFORMATION structure
|
||||
)
|
||||
{
|
||||
printf("CreateProcess failed (%d).\n", GetLastError());
|
||||
return;
|
||||
}
|
||||
}
|
||||
BIN
build/rebrand_stub/rebrand_stub.exe
Normal file
6
element.io/README
Normal file
@@ -0,0 +1,6 @@
|
||||
This directory contains the config file for the official element.io distribution
|
||||
of Element Desktop.
|
||||
|
||||
You probably do not want to build with this config unless you're building the
|
||||
official element.io distribution, or you'll find your builds will replace
|
||||
themselves with the element.io build.
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"update_base_url": "https://packages.riot.im/nightly/update/",
|
||||
"default_server_name": "matrix.org",
|
||||
"brand": "Riot Nightly",
|
||||
"brand": "Element Nightly",
|
||||
"integrations_ui_url": "https://scalar-staging.vector.im/",
|
||||
"integrations_rest_url": "https://scalar-staging.vector.im/api",
|
||||
"integrations_widgets_urls": [
|
||||
@@ -11,9 +11,10 @@
|
||||
"https://scalar-staging.vector.im/api",
|
||||
"https://scalar-staging.riot.im/scalar/api"
|
||||
],
|
||||
"hosting_signup_link": "https://modular.im/services/matrix-hosting-riot?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",
|
||||
"features": {
|
||||
"feature_new_spinner": "labs",
|
||||
"feature_pinning": "labs",
|
||||
"feature_custom_status": "labs",
|
||||
"feature_custom_tags": "labs",
|
||||
@@ -23,10 +24,7 @@
|
||||
"feature_dm_verification": "labs",
|
||||
"feature_bridge_state": "labs",
|
||||
"feature_presence_in_room_list": "labs",
|
||||
"feature_custom_themes": "labs",
|
||||
"feature_new_room_list": "labs",
|
||||
"feature_irc_ui": "labs",
|
||||
"feature_font_scaling": "labs"
|
||||
"feature_custom_themes": "labs"
|
||||
},
|
||||
"piwik": {
|
||||
"url": "https://piwik.riot.im/",
|
||||
@@ -1,11 +1,11 @@
|
||||
Package: riot-nightly
|
||||
Package: element-nightly
|
||||
License: Apache-2.0
|
||||
Vendor: support@riot.im
|
||||
Vendor: support@element.io
|
||||
Architecture: amd64
|
||||
Maintainer: support@riot.im
|
||||
Maintainer: support@element.io
|
||||
Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libappindicator3-1, libsecret-1-0, libsqlcipher0
|
||||
Section: net
|
||||
Priority: extra
|
||||
Homepage: https://riot.im/
|
||||
Homepage: https://element.io/
|
||||
Description:
|
||||
A feature-rich client for Matrix.org (nightly unstable build).
|
||||
riot.im A feature-rich client for Matrix.org (nightly unstable build).
|
||||
@@ -0,0 +1,9 @@
|
||||
Package: riot-nightly
|
||||
Version: 2020071502
|
||||
Depends: element-nightly
|
||||
Maintainer: packages@element.io
|
||||
Architecture: all
|
||||
Priority: optional
|
||||
Section: oldlibs
|
||||
Description: transitional package
|
||||
This is a transitional package. It can safely be removed.
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"update_base_url": "https://packages.riot.im/desktop/update/",
|
||||
"default_server_name": "matrix.org",
|
||||
"brand": "Riot",
|
||||
"brand": "Element",
|
||||
"integrations_ui_url": "https://scalar.vector.im/",
|
||||
"integrations_rest_url": "https://scalar.vector.im/api",
|
||||
"integrations_widgets_urls": [
|
||||
@@ -11,7 +11,7 @@
|
||||
"https://scalar-staging.vector.im/api",
|
||||
"https://scalar-staging.riot.im/scalar/api"
|
||||
],
|
||||
"hosting_signup_link": "https://modular.im/services/matrix-hosting-riot?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",
|
||||
"roomDirectory": {
|
||||
"servers": [
|
||||
@@ -1,13 +1,13 @@
|
||||
Package: riot-desktop
|
||||
Package: element-desktop
|
||||
License: Apache-2.0
|
||||
Vendor: support@riot.im
|
||||
Vendor: support@element.io
|
||||
Architecture: amd64
|
||||
Maintainer: support@riot.im
|
||||
Maintainer: support@element.io
|
||||
Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libappindicator3-1, libsecret-1-0, libsqlcipher0
|
||||
Provides: riot-web
|
||||
Replaces: riot-web
|
||||
Replaces: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)
|
||||
Breaks: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)
|
||||
Section: net
|
||||
Priority: extra
|
||||
Homepage: https://riot.im/
|
||||
Homepage: https://element.io/
|
||||
Description:
|
||||
A feature-rich client for Matrix.org
|
||||
9
element.io/release/riot-desktop_1.7.0_all/DEBIAN/control
Normal file
@@ -0,0 +1,9 @@
|
||||
Package: riot-desktop
|
||||
Version: 1.7.0
|
||||
Depends: element-desktop
|
||||
Maintainer: packages@element.io
|
||||
Architecture: all
|
||||
Priority: optional
|
||||
Section: oldlibs
|
||||
Description: transitional package
|
||||
This is a transitional package. It can safely be removed.
|
||||
42
hak/keytar/build.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
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 path = require('path');
|
||||
const childProcess = require('child_process');
|
||||
|
||||
module.exports = async function(hakEnv, moduleInfo) {
|
||||
await buildKeytar(hakEnv, moduleInfo);
|
||||
};
|
||||
|
||||
async function buildKeytar(hakEnv, moduleInfo) {
|
||||
const env = hakEnv.makeGypEnv();
|
||||
|
||||
console.log("Running yarn with env", env);
|
||||
await new Promise((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
path.join(moduleInfo.nodeModuleBinDir, 'node-gyp' + (hakEnv.isWin() ? '.cmd' : '')),
|
||||
['rebuild'],
|
||||
{
|
||||
cwd: moduleInfo.moduleBuildDir,
|
||||
env,
|
||||
stdio: 'inherit',
|
||||
},
|
||||
);
|
||||
proc.on('exit', (code) => {
|
||||
code ? reject(code) : resolve();
|
||||
});
|
||||
});
|
||||
}
|
||||
36
hak/keytar/check.js
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
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 childProcess = require('child_process');
|
||||
|
||||
module.exports = async function(hakEnv, moduleInfo) {
|
||||
const tools = [['python', '--version']]; // node-gyp uses python for reasons beyond comprehension
|
||||
|
||||
for (const tool of tools) {
|
||||
await new Promise((resolve, reject) => {
|
||||
const proc = childProcess.spawn(tool[0], tool.slice(1), {
|
||||
stdio: ['ignore'],
|
||||
});
|
||||
proc.on('exit', (code) => {
|
||||
if (code !== 0) {
|
||||
reject("Can't find " + tool);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
10
hak/keytar/hak.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"scripts": {
|
||||
"check": "check.js",
|
||||
"build": "build.js"
|
||||
},
|
||||
"copy": "build/Release/keytar.node",
|
||||
"dependencies": {
|
||||
"libsecret": "0.20.3"
|
||||
}
|
||||
}
|
||||
38
package.json
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "riot-desktop",
|
||||
"productName": "Riot",
|
||||
"name": "element-desktop",
|
||||
"productName": "Element",
|
||||
"main": "src/electron-main.js",
|
||||
"version": "1.6.3",
|
||||
"version": "1.7.3",
|
||||
"description": "A feature-rich client for Matrix.org",
|
||||
"author": "New Vector Ltd.",
|
||||
"author": "Element",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/vector-im/riot-desktop"
|
||||
@@ -38,31 +38,30 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"asar": "^2.0.1",
|
||||
"electron-builder": "^22.3.2",
|
||||
"electron-builder-squirrel-windows": "^22.3.2",
|
||||
"electron-builder": "^22.7.0",
|
||||
"electron-builder-squirrel-windows": "^22.7.0",
|
||||
"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",
|
||||
"eslint": "7.3.1",
|
||||
"eslint-config-matrix-org": "^0.1.2",
|
||||
"find-npm-prefix": "^1.0.2",
|
||||
"fs-extra": "^8.1.0",
|
||||
"glob": "^7.1.6",
|
||||
"matrix-js-sdk": "6.2.0",
|
||||
"mkdirp": "^1.0.3",
|
||||
"needle": "^2.3.2",
|
||||
"node-pre-gyp": "^0.14.0",
|
||||
"npm": "^6.13.7",
|
||||
"needle": "^2.5.0",
|
||||
"node-pre-gyp": "^0.15.0",
|
||||
"npm": "^6.14.6",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.1.3",
|
||||
"tar": "^6.0.1"
|
||||
},
|
||||
"hakDependencies": {
|
||||
"matrix-seshat": "^1.3.3"
|
||||
"matrix-seshat": "^2.1.0",
|
||||
"keytar": "^5.6.0"
|
||||
},
|
||||
"build": {
|
||||
"appId": "im.riot.app",
|
||||
"electronVersion": "8.0.3",
|
||||
"electronVersion": "9.0.5",
|
||||
"files": [
|
||||
"package.json",
|
||||
{
|
||||
@@ -81,9 +80,9 @@
|
||||
"linux": {
|
||||
"target": "deb",
|
||||
"category": "Network;InstantMessaging;Chat",
|
||||
"maintainer": "support@riot.im",
|
||||
"maintainer": "support@element.io",
|
||||
"desktop": {
|
||||
"StartupWMClass": "riot"
|
||||
"StartupWMClass": "element"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
@@ -99,12 +98,13 @@
|
||||
"directories": {
|
||||
"output": "dist"
|
||||
},
|
||||
"afterPack": "scripts/electron_afterPack",
|
||||
"afterSign": "scripts/electron_afterSign",
|
||||
"protocols": [
|
||||
{
|
||||
"name": "riot",
|
||||
"name": "element",
|
||||
"schemes": [
|
||||
"riot"
|
||||
"element"
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
50
release.sh
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Script to perform a release of riot-desktop.
|
||||
# Script to perform a release of element-desktop.
|
||||
#
|
||||
# Requires githib-changelog-generator; to install, do
|
||||
# pip install git+https://github.com/matrix-org/github-changelog-generator.git
|
||||
@@ -9,52 +9,4 @@ set -e
|
||||
|
||||
cd `dirname $0`
|
||||
|
||||
for i in matrix-js-sdk
|
||||
do
|
||||
echo "Checking version of $i..."
|
||||
depver=`cat package.json | jq -r .devDependencies[\"$i\"]`
|
||||
latestver=`yarn info -s $i dist-tags.next`
|
||||
if [ "$depver" != "$latestver" ]
|
||||
then
|
||||
echo "The latest version of $i is $latestver but package.json depends on $depver."
|
||||
echo -n "Type 'u' to auto-upgrade, 'c' to continue anyway, or 'a' to abort:"
|
||||
read resp
|
||||
if [ "$resp" != "u" ] && [ "$resp" != "c" ]
|
||||
then
|
||||
echo "Aborting."
|
||||
exit 1
|
||||
fi
|
||||
if [ "$resp" == "u" ]
|
||||
then
|
||||
echo "Upgrading $i to $latestver..."
|
||||
yarn add -ED $i@$latestver
|
||||
git add -u
|
||||
# The `-e` flag opens the editor and gives you a chance to check
|
||||
# the upgrade for correctness.
|
||||
git commit -m "Upgrade $i to $latestver" -e
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
./node_modules/matrix-js-sdk/release.sh -n -z "$@"
|
||||
|
||||
release="${1#v}"
|
||||
prerelease=0
|
||||
# We check if this build is a prerelease by looking to
|
||||
# see if the version has a hyphen in it. Crude,
|
||||
# but semver doesn't support postreleases so anything
|
||||
# with a hyphen is a prerelease.
|
||||
echo $release | grep -q '-' && prerelease=1
|
||||
|
||||
if [ $prerelease -eq 0 ]
|
||||
then
|
||||
# For a release, reset SDK deps back to the `develop` branch.
|
||||
for i in matrix-js-sdk
|
||||
do
|
||||
echo "Resetting $i to develop branch..."
|
||||
yarn add -D github:matrix-org/$i#develop
|
||||
git add -u
|
||||
git commit -m "Reset $i back to develop branch"
|
||||
done
|
||||
git push origin develop
|
||||
fi
|
||||
|
||||
BIN
res/img/element.ico
Normal file
|
After Width: | Height: | Size: 22 KiB |
BIN
res/img/element.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
res/img/riot.ico
|
Before Width: | Height: | Size: 36 KiB |
BIN
res/img/riot.png
|
Before Width: | Height: | Size: 13 KiB |
@@ -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.
|
||||
@@ -2,12 +2,4 @@
|
||||
|
||||
set -ex
|
||||
|
||||
scripts/fetchdep.sh matrix-org matrix-js-sdk
|
||||
|
||||
pushd matrix-js-sdk
|
||||
yarn link
|
||||
yarn install $@
|
||||
popd
|
||||
|
||||
yarn link matrix-js-sdk
|
||||
yarn install $@
|
||||
|
||||
@@ -1,170 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 -v <version> -d <config directory> [-n]"
|
||||
echo
|
||||
echo "version: commit-ish to check out and build"
|
||||
echo "config directory: a path to a directory containing"
|
||||
echo "config.json, a json config file to ship with the build"
|
||||
echo "and env.sh, a file to source environment variables"
|
||||
echo "from."
|
||||
echo "-n: build with no config file."
|
||||
echo
|
||||
echo "The update_base_url value from config.json is used to set up auto-update."
|
||||
echo
|
||||
echo "Environment variables:"
|
||||
echo " OSSLSIGNCODE_SIGNARGS: Arguments to pass to osslsigncode when signing"
|
||||
echo " NOTARIZE_APPLE_ID: Apple ID to use for notarisation. The password for"
|
||||
echo " this account must be set in NOTARIZE_CREDS in the keychain."
|
||||
}
|
||||
|
||||
confdir=
|
||||
version=
|
||||
skipcfg=0
|
||||
while getopts "d:v:n" opt; do
|
||||
case $opt in
|
||||
d)
|
||||
confdir=$OPTARG
|
||||
;;
|
||||
v)
|
||||
version=$OPTARG
|
||||
;;
|
||||
n)
|
||||
skipcfg=1
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: -$OPTARG" >&2
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if [ -z "$version" ]; then
|
||||
echo "No version supplied"
|
||||
usage
|
||||
exit
|
||||
fi
|
||||
|
||||
conffile="$confdir/config.json"
|
||||
|
||||
if [ -z "$conffile" ] && [ "$skipcfg" = 0 ]; then
|
||||
echo "No config file given. Use -c to supply a config file or"
|
||||
echo "-n to build with no config file (and no auto update)."
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -n "$conffile" ]; then
|
||||
update_base_url=`jq -r .update_base_url $conffile`
|
||||
|
||||
if [ -z "$update_base_url" ]; then
|
||||
echo "No update URL supplied. Use update_base_url: null if you really"
|
||||
echo "want a build with no auto-update."
|
||||
usage
|
||||
exit
|
||||
fi
|
||||
# Make sure the base URL ends in a slash if it doesn't already
|
||||
update_base_url=`echo $update_base_url | sed -e 's#\([^\/]\)$#\1\/#'`
|
||||
fi
|
||||
|
||||
if [ ! -f package.json ]; then
|
||||
echo "No package.json found. This script must be run from"
|
||||
echo "the riot-web directory."
|
||||
exit
|
||||
fi
|
||||
|
||||
[ -f "$confdir/env.sh" ] && . "$confdir/env.sh"
|
||||
|
||||
if [ -z "$NOTARIZE_APPLE_ID" ]; then
|
||||
echo "NOTARIZE_APPLE_ID is not set"
|
||||
exit
|
||||
fi
|
||||
|
||||
osslsigncode -h 2> /dev/null
|
||||
if [ $? -ne 255 ]; then # osslsigncode exits with 255 after printing usage...
|
||||
echo "osslsigncode not found"
|
||||
exit
|
||||
fi
|
||||
|
||||
# Test that altool can get its credentials for notarising the mac app
|
||||
xcrun altool -u "$NOTARIZE_APPLE_ID" -p '@keychain:NOTARIZE_CREDS' --list-apps || exit
|
||||
|
||||
# Get the token password: we'll need it later, but get it now so we fail early if it's not there
|
||||
token_password=`security find-generic-password -s riot_signing_token -w`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "riot_signing_token not found in keychain"
|
||||
exit
|
||||
fi
|
||||
|
||||
set -e
|
||||
|
||||
echo "Building $version using Update base URL $update_base_url"
|
||||
|
||||
projdir=`pwd`
|
||||
builddir=`mktemp -d 2>/dev/null || mktemp -d -t 'buildtmp'`
|
||||
pushd "$builddir"
|
||||
|
||||
git clone "$projdir" .
|
||||
git checkout "$version"
|
||||
|
||||
# Figure out what version we're building
|
||||
vername=`jq -r .version package.json`
|
||||
|
||||
if [ -n "$conffile" ]; then
|
||||
popd
|
||||
cp "$conffile" "$builddir/"
|
||||
pushd "$builddir"
|
||||
fi
|
||||
|
||||
# We use Git branch / commit dependencies for some packages, and Yarn seems
|
||||
# to have a hard time getting that right. See also
|
||||
# https://github.com/yarnpkg/yarn/issues/4734. As a workaround, we clean the
|
||||
# global cache here to ensure we get the right thing.
|
||||
yarn cache clean
|
||||
yarn install
|
||||
yarn build:electron
|
||||
|
||||
popd
|
||||
|
||||
distdir="$builddir/electron_app/dist"
|
||||
pubdir="$projdir/electron_app/pub"
|
||||
rm -r "$pubdir" || true
|
||||
mkdir -p "$pubdir"
|
||||
rm -r "$projdir/electron_app/dist" || true
|
||||
mkdir -p "$projdir/electron_app/dist"
|
||||
|
||||
# Install packages: what the user downloads the first time,
|
||||
# (DMGs for mac, exe installer for windows)
|
||||
mkdir -p "$pubdir/install/macos"
|
||||
cp $distdir/*.dmg "$pubdir/install/macos/"
|
||||
|
||||
mkdir -p "$pubdir/install/win32/ia32/"
|
||||
cp $distdir/squirrel-windows-ia32/*.exe "$pubdir/install/win32/ia32/"
|
||||
|
||||
mkdir -p "$pubdir/install/win32/x64/"
|
||||
cp $distdir/squirrel-windows/*.exe "$pubdir/install/win32/x64/"
|
||||
|
||||
# Packages for auto-update
|
||||
mkdir -p "$pubdir/update/macos"
|
||||
cp $distdir/*-mac.zip "$pubdir/update/macos/"
|
||||
echo "$vername" > "$pubdir/update/macos/latest"
|
||||
|
||||
mkdir -p "$pubdir/update/win32/ia32/"
|
||||
cp $distdir/squirrel-windows-ia32/*.nupkg "$pubdir/update/win32/ia32/"
|
||||
cp $distdir/squirrel-windows-ia32/RELEASES "$pubdir/update/win32/ia32/"
|
||||
|
||||
mkdir -p "$pubdir/update/win32/x64/"
|
||||
cp $distdir/squirrel-windows/*.nupkg "$pubdir/update/win32/x64/"
|
||||
cp $distdir/squirrel-windows/RELEASES "$pubdir/update/win32/x64/"
|
||||
|
||||
# Move the deb to the main project dir's dist folder
|
||||
# (just the 64 bit one - the 32 bit one still gets built because
|
||||
# it's one arch argument for all platforms and we still want 32 bit
|
||||
# windows, but 32 bit linux is unsupported as of electron 4 and no
|
||||
# longer appears to work).
|
||||
cp $distdir/*_amd64.deb "$projdir/electron_app/dist/"
|
||||
|
||||
rm -rf "$builddir"
|
||||
|
||||
echo "$pubdir can now be hosted on your web server."
|
||||
echo "deb archives are in electron_app/dist/ - these should be added into your debian repository"
|
||||
15
scripts/electron_afterPack.js
Normal file
@@ -0,0 +1,15 @@
|
||||
const fsProm = require('fs').promises;
|
||||
const path = require('path');
|
||||
|
||||
exports.default = async function(context) {
|
||||
const { electronPlatformName, appOutDir } = context;
|
||||
|
||||
// Squirrel windows will try to relaunch the app using an executable of the same name as
|
||||
// before in the new version, so will fail if the executable is now called something else.
|
||||
// We add a fake Riot.exe that it can run which runs the real one.
|
||||
// This also gets signed automatically, presumably because electron-build just looks for all
|
||||
// exe files and signs them all...
|
||||
if (electronPlatformName === 'win32') {
|
||||
await fsProm.copyFile('build/rebrand_stub/rebrand_stub.exe', path.join(appOutDir, "Riot.exe"));
|
||||
}
|
||||
};
|
||||
@@ -24,7 +24,7 @@ function computeSignToolArgs(options, keyContainer) {
|
||||
// so we don't have to hard-code this here
|
||||
// fwiw https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing
|
||||
// is about the most useful resource on automating code signing...
|
||||
args.push('/f', 'riot.im\\New_Vector_Ltd.pem');
|
||||
args.push('/f', 'element.io\\New_Vector_Ltd.pem');
|
||||
|
||||
if (options.hash !== "sha1") {
|
||||
args.push("/fd", options.hash);
|
||||
|
||||
@@ -289,4 +289,4 @@ async function main() {
|
||||
console.log("Done!");
|
||||
}
|
||||
|
||||
main().then((ret) => process.exit(ret));
|
||||
main().then((ret) => process.exit(ret)).catch(e => process.exit(1));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
hak
|
||||
===
|
||||
|
||||
This tool builds native dependencies for riot-desktop. Here follows some very minimal
|
||||
This tool builds native dependencies for element-desktop. Here follows some very minimal
|
||||
documentation for it.
|
||||
|
||||
Goals:
|
||||
|
||||
@@ -3,6 +3,7 @@ Copyright 2016 Aviral Dasgupta
|
||||
Copyright 2016 OpenMarket Ltd
|
||||
Copyright 2018, 2019 New Vector Ltd
|
||||
Copyright 2017, 2019 Michael Telatynski <7t3chguy@gmail.com>
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -43,6 +44,18 @@ const Store = require('electron-store');
|
||||
const fs = require('fs');
|
||||
const afs = fs.promises;
|
||||
|
||||
const crypto = require('crypto');
|
||||
let keytar;
|
||||
try {
|
||||
keytar = require('keytar');
|
||||
} catch (e) {
|
||||
if (e.code === "MODULE_NOT_FOUND") {
|
||||
console.log("Keytar isn't installed; secure key storage is disabled.");
|
||||
} else {
|
||||
console.warn("Keytar unexpected error:", e);
|
||||
}
|
||||
}
|
||||
|
||||
let seshatSupported = false;
|
||||
let Seshat;
|
||||
let SeshatRecovery;
|
||||
@@ -86,15 +99,43 @@ if (argv["help"]) {
|
||||
app.exit();
|
||||
}
|
||||
|
||||
// Electron creates the user data directory (with just an empty 'Dictionaries' directory...)
|
||||
// as soon as the app path is set, so pick a random path in it that must exist if it's a
|
||||
// real user data directory.
|
||||
function isRealUserDataDir(d) {
|
||||
return fs.existsSync(path.join(d, 'IndexedDB'));
|
||||
}
|
||||
|
||||
// check if we are passed a profile in the SSO callback url
|
||||
let userDataPath;
|
||||
|
||||
const userDataPathInProtocol = getProfileFromDeeplink(argv["_"]);
|
||||
if (userDataPathInProtocol) {
|
||||
app.setPath('userData', userDataPathInProtocol);
|
||||
userDataPath = userDataPathInProtocol;
|
||||
} else if (argv['profile-dir']) {
|
||||
app.setPath('userData', argv['profile-dir']);
|
||||
} else if (argv['profile']) {
|
||||
app.setPath('userData', `${app.getPath('userData')}-${argv['profile']}`);
|
||||
userDataPath = argv['profile-dir'];
|
||||
} else {
|
||||
let newUserDataPath = app.getPath('userData');
|
||||
if (argv['profile']) {
|
||||
newUserDataPath += '-' + argv['profile'];
|
||||
}
|
||||
const newUserDataPathExists = isRealUserDataDir(newUserDataPath);
|
||||
let oldUserDataPath = path.join(app.getPath('appData'), app.getName().replace('Element', 'Riot'));
|
||||
if (argv['profile']) {
|
||||
oldUserDataPath += '-' + argv['profile'];
|
||||
}
|
||||
|
||||
const oldUserDataPathExists = isRealUserDataDir(oldUserDataPath);
|
||||
console.log(newUserDataPath + " exists: " + (newUserDataPathExists ? 'yes' : 'no'));
|
||||
console.log(oldUserDataPath + " exists: " + (oldUserDataPathExists ? 'yes' : 'no'));
|
||||
if (!newUserDataPathExists && oldUserDataPathExists) {
|
||||
console.log("Using legacy user data path: " + oldUserDataPath);
|
||||
userDataPath = oldUserDataPath;
|
||||
} else {
|
||||
userDataPath = newUserDataPath;
|
||||
}
|
||||
}
|
||||
app.setPath('userData', userDataPath);
|
||||
|
||||
async function tryPaths(name, root, rawPaths) {
|
||||
// Make everything relative to root
|
||||
@@ -169,16 +210,16 @@ async function setupGlobals() {
|
||||
|
||||
// The tray icon
|
||||
// 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 iconFile = `element.${process.platform === 'win32' ? 'ico' : 'png'}`;
|
||||
iconPath = path.join(resPath, "img", iconFile);
|
||||
trayConfig = {
|
||||
icon_path: iconPath,
|
||||
brand: vectorConfig.brand || 'Riot',
|
||||
brand: vectorConfig.brand || 'Element',
|
||||
};
|
||||
|
||||
// launcher
|
||||
launcher = new AutoLaunch({
|
||||
name: vectorConfig.brand || 'Riot',
|
||||
name: vectorConfig.brand || 'Element',
|
||||
isHidden: true,
|
||||
mac: {
|
||||
useLaunchAgent: true,
|
||||
@@ -186,6 +227,25 @@ async function setupGlobals() {
|
||||
});
|
||||
}
|
||||
|
||||
async function moveAutoLauncher() {
|
||||
// Look for an auto-launcher under 'Riot' and if we find one, port it's
|
||||
// enabled/disbaledp-ness over to the new 'Element' launcher
|
||||
if (!vectorConfig.brand || vectorConfig.brand === 'Element') {
|
||||
const oldLauncher = new AutoLaunch({
|
||||
name: 'Riot',
|
||||
isHidden: true,
|
||||
mac: {
|
||||
useLaunchAgent: true,
|
||||
},
|
||||
});
|
||||
const wasEnabled = await oldLauncher.isEnabled();
|
||||
if (wasEnabled) {
|
||||
await oldLauncher.disable();
|
||||
await launcher.enable();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const eventStorePath = path.join(app.getPath('userData'), 'EventStore');
|
||||
const store = new Store({ name: "electron-config" });
|
||||
|
||||
@@ -194,6 +254,14 @@ let eventIndex = null;
|
||||
let mainWindow = null;
|
||||
global.appQuitting = false;
|
||||
|
||||
|
||||
const deleteContents = async (p) => {
|
||||
for (const entry of await afs.readdir(p)) {
|
||||
const curPath = path.join(p, entry);
|
||||
await afs.unlink(curPath);
|
||||
}
|
||||
};
|
||||
|
||||
// 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
|
||||
@@ -241,17 +309,6 @@ ipcMain.on('app_onAction', function(ev, payload) {
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
|
||||
@@ -365,6 +422,49 @@ ipcMain.on('ipcCall', async function(ev, payload) {
|
||||
recordSSOSession(args[0]);
|
||||
break;
|
||||
|
||||
case 'getPickleKey':
|
||||
try {
|
||||
ret = await keytar.getPassword("element.io", `${args[0]}|${args[1]}`);
|
||||
// migrate from riot.im (remove once we think there will no longer be
|
||||
// logins from the time of riot.im)
|
||||
if (ret === null) {
|
||||
ret = await keytar.getPassword("riot.im", `${args[0]}|${args[1]}`);
|
||||
}
|
||||
} catch (e) {
|
||||
// if an error is thrown (e.g. keytar can't connect to the keychain),
|
||||
// then return null, which means the default pickle key will be used
|
||||
ret = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'createPickleKey':
|
||||
try {
|
||||
const randomArray = await new Promise((resolve, reject) => {
|
||||
crypto.randomBytes(32, (err, buf) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(buf);
|
||||
}
|
||||
});
|
||||
});
|
||||
const pickleKey = randomArray.toString("base64").replace(/=+$/g, '');
|
||||
await keytar.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
|
||||
ret = pickleKey;
|
||||
} catch (e) {
|
||||
ret = null;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'destroyPickleKey':
|
||||
try {
|
||||
await keytar.deletePassword("element.io", `${args[0]}|${args[1]}`);
|
||||
// migrate from riot.im (remove once we think there will no longer be
|
||||
// logins from the time of riot.im)
|
||||
await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`);
|
||||
} catch (e) {}
|
||||
break;
|
||||
|
||||
default:
|
||||
mainWindow.webContents.send('ipcReply', {
|
||||
id: payload.id,
|
||||
@@ -416,7 +516,22 @@ ipcMain.on('seshat', async function(ev, payload) {
|
||||
const recoveryIndex = new SeshatRecovery(eventStorePath, {
|
||||
passphrase: seshatPassphrase,
|
||||
});
|
||||
await recoveryIndex.reindex();
|
||||
|
||||
const userVersion = await recoveryIndex.getUserVersion();
|
||||
|
||||
// If our user version is 0 we'll delete the db
|
||||
// anyways so reindexing it is a waste of time.
|
||||
if (userVersion === 0) {
|
||||
await recoveryIndex.shutdown();
|
||||
|
||||
try {
|
||||
await deleteContents(eventStorePath);
|
||||
} catch (e) {
|
||||
}
|
||||
} else {
|
||||
await recoveryIndex.reindex();
|
||||
}
|
||||
|
||||
eventIndex = new Seshat(eventStorePath, {
|
||||
passphrase: seshatPassphrase,
|
||||
});
|
||||
@@ -448,15 +563,8 @@ ipcMain.on('seshat', async function(ev, payload) {
|
||||
|
||||
case 'deleteEventIndex':
|
||||
{
|
||||
const deleteFolderRecursive = async (p) => {
|
||||
for (const entry of await afs.readdir(p)) {
|
||||
const curPath = path.join(p, entry);
|
||||
await afs.unlink(curPath);
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
await deleteFolderRecursive(eventStorePath);
|
||||
await deleteContents(eventStorePath);
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
@@ -468,6 +576,11 @@ ipcMain.on('seshat', async function(ev, payload) {
|
||||
else ret = await eventIndex.isEmpty();
|
||||
break;
|
||||
|
||||
case 'isRoomIndexed':
|
||||
if (eventIndex === null) ret = false;
|
||||
else ret = await eventIndex.isRoomIndexed(args[0]);
|
||||
break;
|
||||
|
||||
case 'addEventToIndex':
|
||||
try {
|
||||
eventIndex.addEvent(args[0], args[1]);
|
||||
@@ -576,6 +689,30 @@ ipcMain.on('seshat', async function(ev, payload) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 'setUserVersion':
|
||||
if (eventIndex === null) break;
|
||||
else {
|
||||
try {
|
||||
await eventIndex.setUserVersion(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'getUserVersion':
|
||||
if (eventIndex === null) ret = 0;
|
||||
else {
|
||||
try {
|
||||
ret = await eventIndex.getUserVersion();
|
||||
} catch (e) {
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
mainWindow.webContents.send('seshatReply', {
|
||||
id: payload.id,
|
||||
@@ -629,6 +766,7 @@ app.enableSandbox();
|
||||
app.on('ready', async () => {
|
||||
try {
|
||||
await setupGlobals();
|
||||
await moveAutoLauncher();
|
||||
} catch (e) {
|
||||
console.log("App setup failed: exiting", e);
|
||||
process.exit(1);
|
||||
@@ -827,4 +965,4 @@ app.on('second-instance', (ev, commandLine, workingDirectory) => {
|
||||
// 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');
|
||||
app.setAppUserModelId('com.squirrel.element-desktop.Element');
|
||||
|
||||
@@ -18,8 +18,8 @@ const {app} = require("electron");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
|
||||
const PROTOCOL = "riot://";
|
||||
const SEARCH_PARAM = "riot-desktop-ssoid";
|
||||
const PROTOCOL = "element://";
|
||||
const SEARCH_PARAM = "element-desktop-ssoid";
|
||||
const STORE_FILE_NAME = "sso-sessions.json";
|
||||
|
||||
// we getPath userData before electron-main changes it, so this is the default value
|
||||
@@ -61,10 +61,10 @@ module.exports = {
|
||||
},
|
||||
getProfileFromDeeplink: (args) => {
|
||||
// check if we are passed a profile in the SSO callback url
|
||||
const deeplinkUrl = args.find(arg => arg.startsWith('riot://'));
|
||||
const deeplinkUrl = args.find(arg => arg.startsWith('element://'));
|
||||
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
|
||||
const parsedUrl = new URL(deeplinkUrl);
|
||||
if (parsedUrl.protocol === 'riot:') {
|
||||
if (parsedUrl.protocol === 'element:') {
|
||||
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM);
|
||||
const store = readStore();
|
||||
console.log("Forwarding to profile: ", store[ssoID]);
|
||||
@@ -78,10 +78,10 @@ module.exports = {
|
||||
// --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);
|
||||
app.setAsDefaultProtocolClient('element', 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]);
|
||||
app.setAsDefaultProtocolClient('element', process.execPath, [app.getAppPath(), ...args]);
|
||||
}
|
||||
|
||||
if (process.platform === 'darwin') {
|
||||
|
||||
@@ -17,17 +17,20 @@ limitations under the License.
|
||||
const path = require('path');
|
||||
const spawn = require('child_process').spawn;
|
||||
const {app} = require('electron');
|
||||
const fsProm = require('fs').promises;
|
||||
|
||||
function runUpdateExe(args, done) {
|
||||
function runUpdateExe(args) {
|
||||
// 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);
|
||||
return new Promise(resolve => {
|
||||
spawn(updateExe, args, {
|
||||
detached: true,
|
||||
}).on('close', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
function checkSquirrelHooks() {
|
||||
@@ -36,10 +39,42 @@ function checkSquirrelHooks() {
|
||||
const cmd = process.argv[1];
|
||||
const target = path.basename(process.execPath);
|
||||
if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
|
||||
runUpdateExe(['--createShortcut=' + target + ''], app.quit);
|
||||
Promise.resolve().then(() => {
|
||||
return runUpdateExe(['--createShortcut=' + target]);
|
||||
}).then(() => {
|
||||
// remove the old 'Riot' shortcuts, if they exist (update.exe --removeShortcut doesn't work
|
||||
// because it always uses the name of the product as the name of the shortcut: the only variable
|
||||
// is what executable you're linking to)
|
||||
const appDataDir = process.env.APPDATA;
|
||||
if (!appDataDir) return;
|
||||
const startMenuDir = path.join(
|
||||
appDataDir, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'New Vector Ltd',
|
||||
);
|
||||
return fsProm.rmdir(startMenuDir, { recursive: true });
|
||||
}).then(() => {
|
||||
// same for 'Element (Riot) which is old now too (we have to try to delete both because
|
||||
// we don't know what version we're updating from, but of course we do know this version
|
||||
// is 'Element' so the two old ones are all safe to delete).
|
||||
const appDataDir = process.env.APPDATA;
|
||||
if (!appDataDir) return;
|
||||
const oldStartMenuLink = path.join(
|
||||
appDataDir, 'Microsoft', 'Windows', 'Start Menu', 'Programs', 'Element', 'Element (Riot).lnk',
|
||||
);
|
||||
return fsProm.unlink(oldStartMenuLink).catch(() => {});
|
||||
}).then(() => {
|
||||
const oldDesktopShortcut = path.join(app.getPath('desktop'), 'Element (Riot).lnk');
|
||||
return fsProm.unlink(oldDesktopShortcut).catch(() => {});
|
||||
}).then(() => {
|
||||
const oldDesktopShortcut = path.join(app.getPath('desktop'), 'Riot.lnk');
|
||||
return fsProm.unlink(oldDesktopShortcut).catch(() => {});
|
||||
}).then(() => {
|
||||
app.quit();
|
||||
});
|
||||
return true;
|
||||
} else if (cmd === '--squirrel-uninstall') {
|
||||
runUpdateExe(['--removeShortcut=' + target + ''], app.quit);
|
||||
runUpdateExe(['--removeShortcut=' + target]).then(() => {
|
||||
app.quit();
|
||||
});
|
||||
return true;
|
||||
} else if (cmd === '--squirrel-obsolete') {
|
||||
app.quit();
|
||||
|
||||
@@ -88,7 +88,7 @@ exports.create = function(config) {
|
||||
// Windows likes ico's too much.
|
||||
if (process.platform === 'win32') {
|
||||
try {
|
||||
const icoPath = path.join(app.getPath('temp'), 'win32_riot_icon.ico');
|
||||
const icoPath = path.join(app.getPath('temp'), 'win32_element_icon.ico');
|
||||
fs.writeFileSync(icoPath, await pngToIco(newFavicon.toPNG()));
|
||||
newFavicon = nativeImage.createFromPath(icoPath);
|
||||
} catch (e) {
|
||||
|
||||
@@ -69,15 +69,31 @@ ipcMain.on('install_update', installUpdate);
|
||||
ipcMain.on('check_updates', pollForUpdates);
|
||||
|
||||
function ipcChannelSendUpdateStatus(status) {
|
||||
if (global.mainWindow) {
|
||||
global.mainWindow.webContents.send('check_updates', status);
|
||||
}
|
||||
if (!global.mainWindow) return;
|
||||
global.mainWindow.webContents.send('check_updates', status);
|
||||
}
|
||||
|
||||
// cache the latest update which has been downloaded as electron offers no api to read it
|
||||
let latestUpdateDownloaded;
|
||||
autoUpdater.on('update-available', function() {
|
||||
ipcChannelSendUpdateStatus(true);
|
||||
}).on('update-not-available', function() {
|
||||
ipcChannelSendUpdateStatus(false);
|
||||
if (latestUpdateDownloaded) {
|
||||
// the only time we will get `update-not-available` if `latestUpdateDownloaded` is already set
|
||||
// is if the user used the Manual Update check and there is no update newer than the one we
|
||||
// have downloaded, so show it to them as the latest again.
|
||||
if (!global.mainWindow) return;
|
||||
global.mainWindow.webContents.send('update-downloaded', latestUpdateDownloaded);
|
||||
} else {
|
||||
ipcChannelSendUpdateStatus(false);
|
||||
}
|
||||
}).on('error', function(error) {
|
||||
ipcChannelSendUpdateStatus(error.message);
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', (ev, releaseNotes, releaseName, releaseDate, updateURL) => {
|
||||
if (!global.mainWindow) return;
|
||||
// forward to renderer
|
||||
latestUpdateDownloaded = { releaseNotes, releaseName, releaseDate, updateURL };
|
||||
global.mainWindow.webContents.send('update-downloaded', latestUpdateDownloaded);
|
||||
});
|
||||
|
||||
@@ -62,8 +62,8 @@ const template = [
|
||||
role: 'help',
|
||||
submenu: [
|
||||
{
|
||||
label: 'Riot Help',
|
||||
click() { shell.openExternal('https://about.riot.im/help'); },
|
||||
label: 'Element Help',
|
||||
click() { shell.openExternal('https://element.io/help'); },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
const {clipboard, nativeImage, Menu, MenuItem, shell, dialog} = require('electron');
|
||||
const {clipboard, nativeImage, Menu, MenuItem, shell, dialog, ipcMain} = require('electron');
|
||||
const url = require('url');
|
||||
const fs = require('fs');
|
||||
const request = require('request');
|
||||
const path = require('path');
|
||||
|
||||
const MAILTO_PREFIX = "mailto:";
|
||||
|
||||
@@ -56,7 +57,7 @@ function onLinkContextMenu(ev, params) {
|
||||
// Avoid showing a context menu for app icons
|
||||
if (params.hasImageContents) return;
|
||||
// Rewrite URL so that it can be used outside of the app
|
||||
url = "https://riot.im/app/" + url.substring(23);
|
||||
url = "https://app.element.io/" + url.substring(23);
|
||||
}
|
||||
|
||||
const popupMenu = new Menu();
|
||||
@@ -205,6 +206,9 @@ function onEditableContextMenu(ev, params) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
ipcMain.on('userDownloadOpen', function(ev, {path}) {
|
||||
shell.openPath(path);
|
||||
});
|
||||
|
||||
module.exports = (webContents) => {
|
||||
webContents.on('new-window', onWindowOrNavigate);
|
||||
@@ -222,4 +226,16 @@ module.exports = (webContents) => {
|
||||
onEditableContextMenu(ev, params);
|
||||
}
|
||||
});
|
||||
|
||||
webContents.session.on('will-download', (event, item) => {
|
||||
item.once('done', (event, state) => {
|
||||
if (state === 'completed') {
|
||||
const savePath = item.getSavePath();
|
||||
webContents.send('userDownloadCompleted', {
|
||||
path: savePath,
|
||||
name: path.basename(savePath),
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||