mirror of
https://github.com/element-hq/element-desktop.git
synced 2026-01-04 13:39:09 -05:00
Compare commits
257 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d422df45c | ||
|
|
4b56c71f72 | ||
|
|
c37596e195 | ||
|
|
6cae9fb3a2 | ||
|
|
31b0bc1d06 | ||
|
|
281ecc0662 | ||
|
|
d8de60e17b | ||
|
|
cf6140ac40 | ||
|
|
b431898dcd | ||
|
|
153d0badf5 | ||
|
|
c6b25e86eb | ||
|
|
0a070ac6ed | ||
|
|
08f8f88508 | ||
|
|
6e8aa5e308 | ||
|
|
e1651f30b4 | ||
|
|
e7cccf6ad1 | ||
|
|
ce8d31f4ea | ||
|
|
07c11853f5 | ||
|
|
60e42e4cfa | ||
|
|
7fea56ed8b | ||
|
|
193487eb9e | ||
|
|
0f54e90250 | ||
|
|
467e6189f7 | ||
|
|
5c527e3bc9 | ||
|
|
f0107d64a9 | ||
|
|
fb8fff7799 | ||
|
|
031043f2d8 | ||
|
|
926ecec65f | ||
|
|
fb5490e8e8 | ||
|
|
65a446db75 | ||
|
|
ca91532635 | ||
|
|
8f71628533 | ||
|
|
9359c38939 | ||
|
|
634c5c66a6 | ||
|
|
a80bc76e22 | ||
|
|
230657b1db | ||
|
|
da6b3b02f2 | ||
|
|
e2b9922d44 | ||
|
|
3421979db4 | ||
|
|
47f59a4840 | ||
|
|
e3f3814a25 | ||
|
|
ec4057f7e5 | ||
|
|
275e228387 | ||
|
|
61ed2a21c6 | ||
|
|
8fd24d2fa2 | ||
|
|
bfb96a33ba | ||
|
|
0d37d8d8e9 | ||
|
|
f4ee34cc56 | ||
|
|
379a9e9969 | ||
|
|
4b6983747e | ||
|
|
8027988239 | ||
|
|
025a8808b8 | ||
|
|
528a93a3a9 | ||
|
|
5b3301bb0e | ||
|
|
747b596e8b | ||
|
|
9aaeab2221 | ||
|
|
87c5232ba5 | ||
|
|
771483d324 | ||
|
|
90359643ba | ||
|
|
ccade5eccf | ||
|
|
79b0f14984 | ||
|
|
989e030d97 | ||
|
|
531dde8bff | ||
|
|
99ce48be8c | ||
|
|
f18be113c3 | ||
|
|
8b25178aed | ||
|
|
eef3dfc724 | ||
|
|
37d7559d86 | ||
|
|
326e6577e1 | ||
|
|
18500e7ec3 | ||
|
|
1cd299b98e | ||
|
|
3c8650065c | ||
|
|
e2bdedfec1 | ||
|
|
aa6e4d5ce2 | ||
|
|
846a8df9a6 | ||
|
|
eb8429ae9d | ||
|
|
89b1e39b80 | ||
|
|
b9880e2463 | ||
|
|
7f292b12ea | ||
|
|
3599a015d7 | ||
|
|
0681fa81a4 | ||
|
|
b79645adb4 | ||
|
|
f52b10a63a | ||
|
|
e100388495 | ||
|
|
aacb8cb349 | ||
|
|
20d9e2b14b | ||
|
|
9b96700daf | ||
|
|
ffd6cf5ad7 | ||
|
|
4a44ad0a8f | ||
|
|
548f22d438 | ||
|
|
145485326a | ||
|
|
8dd564a7dc | ||
|
|
12809ff4fd | ||
|
|
26e02eff94 | ||
|
|
4b23aaa31e | ||
|
|
fc86ad3db0 | ||
|
|
0af82dbbbd | ||
|
|
0c3736f3af | ||
|
|
7af662cd38 | ||
|
|
4bc4eb74e2 | ||
|
|
c68dcab7c6 | ||
|
|
f53e12624e | ||
|
|
5cefdb028d | ||
|
|
48b01f7070 | ||
|
|
1122c41cc1 | ||
|
|
54d13516b7 | ||
|
|
b662846bf1 | ||
|
|
f5ee82a8ca | ||
|
|
c1bc40d9f8 | ||
|
|
62cb1a36c0 | ||
|
|
859889c3f3 | ||
|
|
69c946132d | ||
|
|
74a3e4fd8b | ||
|
|
048b7932bd | ||
|
|
2fbb9ca630 | ||
|
|
67f6c60e52 | ||
|
|
452ab97314 | ||
|
|
f48c5e7de4 | ||
|
|
eaa515de07 | ||
|
|
b498885b2d | ||
|
|
db86a3f726 | ||
|
|
6b35146f84 | ||
|
|
1659ce7624 | ||
|
|
4e29b24f1e | ||
|
|
4fe261b3d0 | ||
|
|
bf8a648fd4 | ||
|
|
58d56f0068 | ||
|
|
0e5e92015c | ||
|
|
6a4c1afe27 | ||
|
|
bd7e74545a | ||
|
|
c16c473dbf | ||
|
|
96e5389779 | ||
|
|
798a042481 | ||
|
|
fdf99f3d53 | ||
|
|
fd16f79a23 | ||
|
|
2b5208f4e6 | ||
|
|
a6b038e207 | ||
|
|
2b4a8a6ca9 | ||
|
|
87ac970ee5 | ||
|
|
010ad9825f | ||
|
|
31245c7c3a | ||
|
|
f498c7de30 | ||
|
|
58611e41d3 | ||
|
|
31a43aeb24 | ||
|
|
836a99745c | ||
|
|
093dde799d | ||
|
|
df6fb175b3 | ||
|
|
de6570c58e | ||
|
|
c9eb2379ef | ||
|
|
bc75eac336 | ||
|
|
4117f3f858 | ||
|
|
96203a882c | ||
|
|
2b6d064fb5 | ||
|
|
7a03dd2b0c | ||
|
|
03862cda8b | ||
|
|
6fd0c7c87e | ||
|
|
0dac5a3384 | ||
|
|
bdfc6ac35c | ||
|
|
71c46e7365 | ||
|
|
ea30e1ab96 | ||
|
|
9fde6791e5 | ||
|
|
13db0f5ea1 | ||
|
|
24a27bbd17 | ||
|
|
8146de344b | ||
|
|
30634ffedd | ||
|
|
3e1a9e8db4 | ||
|
|
ec8a406348 | ||
|
|
53d25e14e7 | ||
|
|
240c07c65d | ||
|
|
019f4fa22e | ||
|
|
45c5a4acb5 | ||
|
|
af8a686fac | ||
|
|
18a9b07218 | ||
|
|
f26ca3d61d | ||
|
|
7e59fa6e21 | ||
|
|
3a8bde850a | ||
|
|
609677d9c1 | ||
|
|
d24ae7b4c1 | ||
|
|
368cdd4d20 | ||
|
|
2631ceecb8 | ||
|
|
9133260b61 | ||
|
|
e4afc40887 | ||
|
|
bedc4be8bd | ||
|
|
1ac971112f | ||
|
|
00bbd043d6 | ||
|
|
a978ca52ec | ||
|
|
b1085f7a8c | ||
|
|
986f728019 | ||
|
|
254ac4e0b8 | ||
|
|
394e3cde3a | ||
|
|
b725ac99de | ||
|
|
63cefd4540 | ||
|
|
bf5d3f0dc6 | ||
|
|
d8f14a4644 | ||
|
|
f8f6a3c36d | ||
|
|
cce5816da5 | ||
|
|
291205170b | ||
|
|
f174abb8b0 | ||
|
|
ab6b21d47b | ||
|
|
f1dd3d95ea | ||
|
|
bdae96d939 | ||
|
|
4ceb91b3ae | ||
|
|
dbac457d14 | ||
|
|
511867e5f0 | ||
|
|
731e5718e1 | ||
|
|
0c823f5c2d | ||
|
|
937f1c4b40 | ||
|
|
984a98b9df | ||
|
|
905223517e | ||
|
|
15600584ec | ||
|
|
2be7b56a2b | ||
|
|
39c56e6d6a | ||
|
|
c7dea97893 | ||
|
|
928d8c5d56 | ||
|
|
a76d7796a8 | ||
|
|
6aef1fc203 | ||
|
|
3fb802e563 | ||
|
|
1a38ca6fa7 | ||
|
|
3e69d1ec63 | ||
|
|
0bdb69372f | ||
|
|
0ac9454e3a | ||
|
|
63065761ed | ||
|
|
71134c448d | ||
|
|
290907a427 | ||
|
|
bfcb1e6bfb | ||
|
|
494200d576 | ||
|
|
28cbc01d61 | ||
|
|
ba0dd9e2a6 | ||
|
|
45eb1252b6 | ||
|
|
b9e2fbbd23 | ||
|
|
5febbeb681 | ||
|
|
768066e764 | ||
|
|
e436b87e80 | ||
|
|
d5c395f509 | ||
|
|
7107f45cee | ||
|
|
bd85f19c15 | ||
|
|
e2697cd8b4 | ||
|
|
15ca3a3145 | ||
|
|
e2829822a3 | ||
|
|
fac9f53bb6 | ||
|
|
3c324ad5f7 | ||
|
|
d82377e2de | ||
|
|
79a426b1c0 | ||
|
|
00a91489a8 | ||
|
|
b315b71e43 | ||
|
|
e132e1c610 | ||
|
|
8592840143 | ||
|
|
a8f44fd6e9 | ||
|
|
a22ba39e63 | ||
|
|
3dd611b5d5 | ||
|
|
eed1252f33 | ||
|
|
9913b0ff78 | ||
|
|
e07bfc1d6a | ||
|
|
b5725da9ea | ||
|
|
5bbce91e51 | ||
|
|
0aed8eac36 | ||
|
|
b6cd3c4cee |
@@ -19,7 +19,7 @@ module.exports = {
|
||||
"no-async-promise-executor": "off",
|
||||
},
|
||||
overrides: [{
|
||||
files: ["src/**/*.{ts,tsx}"],
|
||||
files: ["{src,scripts,hak}/**/*.{ts,tsx}"],
|
||||
extends: [
|
||||
"plugin:matrix-org/typescript",
|
||||
],
|
||||
|
||||
1
.github/CODEOWNERS
vendored
Normal file
1
.github/CODEOWNERS
vendored
Normal file
@@ -0,0 +1 @@
|
||||
* @vector-im/element-web
|
||||
12
.github/workflows/preview_changelog.yaml
vendored
Normal file
12
.github/workflows/preview_changelog.yaml
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
name: Preview Changelog
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [ opened, edited, labeled ]
|
||||
jobs:
|
||||
changelog:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Preview Changelog
|
||||
uses: matrix-org/allchange@main
|
||||
with:
|
||||
ghToken: ${{ secrets.GITHUB_TOKEN }}
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,3 +11,5 @@
|
||||
/.yarnrc
|
||||
/docker
|
||||
/.npmrc
|
||||
.vscode
|
||||
.vscode/
|
||||
|
||||
1148
CHANGELOG.md
1148
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
38
README.md
38
README.md
@@ -20,7 +20,7 @@ so the first step is to get a working copy of Element Web. There are a few ways
|
||||
# Fetch the prebuilt release Element package from the element-web 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 ''
|
||||
yarn run fetch --noverify --cfgdir ""
|
||||
```
|
||||
|
||||
...or if you'd like to use GPG to verify the downloaded package:
|
||||
@@ -30,14 +30,14 @@ yarn run fetch --noverify --cfgdir ''
|
||||
# once.
|
||||
yarn run fetch --importkey
|
||||
# Fetch the package and verify the signature
|
||||
yarn run fetch --cfgdir ''
|
||||
yarn run fetch --cfgdir ""
|
||||
```
|
||||
|
||||
...or either of the above, but fetching a specific version of Element:
|
||||
```
|
||||
# Fetch the prebuilt release Element package from the element-web GitHub releases page. The version
|
||||
# fetched will be the same as the local element-desktop package.
|
||||
yarn run fetch --noverify --cfgdir '' v1.5.6
|
||||
yarn run fetch --noverify --cfgdir "" v1.5.6
|
||||
```
|
||||
|
||||
If you only want to run the app locally and don't need to build packages, you can
|
||||
@@ -49,26 +49,17 @@ ln -s ../element-web/webapp ./
|
||||
|
||||
[TODO: add support for fetching develop builds, arbitrary URLs and arbitrary paths]
|
||||
|
||||
|
||||
Building
|
||||
========
|
||||
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.
|
||||
|
||||
If you'd like to build the native modules (for searching in encrypted rooms and
|
||||
secure storage), do this first. This will take 10 minutes or so, and will
|
||||
require a number of native tools to be installed, depending on your OS (eg.
|
||||
rust, tcl, make/nmake). If you don't need these features, you can skip this
|
||||
step.
|
||||
```
|
||||
yarn run build:native
|
||||
```
|
||||
## Native Build
|
||||
|
||||
On Windows, this will automatically determine the architecture to build for based
|
||||
on the environment. Make sure that you have all the [tools required to perform the native modules build](docs/windows-requirements.md)
|
||||
TODO: List native pre-requisites
|
||||
|
||||
Now you can build the package:
|
||||
Optionally, [build the native modules](https://github.com/vector-im/element-desktop/blob/develop/docs/native-node-modules.md),
|
||||
which include support for searching in encrypted rooms and secure storage. Skipping this step is fine, you just won't have those features.
|
||||
|
||||
Then, run
|
||||
```
|
||||
yarn run build
|
||||
```
|
||||
@@ -78,18 +69,9 @@ This will do a couple of things:
|
||||
* Run electron-builder to build a package. The package built will match the operating system
|
||||
you're running the build process on.
|
||||
|
||||
If you're on Windows, you can choose to build specifically for 32 or 64 bit:
|
||||
```
|
||||
yarn run build32
|
||||
```
|
||||
or
|
||||
```
|
||||
yarn run build64
|
||||
```
|
||||
## Docker
|
||||
|
||||
This build step will not build any native modules.
|
||||
|
||||
You can also build using docker, which will always produce the linux package:
|
||||
Alternatively, you can also build using docker, which will always produce the linux package:
|
||||
```
|
||||
# Run this once to make the docker image
|
||||
yarn run docker:setup
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM buildpack-deps:xenial-curl
|
||||
FROM buildpack-deps:bionic-curl
|
||||
|
||||
ENV DEBIAN_FRONTEND noninteractive
|
||||
|
||||
@@ -10,7 +10,7 @@ RUN apt-get -qq update && apt-get -qq dist-upgrade && \
|
||||
# python for node-gyp
|
||||
# rpm is required for FPM to build rpm package
|
||||
# libsecret-1-dev and libgnome-keyring-dev are required even for prebuild keytar
|
||||
apt-get -qq install --no-install-recommends qtbase5-dev bsdtar build-essential autoconf libssl-dev gcc-multilib g++-multilib lzip rpm python libcurl3 git git-lfs ssh unzip \
|
||||
apt-get -qq install --no-install-recommends qtbase5-dev bsdtar build-essential autoconf libssl-dev gcc-multilib g++-multilib lzip rpm python libcurl4 git git-lfs ssh unzip \
|
||||
libsecret-1-dev libgnome-keyring-dev \
|
||||
libopenjp2-tools \
|
||||
# Used by Seshat
|
||||
|
||||
@@ -10,20 +10,26 @@ modules from source to ensure we can trust the compiled output. In the future,
|
||||
we may offer a pre-compiled path for those who want to use these features in a
|
||||
custom build of Element without installing the various build tools required.
|
||||
|
||||
Do note that compiling a module for a particular operating system
|
||||
(Linux/macOS/Windows) will need to be done on that operating system.
|
||||
Cross-compiling from a host OS for a different target OS may be possible, but
|
||||
we don't support this flow with Element dependencies at this time.
|
||||
|
||||
The process is automated by [vector-im/element-builder](https://github.com/vector-im/element-builder)
|
||||
when releasing.
|
||||
The following sections explain the manual steps you can use with a custom build of Element to enable
|
||||
these features if you'd like to try them out.
|
||||
It is possible to [build those native modules locally automatically](https://github.com/vector-im/element-desktop#building).
|
||||
when releasing.
|
||||
|
||||
## Building
|
||||
|
||||
Install the pre-requisites for your system:
|
||||
|
||||
* [Windows pre-requisites](https://github.com/vector-im/element-desktop/blob/develop/docs/windows-requirements.md)
|
||||
* Linux: TODO
|
||||
* OS X: TODO
|
||||
|
||||
Then optionally, [add seshat and dependencies to support search in E2E rooms](#adding-seshat-for-search-in-e2e-encrypted-rooms).
|
||||
|
||||
Then, to build for an architecture selected automatically based on your system (recommended), run:
|
||||
```
|
||||
yarn run build:native
|
||||
```
|
||||
|
||||
If you need to build for a specific architecture, see [here](#compiling-for-specific-architectures).
|
||||
|
||||
## Adding Seshat for search in E2E encrypted rooms
|
||||
|
||||
Seshat is a native Node module that adds support for local event indexing and
|
||||
@@ -59,3 +65,74 @@ After this is done the Electron version of Element can be run from the main fold
|
||||
as usual using:
|
||||
|
||||
yarn start
|
||||
|
||||
## Compiling for specific architectures
|
||||
|
||||
### macOS
|
||||
|
||||
On macOS, you can build universal native modules too:
|
||||
```
|
||||
yarn run build:native:universal
|
||||
```
|
||||
|
||||
...or you can build for a specific architecture:
|
||||
```
|
||||
yarn run build:native --target x86_64-apple-darwin
|
||||
```
|
||||
or
|
||||
```
|
||||
yarn run build:native --target aarch64-apple-darwin
|
||||
```
|
||||
|
||||
You'll then need to create a built bundle with the same architecture.
|
||||
To bundle a universal build for macOS, run:
|
||||
|
||||
```
|
||||
yarn run build:universal
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
If you're on Windows, you can choose to build specifically for 32 or 64 bit:
|
||||
```
|
||||
yarn run build:32
|
||||
```
|
||||
or
|
||||
```
|
||||
yarn run build:64
|
||||
```
|
||||
|
||||
### Cross compiling
|
||||
|
||||
Compiling a module for a particular operating system (Linux/macOS/Windows) needs
|
||||
to be done on that operating system. Cross-compiling from a host OS for a different
|
||||
target OS may be possible, but we don't support this flow with Element dependencies
|
||||
at this time.
|
||||
|
||||
### Switching between architectures
|
||||
|
||||
The native module build system keeps the different architectures
|
||||
separate, so you can keep native modules for several architectures at the same
|
||||
time and switch which are active using a `yarn run hak copy` command, passing
|
||||
the appropriate architectures. This will error if you haven't yet built those
|
||||
architectures. eg:
|
||||
|
||||
```
|
||||
yarn run build:native --target x86_64-apple-darwin
|
||||
# We've now built & linked into place native modules for Intel
|
||||
yarn run build:native --target aarch64-apple-darwin
|
||||
# We've now built Apple Silicon modules too, and linked them into place as the active ones
|
||||
|
||||
yarn run hak copy --target x86_64-apple-darwin
|
||||
# We've now switched back to our Intel modules
|
||||
yarn run hak copy --target x86_64-apple-darwin --target aarch64-apple-darwin
|
||||
# Now our native modules are universal x86_64+aarch64 binaries
|
||||
```
|
||||
|
||||
The current set of native modules are stored in `.hak/hakModules`,
|
||||
so you can use this to check what architecture is currently in place, eg:
|
||||
|
||||
```
|
||||
$ lipo -info .hak/hakModules/keytar/build/Release/keytar.node
|
||||
Architectures in the fat file: .hak/hakModules/keytar/build/Release/keytar.node are: x86_64 arm64
|
||||
```
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"update_base_url": "https://packages.riot.im/nightly/update/",
|
||||
"update_base_url": "https://packages.element.io/nightly/update/",
|
||||
"default_server_name": "matrix.org",
|
||||
"brand": "Element Nightly",
|
||||
"integrations_ui_url": "https://scalar.vector.im/",
|
||||
@@ -13,6 +13,7 @@
|
||||
],
|
||||
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
|
||||
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||
"uisi_autorageshake_app": "element-auto-uisi",
|
||||
"showLabsSettings": true,
|
||||
"piwik": {
|
||||
"url": "https://piwik.riot.im/",
|
||||
@@ -39,5 +40,17 @@
|
||||
"url": "https://element.io/cookie-policy",
|
||||
"text": "Cookie Policy"
|
||||
}
|
||||
]
|
||||
],
|
||||
"sentry": {
|
||||
"dsn": "https://029a0eb289f942508ae0fb17935bd8c5@sentry.matrix.org/6",
|
||||
"environment": "nightly"
|
||||
},
|
||||
"posthog": {
|
||||
"projectApiKey": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
|
||||
"apiHost": "https://posthog.element.io"
|
||||
},
|
||||
"features": {
|
||||
"feature_spotlight": true
|
||||
},
|
||||
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"update_base_url": "https://packages.riot.im/desktop/update/",
|
||||
"update_base_url": "https://packages.element.io/desktop/update/",
|
||||
"default_server_name": "matrix.org",
|
||||
"brand": "Element",
|
||||
"integrations_ui_url": "https://scalar.vector.im/",
|
||||
@@ -13,6 +13,7 @@
|
||||
],
|
||||
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
|
||||
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
|
||||
"uisi_autorageshake_app": "element-auto-uisi",
|
||||
"roomDirectory": {
|
||||
"servers": [
|
||||
"matrix.org",
|
||||
@@ -39,5 +40,10 @@
|
||||
"url": "https://element.io/cookie-policy",
|
||||
"text": "Cookie Policy"
|
||||
}
|
||||
]
|
||||
],
|
||||
"posthog": {
|
||||
"projectApiKey": "phc_Jzsm6DTm6V2705zeU5dcNvQDlonOR68XvX2sh1sEOHO",
|
||||
"apiHost": "https://posthog.element.io"
|
||||
},
|
||||
"map_style_url": "https://api.maptiler.com/maps/streets/style.json?key=fU3vlMsMn4Jb6dnEIFsx"
|
||||
}
|
||||
|
||||
@@ -14,18 +14,17 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const childProcess = require('child_process');
|
||||
import path from 'path';
|
||||
import childProcess from 'child_process';
|
||||
|
||||
module.exports = async function(hakEnv, moduleInfo) {
|
||||
await buildKeytar(hakEnv, moduleInfo);
|
||||
};
|
||||
import HakEnv from '../../scripts/hak/hakEnv';
|
||||
import { DependencyInfo } from '../../scripts/hak/dep';
|
||||
|
||||
async function buildKeytar(hakEnv, moduleInfo) {
|
||||
export default async function buildKeytar(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
const env = hakEnv.makeGypEnv();
|
||||
|
||||
console.log("Running yarn with env", env);
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
path.join(moduleInfo.nodeModuleBinDir, 'node-gyp' + (hakEnv.isWin() ? '.cmd' : '')),
|
||||
['rebuild'],
|
||||
@@ -14,13 +14,16 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const childProcess = require('child_process');
|
||||
import childProcess from 'child_process';
|
||||
|
||||
module.exports = async function(hakEnv, moduleInfo) {
|
||||
import HakEnv from '../../scripts/hak/hakEnv';
|
||||
import { DependencyInfo } from '../../scripts/hak/dep';
|
||||
|
||||
export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
const tools = [['python', '--version']]; // node-gyp uses python for reasons beyond comprehension
|
||||
|
||||
for (const tool of tools) {
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(tool[0], tool.slice(1), {
|
||||
stdio: ['ignore'],
|
||||
});
|
||||
@@ -33,4 +36,4 @@ module.exports = async function(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"scripts": {
|
||||
"check": "check.js",
|
||||
"build": "build.js"
|
||||
"check": "check.ts",
|
||||
"build": "build.ts"
|
||||
},
|
||||
"copy": "build/Release/keytar.node",
|
||||
"dependencies": {
|
||||
|
||||
@@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const childProcess = require('child_process');
|
||||
import path from 'path';
|
||||
import childProcess from 'child_process';
|
||||
import mkdirp from 'mkdirp';
|
||||
import fsExtra from 'fs-extra';
|
||||
|
||||
const mkdirp = require('mkdirp');
|
||||
const fsExtra = require('fs-extra');
|
||||
import HakEnv from '../../scripts/hak/hakEnv';
|
||||
import { DependencyInfo } from '../../scripts/hak/dep';
|
||||
|
||||
module.exports = async function(hakEnv, moduleInfo) {
|
||||
export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
if (hakEnv.isWin()) {
|
||||
await buildOpenSslWin(hakEnv, moduleInfo);
|
||||
await buildSqlCipherWin(hakEnv, moduleInfo);
|
||||
@@ -28,24 +30,24 @@ module.exports = async function(hakEnv, moduleInfo) {
|
||||
await buildSqlCipherUnix(hakEnv, moduleInfo);
|
||||
}
|
||||
await buildMatrixSeshat(hakEnv, moduleInfo);
|
||||
};
|
||||
}
|
||||
|
||||
async function buildOpenSslWin(hakEnv, moduleInfo) {
|
||||
const version = moduleInfo.cfg.dependencies.openssl;
|
||||
const openSslDir = path.join(moduleInfo.moduleDotHakDir, `openssl-${version}`);
|
||||
const openSslDir = path.join(moduleInfo.moduleTargetDotHakDir, `openssl-${version}`);
|
||||
|
||||
const openSslArch = hakEnv.getTargetArch() === 'x64' ? 'VC-WIN64A' : 'VC-WIN32';
|
||||
|
||||
console.log("Building openssl in " + openSslDir);
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
'perl',
|
||||
[
|
||||
'Configure',
|
||||
'--prefix=' + moduleInfo.depPrefix,
|
||||
// sqlcipher only uses about a tiny part of openssl. We link statically
|
||||
// so will only pull in the symbols we use, but we may as well turn off
|
||||
// as much as possible to save on build time.
|
||||
// sqlcipher only uses about a tiny part of openssl. We link statically
|
||||
// so will only pull in the symbols we use, but we may as well turn off
|
||||
// as much as possible to save on build time.
|
||||
'no-afalgeng',
|
||||
'no-capieng',
|
||||
'no-cms',
|
||||
@@ -103,7 +105,7 @@ async function buildOpenSslWin(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
'nmake',
|
||||
['build_libs'],
|
||||
@@ -117,7 +119,7 @@ async function buildOpenSslWin(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
'nmake',
|
||||
['install_dev'],
|
||||
@@ -134,12 +136,12 @@ async function buildOpenSslWin(hakEnv, moduleInfo) {
|
||||
|
||||
async function buildSqlCipherWin(hakEnv, moduleInfo) {
|
||||
const version = moduleInfo.cfg.dependencies.sqlcipher;
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleDotHakDir, `sqlcipher-${version}`);
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`);
|
||||
const buildDir = path.join(sqlCipherDir, 'bld');
|
||||
|
||||
await mkdirp(buildDir);
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
'nmake',
|
||||
['/f', path.join('..', 'Makefile.msc'), 'libsqlite3.lib', 'TOP=..'],
|
||||
@@ -171,7 +173,7 @@ async function buildSqlCipherWin(hakEnv, moduleInfo) {
|
||||
|
||||
async function buildSqlCipherUnix(hakEnv, moduleInfo) {
|
||||
const version = moduleInfo.cfg.dependencies.sqlcipher;
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleDotHakDir, `sqlcipher-${version}`);
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`);
|
||||
|
||||
const args = [
|
||||
'--prefix=' + moduleInfo.depPrefix + '',
|
||||
@@ -214,7 +216,7 @@ async function buildSqlCipherUnix(hakEnv, moduleInfo) {
|
||||
args.push(`LDFLAGS=${ldflags.join(' ')}`);
|
||||
}
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
path.join(sqlCipherDir, 'configure'),
|
||||
args,
|
||||
@@ -228,7 +230,7 @@ async function buildSqlCipherUnix(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
'make',
|
||||
[],
|
||||
@@ -242,7 +244,7 @@ async function buildSqlCipherUnix(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
'make',
|
||||
['install'],
|
||||
@@ -258,6 +260,9 @@ async function buildSqlCipherUnix(hakEnv, moduleInfo) {
|
||||
}
|
||||
|
||||
async function buildMatrixSeshat(hakEnv, moduleInfo) {
|
||||
// seshat now uses n-api so we shouldn't need to specify a node version to
|
||||
// build against, but it does seems to still need something in here, so leaving
|
||||
// it for now: we should confirm how much of this it still actually needs.
|
||||
const env = hakEnv.makeGypEnv();
|
||||
|
||||
if (!hakEnv.isLinux()) {
|
||||
@@ -283,7 +288,7 @@ async function buildMatrixSeshat(hakEnv, moduleInfo) {
|
||||
}
|
||||
|
||||
console.log("Running neon with env", env);
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
path.join(moduleInfo.nodeModuleBinDir, 'neon' + (hakEnv.isWin() ? '.cmd' : '')),
|
||||
['build', '--release'],
|
||||
@@ -14,12 +14,16 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const childProcess = require('child_process');
|
||||
import childProcess from 'child_process';
|
||||
import fsProm from 'fs/promises';
|
||||
|
||||
module.exports = async function(hakEnv, moduleInfo) {
|
||||
import HakEnv from '../../scripts/hak/hakEnv';
|
||||
import { DependencyInfo } from '../../scripts/hak/dep';
|
||||
|
||||
export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
// of course tcl doesn't have a --version
|
||||
if (!hakEnv.isLinux()) {
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn('tclsh', [], {
|
||||
stdio: ['pipe', 'ignore', 'ignore'],
|
||||
});
|
||||
@@ -47,7 +51,7 @@ module.exports = async function(hakEnv, moduleInfo) {
|
||||
}
|
||||
|
||||
for (const tool of tools) {
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(tool[0], tool.slice(1), {
|
||||
stdio: ['ignore'],
|
||||
});
|
||||
@@ -61,17 +65,21 @@ module.exports = async function(hakEnv, moduleInfo) {
|
||||
});
|
||||
}
|
||||
|
||||
// Ensure Rust target exists
|
||||
// Ensure Rust target exists (nb. we avoid depending on rustup)
|
||||
await new Promise((resolve, reject) => {
|
||||
childProcess.execFile('rustup', ['target', 'list', '--installed'], (err, out) => {
|
||||
const rustc = childProcess.execFile('rustc', [
|
||||
'--target', hakEnv.getTargetId(), '-o', 'tmp', '-',
|
||||
], (err, out) => {
|
||||
if (err) {
|
||||
reject("Can't find rustup");
|
||||
reject(
|
||||
"rustc can't build for target " + hakEnv.getTargetId() +
|
||||
": ensure target is installed via `rustup target add " + hakEnv.getTargetId() + "` " +
|
||||
"or your package manager if not using `rustup`",
|
||||
);
|
||||
}
|
||||
const target = hakEnv.getTargetId();
|
||||
if (!out.includes(target)) {
|
||||
reject(`Rust target ${target} not installed`);
|
||||
}
|
||||
resolve();
|
||||
fsProm.unlink('tmp').then(resolve);
|
||||
});
|
||||
rustc.stdin.write('fn main() {}');
|
||||
rustc.stdin.end();
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -14,15 +14,17 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const childProcess = require('child_process');
|
||||
import path from 'path';
|
||||
import childProcess from 'child_process';
|
||||
import fs from 'fs';
|
||||
import fsProm from 'fs/promises';
|
||||
import needle from 'needle';
|
||||
import tar from 'tar';
|
||||
|
||||
const fs = require('fs');
|
||||
const fsProm = require('fs').promises;
|
||||
const needle = require('needle');
|
||||
const tar = require('tar');
|
||||
import HakEnv from '../../scripts/hak/hakEnv';
|
||||
import { DependencyInfo } from '../../scripts/hak/dep';
|
||||
|
||||
module.exports = async function(hakEnv, moduleInfo) {
|
||||
export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
if (!hakEnv.isLinux()) {
|
||||
await getSqlCipher(hakEnv, moduleInfo);
|
||||
}
|
||||
@@ -30,11 +32,11 @@ module.exports = async function(hakEnv, moduleInfo) {
|
||||
if (hakEnv.isWin()) {
|
||||
await getOpenSsl(hakEnv, moduleInfo);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
async function getSqlCipher(hakEnv, moduleInfo) {
|
||||
async function getSqlCipher(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
const version = moduleInfo.cfg.dependencies.sqlcipher;
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleDotHakDir, `sqlcipher-${version}`);
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`);
|
||||
|
||||
let haveSqlcipher;
|
||||
try {
|
||||
@@ -62,9 +64,10 @@ async function getSqlCipher(hakEnv, moduleInfo) {
|
||||
await bob;
|
||||
}
|
||||
|
||||
// Extract the tarball to per-target directories, then we avoid cross-contaiminating archs
|
||||
await tar.x({
|
||||
file: sqlCipherTarball,
|
||||
cwd: moduleInfo.moduleDotHakDir,
|
||||
cwd: moduleInfo.moduleTargetDotHakDir,
|
||||
});
|
||||
|
||||
if (hakEnv.isWin()) {
|
||||
@@ -73,8 +76,8 @@ async function getSqlCipher(hakEnv, moduleInfo) {
|
||||
// set it to 2 (default to memory).
|
||||
const patchFile = path.join(moduleInfo.moduleHakDir, `sqlcipher-${version}-win.patch`);
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
const readStream = fs.createReadStream(patchFile);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const readStream = fs.createReadStream(patchFile);
|
||||
|
||||
const proc = childProcess.spawn(
|
||||
'patch',
|
||||
@@ -92,9 +95,9 @@ async function getSqlCipher(hakEnv, moduleInfo) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getOpenSsl(hakEnv, moduleInfo) {
|
||||
async function getOpenSsl(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
const version = moduleInfo.cfg.dependencies.openssl;
|
||||
const openSslDir = path.join(moduleInfo.moduleDotHakDir, `openssl-${version}`);
|
||||
const openSslDir = path.join(moduleInfo.moduleTargetDotHakDir, `openssl-${version}`);
|
||||
|
||||
let haveOpenSsl;
|
||||
try {
|
||||
@@ -121,9 +124,9 @@ async function getOpenSsl(hakEnv, moduleInfo) {
|
||||
});
|
||||
}
|
||||
|
||||
console.log("extracting " + openSslTarball + " in " + moduleInfo.moduleDotHakDir);
|
||||
console.log("extracting " + openSslTarball + " in " + moduleInfo.moduleTargetDotHakDir);
|
||||
await tar.x({
|
||||
file: openSslTarball,
|
||||
cwd: moduleInfo.moduleDotHakDir,
|
||||
cwd: moduleInfo.moduleTargetDotHakDir,
|
||||
});
|
||||
}
|
||||
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"scripts": {
|
||||
"check": "check.js",
|
||||
"fetchDeps": "fetchDeps.js",
|
||||
"build": "build.js"
|
||||
"check": "check.ts",
|
||||
"fetchDeps": "fetchDeps.ts",
|
||||
"build": "build.ts"
|
||||
},
|
||||
"prune": "native",
|
||||
"copy": "native/index.node",
|
||||
|
||||
17
hak/tsconfig.json
Normal file
17
hak/tsconfig.json
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"target": "es2016",
|
||||
"sourceMap": false,
|
||||
"lib": [
|
||||
"es2019",
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
],
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
}
|
||||
}
|
||||
44
package.json
44
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "element-desktop",
|
||||
"productName": "Element",
|
||||
"main": "lib/electron-main.js",
|
||||
"version": "1.7.32",
|
||||
"version": "1.10.9",
|
||||
"description": "A feature-rich client for Matrix.org",
|
||||
"author": "Element",
|
||||
"repository": {
|
||||
@@ -20,11 +20,14 @@
|
||||
"asar-webapp": "asar p webapp webapp.asar",
|
||||
"start": "yarn run build:ts && yarn run build:res && electron .",
|
||||
"lint": "yarn lint:types && yarn lint:js",
|
||||
"lint:js": "eslint src/ scripts/ hak/",
|
||||
"lint:types": "tsc --noEmit",
|
||||
"lint:js": "eslint --max-warnings 0 src scripts hak",
|
||||
"lint:js-fix": "eslint --fix src scripts hak",
|
||||
"lint:types": "tsc --noEmit && tsc -p scripts/hak/tsconfig.json --noEmit && tsc -p hak/tsconfig.json --noEmit",
|
||||
"build:native": "yarn run hak",
|
||||
"build32": "yarn run build:ts && yarn run build:res && electron-builder --ia32",
|
||||
"build64": "yarn run build:ts && yarn run build:res && electron-builder --x64",
|
||||
"build:native:universal": "yarn run hak --target x86_64-apple-darwin fetchandbuild && yarn run hak --target aarch64-apple-darwin fetchandbuild && yarn run hak --target x86_64-apple-darwin --target aarch64-apple-darwin copyandlink",
|
||||
"build:32": "yarn run build:ts && yarn run build:res && electron-builder --ia32",
|
||||
"build:64": "yarn run build:ts && yarn run build:res && electron-builder --x64",
|
||||
"build:universal": "yarn run build:ts && yarn run build:res && electron-builder --universal",
|
||||
"build": "yarn run build:ts && yarn run build:res && electron-builder",
|
||||
"build:ts": "tsc",
|
||||
"build:res": "node scripts/copy-res.js",
|
||||
@@ -34,14 +37,14 @@
|
||||
"docker:install": "scripts/in-docker.sh yarn install",
|
||||
"debrepo": "scripts/mkrepo.sh",
|
||||
"clean": "rimraf webapp.asar dist packages deploys lib",
|
||||
"hak": "node scripts/hak/index.js"
|
||||
"hak": "ts-node scripts/hak/index.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"auto-launch": "^5.0.5",
|
||||
"counterpart": "^0.18.6",
|
||||
"electron-store": "^6.0.1",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"minimist": "^1.2.3",
|
||||
"minimist": "^1.2.6",
|
||||
"png-to-ico": "^2.1.1",
|
||||
"request": "^2.88.2"
|
||||
},
|
||||
@@ -49,38 +52,43 @@
|
||||
"@types/auto-launch": "^5.0.1",
|
||||
"@types/counterpart": "^0.18.1",
|
||||
"@types/minimist": "^1.2.1",
|
||||
"@typescript-eslint/eslint-plugin": "^4.17.0",
|
||||
"@typescript-eslint/parser": "^4.17.0",
|
||||
"@types/mkdirp": "^1.0.2",
|
||||
"@types/pacote": "^11.1.1",
|
||||
"@types/rimraf": "^3.0.2",
|
||||
"@typescript-eslint/eslint-plugin": "^5.6.0",
|
||||
"@typescript-eslint/parser": "^5.6.0",
|
||||
"allchange": "^1.0.6",
|
||||
"app-builder-lib": "^22.14.10",
|
||||
"asar": "^2.0.1",
|
||||
"chokidar": "^3.5.2",
|
||||
"electron": "12.0.11",
|
||||
"electron": "^17",
|
||||
"electron-builder": "22.11.4",
|
||||
"electron-builder-squirrel-windows": "22.11.4",
|
||||
"electron-devtools-installer": "^3.1.1",
|
||||
"electron-notarize": "^1.0.0",
|
||||
"eslint": "7.18.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-matrix-org": "github:matrix-org/eslint-plugin-matrix-org#main",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-matrix-org": "^0.4.0",
|
||||
"find-npm-prefix": "^1.0.2",
|
||||
"fs-extra": "^8.1.0",
|
||||
"glob": "^7.1.6",
|
||||
"matrix-web-i18n": "github:matrix-org/matrix-web-i18n",
|
||||
"matrix-web-i18n": "^1.2.0",
|
||||
"mkdirp": "^1.0.3",
|
||||
"needle": "^2.5.0",
|
||||
"node-pre-gyp": "^0.15.0",
|
||||
"npm": "^6.14.11",
|
||||
"pacote": "^11.3.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"semver": "^7.3.4",
|
||||
"tar": "^6.1.0",
|
||||
"typescript": "^4.1.3"
|
||||
"tar": "^6.1.2",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "^4.5.3"
|
||||
},
|
||||
"hakDependencies": {
|
||||
"matrix-seshat": "^2.2.3",
|
||||
"matrix-seshat": "^2.3.0",
|
||||
"keytar": "^5.6.0"
|
||||
},
|
||||
"build": {
|
||||
"appId": "im.riot.app",
|
||||
"electronVersion": "12.0.12",
|
||||
"files": [
|
||||
"package.json",
|
||||
{
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
signing_id: releases@riot.im
|
||||
subprojects:
|
||||
element-web:
|
||||
includeByDefault: true
|
||||
# Because element-web is not in our dependencies, but the versions
|
||||
# follow those of this project (well, vice-versa really)
|
||||
mirrorVersion: true
|
||||
|
||||
@@ -2,4 +2,4 @@
|
||||
|
||||
set -ex
|
||||
|
||||
yarn install $@
|
||||
yarn install --pure-lockfile $@
|
||||
|
||||
@@ -10,13 +10,12 @@ const asar = require('asar');
|
||||
const needle = require('needle');
|
||||
|
||||
const riotDesktopPackageJson = require('../package.json');
|
||||
const { setPackageVersion } = require('./set-version.js');
|
||||
|
||||
const PUB_KEY_URL = "https://packages.riot.im/element-release-key.asc";
|
||||
const PACKAGE_URL_PREFIX = "https://github.com/vector-im/element-web/releases/download/";
|
||||
const ASAR_PATH = 'webapp.asar';
|
||||
|
||||
const { setPackageVersion } = require('./set-version.js');
|
||||
|
||||
async function getLatestDevelopUrl(bkToken) {
|
||||
const buildsResult = await needle('get',
|
||||
"https://api.buildkite.com/v2/organizations/matrix-dot-org/pipelines/element-web/builds",
|
||||
|
||||
@@ -17,7 +17,8 @@ clone() {
|
||||
if [ -n "$branch" ]
|
||||
then
|
||||
echo "Trying to use $org/$repo#$branch"
|
||||
git clone git://github.com/$org/$repo.git $repo --branch "$branch" --depth 1 && exit 0
|
||||
# Disable auth prompts: https://serverfault.com/a/665959
|
||||
GIT_TERMINAL_PROMPT=0 git clone https://github.com/$org/$repo.git $repo --branch "$branch" --depth 1 && exit 0
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -14,8 +14,9 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
async function build(hakEnv, moduleInfo) {
|
||||
import { DependencyInfo } from "./dep";
|
||||
import HakEnv from "./hakEnv";
|
||||
|
||||
export default async function build(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
await moduleInfo.scripts.build(hakEnv, moduleInfo);
|
||||
}
|
||||
|
||||
module.exports = build;
|
||||
@@ -14,10 +14,11 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
async function check(hakEnv, moduleInfo) {
|
||||
import { DependencyInfo } from "./dep";
|
||||
import HakEnv from "./hakEnv";
|
||||
|
||||
export default async function check(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
if (moduleInfo.scripts.check) {
|
||||
await moduleInfo.scripts.check(hakEnv, moduleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = check;
|
||||
@@ -14,13 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
import path from 'path';
|
||||
import rimraf from 'rimraf';
|
||||
|
||||
const rimraf = require('rimraf');
|
||||
import { DependencyInfo } from './dep';
|
||||
import HakEnv from './hakEnv';
|
||||
|
||||
async function clean(hakEnv, moduleInfo) {
|
||||
await new Promise((resolve, reject) => {
|
||||
rimraf(moduleInfo.moduleDotHakDir, (err) => {
|
||||
export default async function clean(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
rimraf(moduleInfo.moduleDotHakDir, (err: Error) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
@@ -29,8 +31,8 @@ async function clean(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
rimraf(path.join(hakEnv.dotHakDir, 'links', moduleInfo.name), (err) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
rimraf(path.join(hakEnv.dotHakDir, 'links', moduleInfo.name), (err: Error) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
@@ -39,8 +41,8 @@ async function clean(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
rimraf(path.join(hakEnv.projectRoot, 'node_modules', moduleInfo.name), (err) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
rimraf(path.join(hakEnv.projectRoot, 'node_modules', moduleInfo.name), (err: Error) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
@@ -49,5 +51,3 @@ async function clean(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = clean;
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
Copyright 2020-2021 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 fsProm = require('fs').promises;
|
||||
|
||||
const rimraf = require('rimraf');
|
||||
const glob = require('glob');
|
||||
const mkdirp = require('mkdirp');
|
||||
|
||||
async function copy(hakEnv, moduleInfo) {
|
||||
if (moduleInfo.cfg.prune) {
|
||||
console.log("Removing " + moduleInfo.cfg.prune + " from " + moduleInfo.moduleOutDir);
|
||||
// rimraf doesn't have a 'cwd' option: it always uses process.cwd()
|
||||
// (and if you set glob.cwd it just breaks because it can't find the files)
|
||||
const oldCwd = process.cwd();
|
||||
try {
|
||||
process.chdir(moduleInfo.moduleOutDir);
|
||||
await new Promise((resolve, reject) => {
|
||||
rimraf(moduleInfo.cfg.prune, {}, err => {
|
||||
err ? reject(err) : resolve();
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
process.chdir(oldCwd);
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleInfo.cfg.copy) {
|
||||
console.log(
|
||||
"Copying files from " +
|
||||
moduleInfo.moduleBuildDir + " to " + moduleInfo.moduleOutDir,
|
||||
);
|
||||
const files = await new Promise(async (resolve, reject) => {
|
||||
glob(moduleInfo.cfg.copy, {
|
||||
nosort: true,
|
||||
silent: true,
|
||||
cwd: moduleInfo.moduleBuildDir,
|
||||
}, (err, files) => {
|
||||
err ? reject(err) : resolve(files);
|
||||
});
|
||||
});
|
||||
for (const f of files) {
|
||||
console.log("\t" + f);
|
||||
const src = path.join(moduleInfo.moduleBuildDir, f);
|
||||
const dst = path.join(moduleInfo.moduleOutDir, f);
|
||||
|
||||
await mkdirp(path.dirname(dst));
|
||||
await fsProm.copyFile(src, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = copy;
|
||||
100
scripts/hak/copy.ts
Normal file
100
scripts/hak/copy.ts
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
Copyright 2020-2021 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.
|
||||
*/
|
||||
|
||||
import path from 'path';
|
||||
import fsProm from 'fs/promises';
|
||||
import childProcess from 'child_process';
|
||||
import rimraf from 'rimraf';
|
||||
import glob from 'glob';
|
||||
import mkdirp from 'mkdirp';
|
||||
|
||||
import HakEnv from './hakEnv';
|
||||
import { DependencyInfo } from './dep';
|
||||
|
||||
export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
if (moduleInfo.cfg.prune) {
|
||||
console.log("Removing " + moduleInfo.cfg.prune + " from " + moduleInfo.moduleOutDir);
|
||||
// rimraf doesn't have a 'cwd' option: it always uses process.cwd()
|
||||
// (and if you set glob.cwd it just breaks because it can't find the files)
|
||||
const oldCwd = process.cwd();
|
||||
try {
|
||||
process.chdir(moduleInfo.moduleOutDir);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
rimraf(moduleInfo.cfg.prune, {}, err => {
|
||||
err ? reject(err) : resolve();
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
process.chdir(oldCwd);
|
||||
}
|
||||
}
|
||||
|
||||
if (moduleInfo.cfg.copy) {
|
||||
// If there are multiple moduleBuildDirs, singular moduleBuildDir
|
||||
// is the same as moduleBuildDirs[0], so we're just listing the contents
|
||||
// of the first one.
|
||||
const files = await new Promise<string[]>((resolve, reject) => {
|
||||
glob(moduleInfo.cfg.copy, {
|
||||
nosort: true,
|
||||
silent: true,
|
||||
cwd: moduleInfo.moduleBuildDir,
|
||||
}, (err, files) => {
|
||||
err ? reject(err) : resolve(files);
|
||||
});
|
||||
});
|
||||
|
||||
if (moduleInfo.moduleBuildDirs.length > 1) {
|
||||
if (!hakEnv.isMac()) {
|
||||
console.error(
|
||||
"You asked me to copy multiple targets but I've only been taught " +
|
||||
"how to do that on macOS.",
|
||||
);
|
||||
throw new Error("Can't copy multiple targets on this platform");
|
||||
}
|
||||
|
||||
for (const f of files) {
|
||||
const components = moduleInfo.moduleBuildDirs.map(dir => path.join(dir, f));
|
||||
const dst = path.join(moduleInfo.moduleOutDir, f);
|
||||
|
||||
await mkdirp(path.dirname(dst));
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
childProcess.execFile('lipo',
|
||||
['-create', '-output', dst, ...components], (err) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
console.log(
|
||||
"Copying files from " +
|
||||
moduleInfo.moduleBuildDir + " to " + moduleInfo.moduleOutDir,
|
||||
);
|
||||
for (const f of files) {
|
||||
console.log("\t" + f);
|
||||
const src = path.join(moduleInfo.moduleBuildDir, f);
|
||||
const dst = path.join(moduleInfo.moduleOutDir, f);
|
||||
|
||||
await mkdirp(path.dirname(dst));
|
||||
await fsProm.copyFile(src, dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
32
scripts/hak/dep.ts
Normal file
32
scripts/hak/dep.ts
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Copyright 2021 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.
|
||||
*/
|
||||
|
||||
import HakEnv from "./hakEnv";
|
||||
|
||||
export interface DependencyInfo {
|
||||
name: string;
|
||||
version: string;
|
||||
cfg: Record<string, any>;
|
||||
moduleHakDir: string;
|
||||
moduleDotHakDir: string;
|
||||
moduleTargetDotHakDir: string;
|
||||
moduleBuildDir: string;
|
||||
moduleBuildDirs: string[];
|
||||
moduleOutDir: string;
|
||||
nodeModuleBinDir: string;
|
||||
depPrefix: string;
|
||||
scripts: Record<string, (hakEnv: HakEnv, moduleInfo: DependencyInfo) => Promise<void> >;
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const url = require('url');
|
||||
const fsProm = require('fs').promises;
|
||||
const childProcess = require('child_process');
|
||||
|
||||
const npm = require('npm');
|
||||
const semver = require('semver');
|
||||
const needle = require('needle');
|
||||
const mkdirp = require('mkdirp');
|
||||
const tar = require('tar');
|
||||
|
||||
async function fetch(hakEnv, moduleInfo) {
|
||||
let haveModuleBuildDir;
|
||||
try {
|
||||
const stats = await fsProm.stat(moduleInfo.moduleBuildDir);
|
||||
haveModuleBuildDir = stats.isDirectory();
|
||||
} catch (e) {
|
||||
haveModuleBuildDir = false;
|
||||
}
|
||||
|
||||
if (haveModuleBuildDir) return;
|
||||
|
||||
await new Promise((resolve) => {
|
||||
npm.load({ 'loglevel': 'silent' }, resolve);
|
||||
});
|
||||
|
||||
console.log("Fetching " + moduleInfo.name + " at version " + moduleInfo.version);
|
||||
const versions = await new Promise((resolve, reject) => {
|
||||
npm.view([
|
||||
moduleInfo.name + '@' + moduleInfo.version,
|
||||
'dist.tarball',
|
||||
(err, versions) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(versions);
|
||||
}
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
const orderedVersions = Object.keys(versions);
|
||||
semver.sort(orderedVersions);
|
||||
|
||||
console.log("Resolved version " + orderedVersions[0] + " for " + moduleInfo.name);
|
||||
|
||||
const tarballUrl = versions[orderedVersions[0]]['dist.tarball'];
|
||||
|
||||
await mkdirp(moduleInfo.moduleDotHakDir);
|
||||
|
||||
const parsedUrl = url.parse(tarballUrl);
|
||||
const tarballFile = path.join(moduleInfo.moduleDotHakDir, path.basename(parsedUrl.path));
|
||||
|
||||
let haveTarball;
|
||||
try {
|
||||
await fsProm.stat(tarballFile);
|
||||
haveTarball = true;
|
||||
} catch (e) {
|
||||
haveTarball = false;
|
||||
}
|
||||
if (!haveTarball) {
|
||||
console.log("Downloading " + tarballUrl);
|
||||
await needle('get', tarballUrl, { output: tarballFile });
|
||||
} else {
|
||||
console.log(tarballFile + " already exists.");
|
||||
}
|
||||
|
||||
await mkdirp(moduleInfo.moduleBuildDir);
|
||||
|
||||
await tar.x({
|
||||
file: tarballFile,
|
||||
cwd: moduleInfo.moduleBuildDir,
|
||||
strip: 1,
|
||||
});
|
||||
|
||||
console.log("Running yarn install in " + moduleInfo.moduleBuildDir);
|
||||
await new Promise((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
hakEnv.isWin() ? 'yarn.cmd' : 'yarn',
|
||||
['install', '--ignore-scripts'],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
cwd: moduleInfo.moduleBuildDir,
|
||||
},
|
||||
);
|
||||
proc.on('exit', code => {
|
||||
code ? reject(code) : resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// also extract another copy to the output directory at this point
|
||||
// nb. we do not yarn install in the output copy: we could install in
|
||||
// production mode to get only runtime dependencies and not devDependencies,
|
||||
// but usually native modules come with dependencies that are needed for
|
||||
// building/fetching the native modules (eg. node-pre-gyp) rather than
|
||||
// actually used at runtime: we do not want to bundle these into our app.
|
||||
// We therefore just install no dependencies at all, and accept that any
|
||||
// actual runtime dependencies will have to be added to the main app's
|
||||
// dependencies. We can't tell what dependencies are real runtime deps
|
||||
// and which are just used for native module building.
|
||||
await mkdirp(moduleInfo.moduleOutDir);
|
||||
await tar.x({
|
||||
file: tarballFile,
|
||||
cwd: moduleInfo.moduleOutDir,
|
||||
strip: 1,
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = fetch;
|
||||
70
scripts/hak/fetch.ts
Normal file
70
scripts/hak/fetch.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
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.
|
||||
*/
|
||||
|
||||
import fsProm from 'fs/promises';
|
||||
import childProcess from 'child_process';
|
||||
import pacote from 'pacote';
|
||||
|
||||
import HakEnv from './hakEnv';
|
||||
import { DependencyInfo } from './dep';
|
||||
|
||||
export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
let haveModuleBuildDir;
|
||||
try {
|
||||
const stats = await fsProm.stat(moduleInfo.moduleBuildDir);
|
||||
haveModuleBuildDir = stats.isDirectory();
|
||||
} catch (e) {
|
||||
haveModuleBuildDir = false;
|
||||
}
|
||||
|
||||
if (haveModuleBuildDir) return;
|
||||
|
||||
console.log("Fetching " + moduleInfo.name + "@" + moduleInfo.version);
|
||||
|
||||
const packumentCache = new Map();
|
||||
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleBuildDir, {
|
||||
packumentCache,
|
||||
});
|
||||
|
||||
console.log("Running yarn install in " + moduleInfo.moduleBuildDir);
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(
|
||||
hakEnv.isWin() ? 'yarn.cmd' : 'yarn',
|
||||
['install', '--ignore-scripts'],
|
||||
{
|
||||
stdio: 'inherit',
|
||||
cwd: moduleInfo.moduleBuildDir,
|
||||
},
|
||||
);
|
||||
proc.on('exit', code => {
|
||||
code ? reject(code) : resolve();
|
||||
});
|
||||
});
|
||||
|
||||
// also extract another copy to the output directory at this point
|
||||
// nb. we do not yarn install in the output copy: we could install in
|
||||
// production mode to get only runtime dependencies and not devDependencies,
|
||||
// but usually native modules come with dependencies that are needed for
|
||||
// building/fetching the native modules (eg. node-pre-gyp) rather than
|
||||
// actually used at runtime: we do not want to bundle these into our app.
|
||||
// We therefore just install no dependencies at all, and accept that any
|
||||
// actual runtime dependencies will have to be added to the main app's
|
||||
// dependencies. We can't tell what dependencies are real runtime deps
|
||||
// and which are just used for native module building.
|
||||
await pacote.extract(`${moduleInfo.name}@${moduleInfo.version}`, moduleInfo.moduleOutDir, {
|
||||
packumentCache,
|
||||
});
|
||||
}
|
||||
@@ -14,13 +14,14 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const mkdirp = require('mkdirp');
|
||||
import mkdirp from 'mkdirp';
|
||||
|
||||
async function fetchDeps(hakEnv, moduleInfo) {
|
||||
import { DependencyInfo } from './dep';
|
||||
import HakEnv from './hakEnv';
|
||||
|
||||
export default async function fetchDeps(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
await mkdirp(moduleInfo.moduleDotHakDir);
|
||||
if (moduleInfo.scripts.fetchDeps) {
|
||||
await moduleInfo.scripts.fetchDeps(hakEnv, moduleInfo);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = fetchDeps;
|
||||
@@ -14,28 +14,20 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import nodePreGypVersioning from "node-pre-gyp/lib/util/versioning";
|
||||
import { getElectronVersion } from "app-builder-lib/out/electron/electronVersion";
|
||||
|
||||
const nodePreGypVersioning = require('node-pre-gyp/lib/util/versioning');
|
||||
const { TARGETS, getHost, isHostId } = require('./target');
|
||||
import { Arch, Target, TARGETS, getHost, isHostId, TargetId } from './target';
|
||||
|
||||
function getElectronVersion(packageJson) {
|
||||
// should we pick the version of an installed electron
|
||||
// dependency, and if so, before or after electronVersion?
|
||||
if (packageJson.build && packageJson.build.electronVersion) {
|
||||
return packageJson.build.electronVersion;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
function getRuntime(packageJson) {
|
||||
const electronVersion = getElectronVersion(packageJson);
|
||||
async function getRuntime(projectRoot: string): Promise<string> {
|
||||
const electronVersion = await getElectronVersion(projectRoot);
|
||||
return electronVersion ? 'electron' : 'node-webkit';
|
||||
}
|
||||
|
||||
function getRuntimeVersion(packageJson) {
|
||||
const electronVersion = getElectronVersion(packageJson);
|
||||
async function getRuntimeVersion(projectRoot: string): Promise<string> {
|
||||
const electronVersion = await getElectronVersion(projectRoot);
|
||||
if (electronVersion) {
|
||||
return electronVersion;
|
||||
} else {
|
||||
@@ -43,8 +35,14 @@ function getRuntimeVersion(packageJson) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = class HakEnv {
|
||||
constructor(prefix, packageJson, targetId) {
|
||||
export default class HakEnv {
|
||||
public target: Target;
|
||||
public projectRoot: string;
|
||||
public runtime: string;
|
||||
public runtimeVersion: string;
|
||||
public dotHakDir: string;
|
||||
|
||||
constructor(prefix: string, targetId: TargetId) {
|
||||
let target;
|
||||
if (targetId) {
|
||||
target = TARGETS[targetId];
|
||||
@@ -55,20 +53,17 @@ module.exports = class HakEnv {
|
||||
if (!target) {
|
||||
throw new Error(`Unknown target ${targetId}!`);
|
||||
}
|
||||
|
||||
Object.assign(this, {
|
||||
// what we're targeting
|
||||
runtime: getRuntime(packageJson),
|
||||
runtimeVersion: getRuntimeVersion(packageJson),
|
||||
target,
|
||||
|
||||
// paths
|
||||
projectRoot: prefix,
|
||||
dotHakDir: path.join(prefix, '.hak'),
|
||||
});
|
||||
this.target = target;
|
||||
this.projectRoot = prefix;
|
||||
this.dotHakDir = path.join(this.projectRoot, '.hak');
|
||||
}
|
||||
|
||||
getRuntimeAbi() {
|
||||
async init() {
|
||||
this.runtime = await getRuntime(this.projectRoot);
|
||||
this.runtimeVersion = await getRuntimeVersion(this.projectRoot);
|
||||
}
|
||||
|
||||
getRuntimeAbi(): string {
|
||||
return nodePreGypVersioning.get_runtime_abi(
|
||||
this.runtime,
|
||||
this.runtimeVersion,
|
||||
@@ -76,35 +71,35 @@ module.exports = class HakEnv {
|
||||
}
|
||||
|
||||
// {node_abi}-{platform}-{arch}
|
||||
getNodeTriple() {
|
||||
getNodeTriple(): string {
|
||||
return this.getRuntimeAbi() + '-' + this.target.platform + '-' + this.target.arch;
|
||||
}
|
||||
|
||||
getTargetId() {
|
||||
getTargetId(): TargetId {
|
||||
return this.target.id;
|
||||
}
|
||||
|
||||
isWin() {
|
||||
isWin(): boolean {
|
||||
return this.target.platform === 'win32';
|
||||
}
|
||||
|
||||
isMac() {
|
||||
isMac(): boolean {
|
||||
return this.target.platform === 'darwin';
|
||||
}
|
||||
|
||||
isLinux() {
|
||||
isLinux(): boolean {
|
||||
return this.target.platform === 'linux';
|
||||
}
|
||||
|
||||
getTargetArch() {
|
||||
getTargetArch(): Arch {
|
||||
return this.target.arch;
|
||||
}
|
||||
|
||||
isHost() {
|
||||
isHost(): boolean {
|
||||
return isHostId(this.target.id);
|
||||
}
|
||||
|
||||
makeGypEnv() {
|
||||
makeGypEnv(): Record<string, string> {
|
||||
return Object.assign({}, process.env, {
|
||||
npm_config_arch: this.target.arch,
|
||||
npm_config_target_arch: this.target.arch,
|
||||
@@ -116,7 +111,7 @@ module.exports = class HakEnv {
|
||||
});
|
||||
}
|
||||
|
||||
getNodeModuleBin(name) {
|
||||
getNodeModuleBin(name: string): string {
|
||||
return path.join(this.projectRoot, 'node_modules', '.bin', name);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -14,11 +14,12 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
import path from 'path';
|
||||
import findNpmPrefix from 'find-npm-prefix';
|
||||
|
||||
const findNpmPrefix = require('find-npm-prefix');
|
||||
|
||||
const HakEnv = require('./hakEnv');
|
||||
import HakEnv from './hakEnv';
|
||||
import { TargetId } from './target';
|
||||
import { DependencyInfo } from './dep';
|
||||
|
||||
const GENERALCOMMANDS = [
|
||||
'target',
|
||||
@@ -35,6 +36,13 @@ const MODULECOMMANDS = [
|
||||
'clean',
|
||||
];
|
||||
|
||||
// Shortcuts for multiple commands at once (useful for building universal binaries
|
||||
// because you can run the fetch/fetchDeps/build for each arch and then copy/link once)
|
||||
const METACOMMANDS = {
|
||||
'fetchandbuild': ['check', 'fetch', 'fetchDeps', 'build'],
|
||||
'copyandlink': ['copy', 'link'],
|
||||
};
|
||||
|
||||
// Scripts valid in a hak.json 'scripts' section
|
||||
const HAKSCRIPTS = [
|
||||
'check',
|
||||
@@ -53,21 +61,30 @@ async function main() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const targetIds = [] as TargetId[];
|
||||
// Apply `--target <target>` option if specified
|
||||
const targetIndex = process.argv.indexOf('--target');
|
||||
let targetId;
|
||||
if (targetIndex >= 0) {
|
||||
// Can be specified multiple times for the copy command to bundle
|
||||
// multiple archs into a single universal output module)
|
||||
while (true) { // eslint-disable-line no-constant-condition
|
||||
const targetIndex = process.argv.indexOf('--target');
|
||||
if (targetIndex === -1) break;
|
||||
|
||||
if ((targetIndex + 1) >= process.argv.length) {
|
||||
console.error("--target option specified without a target");
|
||||
process.exit(1);
|
||||
}
|
||||
// Extract target ID and remove from args
|
||||
targetId = process.argv.splice(targetIndex, 2)[1];
|
||||
targetIds.push(process.argv.splice(targetIndex, 2)[1] as TargetId);
|
||||
}
|
||||
|
||||
const hakEnv = new HakEnv(prefix, packageJson, targetId);
|
||||
const hakEnvs = targetIds.map(tid => new HakEnv(prefix, tid));
|
||||
if (hakEnvs.length == 0) hakEnvs.push(new HakEnv(prefix, null));
|
||||
for (const h of hakEnvs) {
|
||||
await h.init();
|
||||
}
|
||||
const hakEnv = hakEnvs[0];
|
||||
|
||||
const deps = {};
|
||||
const deps = {} as Record<string, DependencyInfo>;
|
||||
|
||||
const hakDepsCfg = packageJson.hakDependencies || {};
|
||||
|
||||
@@ -87,16 +104,23 @@ async function main() {
|
||||
cfg: hakJson,
|
||||
moduleHakDir: path.join(prefix, 'hak', dep),
|
||||
moduleDotHakDir: path.join(hakEnv.dotHakDir, dep),
|
||||
moduleBuildDir: path.join(hakEnv.dotHakDir, dep, 'build'),
|
||||
moduleTargetDotHakDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId()),
|
||||
moduleBuildDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), 'build'),
|
||||
moduleBuildDirs: hakEnvs.map(h => path.join(h.dotHakDir, dep, h.getTargetId(), 'build')),
|
||||
moduleOutDir: path.join(hakEnv.dotHakDir, 'hakModules', dep),
|
||||
nodeModuleBinDir: path.join(hakEnv.dotHakDir, dep, 'build', 'node_modules', '.bin'),
|
||||
depPrefix: path.join(hakEnv.dotHakDir, dep, 'opt'),
|
||||
nodeModuleBinDir: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), 'build', 'node_modules', '.bin'),
|
||||
depPrefix: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), 'opt'),
|
||||
scripts: {},
|
||||
};
|
||||
|
||||
for (const s of HAKSCRIPTS) {
|
||||
if (hakJson.scripts && hakJson.scripts[s]) {
|
||||
deps[dep].scripts[s] = require(path.join(prefix, 'hak', dep, hakJson.scripts[s]));
|
||||
const scriptModule = await import(path.join(prefix, 'hak', dep, hakJson.scripts[s]));
|
||||
if (scriptModule.__esModule) {
|
||||
deps[dep].scripts[s] = scriptModule.default;
|
||||
} else {
|
||||
deps[dep].scripts[s] = scriptModule;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,10 +128,18 @@ async function main() {
|
||||
let cmds;
|
||||
if (process.argv.length < 3) {
|
||||
cmds = ['check', 'fetch', 'fetchDeps', 'build', 'copy', 'link'];
|
||||
} else if (METACOMMANDS[process.argv[2]]) {
|
||||
cmds = METACOMMANDS[process.argv[2]];
|
||||
} else {
|
||||
cmds = [process.argv[2]];
|
||||
}
|
||||
|
||||
if (hakEnvs.length > 1 && cmds.some(c => !['copy', 'link'].includes(c))) {
|
||||
// We allow link here too for convenience because it's completely arch independent
|
||||
console.error("Multiple targets only supported with the copy command");
|
||||
return;
|
||||
}
|
||||
|
||||
let modules = process.argv.slice(3);
|
||||
if (modules.length === 0) modules = Object.keys(deps);
|
||||
|
||||
@@ -128,7 +160,7 @@ async function main() {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const cmdFunc = require('./' + cmd);
|
||||
const cmdFunc = (await import('./' + cmd)).default;
|
||||
|
||||
for (const mod of modules) {
|
||||
const depInfo = deps[mod];
|
||||
@@ -14,12 +14,15 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const fsProm = require('fs').promises;
|
||||
const childProcess = require('child_process');
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import fsProm from 'fs/promises';
|
||||
import childProcess from 'child_process';
|
||||
|
||||
async function link(hakEnv, moduleInfo) {
|
||||
import HakEnv from './hakEnv';
|
||||
import { DependencyInfo } from './dep';
|
||||
|
||||
export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
const yarnrc = path.join(hakEnv.projectRoot, '.yarnrc');
|
||||
// this is fairly terrible but it's reasonably clunky to either parse a yarnrc
|
||||
// properly or get yarn to do it, so this will probably suffice for now.
|
||||
@@ -46,7 +49,7 @@ async function link(hakEnv, moduleInfo) {
|
||||
|
||||
const yarnCmd = 'yarn' + (hakEnv.isWin() ? '.cmd' : '');
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(yarnCmd, ['link'], {
|
||||
cwd: moduleInfo.moduleOutDir,
|
||||
stdio: 'inherit',
|
||||
@@ -56,7 +59,7 @@ async function link(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise((resolve, reject) => {
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const proc = childProcess.spawn(yarnCmd, ['link', moduleInfo.name], {
|
||||
cwd: hakEnv.projectRoot,
|
||||
stdio: 'inherit',
|
||||
@@ -66,5 +69,3 @@ async function link(hakEnv, moduleInfo) {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = link;
|
||||
@@ -1,82 +0,0 @@
|
||||
"use strict";
|
||||
/*
|
||||
Copyright 2021 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* THIS FILE IS GENERATED, NOT MEANT FOR EDITING DIRECTLY
|
||||
* The original source is `target.ts` in the `element-builder` repo. You can
|
||||
* edit it over there, run `yarn build`, and paste the changes here. It is
|
||||
* currently assumed this file will rarely change, so a spearate package is not
|
||||
* yet warranted.
|
||||
*/
|
||||
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.isHost = exports.isHostId = exports.getHost = exports.ENABLED_TARGETS = exports.TARGETS = void 0;
|
||||
const aarch64AppleDarwin = {
|
||||
id: 'aarch64-apple-darwin',
|
||||
platform: 'darwin',
|
||||
arch: 'arm64',
|
||||
};
|
||||
const i686PcWindowsMsvc = {
|
||||
id: 'i686-pc-windows-msvc',
|
||||
platform: 'win32',
|
||||
arch: 'ia32',
|
||||
vcVarsArch: 'x86',
|
||||
};
|
||||
const x8664PcWindowsMsvc = {
|
||||
id: 'x86_64-pc-windows-msvc',
|
||||
platform: 'win32',
|
||||
arch: 'x64',
|
||||
vcVarsArch: 'amd64',
|
||||
};
|
||||
const x8664AppleDarwin = {
|
||||
id: 'x86_64-apple-darwin',
|
||||
platform: 'darwin',
|
||||
arch: 'x64',
|
||||
};
|
||||
const x8664UnknownLinuxGnu = {
|
||||
id: 'x86_64-unknown-linux-gnu',
|
||||
platform: 'linux',
|
||||
arch: 'x64',
|
||||
};
|
||||
exports.TARGETS = {
|
||||
'aarch64-apple-darwin': aarch64AppleDarwin,
|
||||
'i686-pc-windows-msvc': i686PcWindowsMsvc,
|
||||
'x86_64-pc-windows-msvc': x8664PcWindowsMsvc,
|
||||
'x86_64-apple-darwin': x8664AppleDarwin,
|
||||
'x86_64-unknown-linux-gnu': x8664UnknownLinuxGnu,
|
||||
};
|
||||
// The set of targets we build by default, sorted by increasing complexity so
|
||||
// that we fail fast when the native host target fails.
|
||||
exports.ENABLED_TARGETS = [
|
||||
exports.TARGETS['x86_64-apple-darwin'],
|
||||
exports.TARGETS['aarch64-apple-darwin'],
|
||||
exports.TARGETS['x86_64-unknown-linux-gnu'],
|
||||
exports.TARGETS['i686-pc-windows-msvc'],
|
||||
];
|
||||
function getHost() {
|
||||
return Object.values(exports.TARGETS).find(target => (target.platform === process.platform &&
|
||||
target.arch === process.arch));
|
||||
}
|
||||
exports.getHost = getHost;
|
||||
function isHostId(id) {
|
||||
return getHost()?.id === id;
|
||||
}
|
||||
exports.isHostId = isHostId;
|
||||
function isHost(target) {
|
||||
return getHost()?.id === target.id;
|
||||
}
|
||||
exports.isHost = isHost;
|
||||
126
scripts/hak/target.ts
Normal file
126
scripts/hak/target.ts
Normal file
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
Copyright 2021 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.
|
||||
*/
|
||||
|
||||
// We borrow Rust's target naming scheme as a way of expressing all target
|
||||
// details in a single string.
|
||||
// See https://doc.rust-lang.org/rustc/platform-support.html.
|
||||
export type TargetId =
|
||||
'aarch64-apple-darwin' |
|
||||
'x86_64-apple-darwin' |
|
||||
'universal-apple-darwin' |
|
||||
'i686-pc-windows-msvc' |
|
||||
'x86_64-pc-windows-msvc' |
|
||||
'x86_64-unknown-linux-gnu';
|
||||
|
||||
// Values are expected to match those used in `process.platform`.
|
||||
export type Platform = 'darwin' | 'linux' | 'win32';
|
||||
|
||||
// Values are expected to match those used in `process.arch`.
|
||||
export type Arch = 'arm64' | 'ia32' | 'x64' | 'universal';
|
||||
|
||||
// Values are expected to match those used by Visual Studio's `vcvarsall.bat`.
|
||||
// See https://docs.microsoft.com/cpp/build/building-on-the-command-line?view=msvc-160#vcvarsall-syntax
|
||||
export type VcVarsArch = 'amd64' | 'arm64' | 'x86';
|
||||
|
||||
export type Target = {
|
||||
id: TargetId;
|
||||
platform: Platform;
|
||||
arch: Arch;
|
||||
};
|
||||
|
||||
export type WindowsTarget = Target & {
|
||||
platform: 'win32';
|
||||
vcVarsArch: VcVarsArch;
|
||||
};
|
||||
|
||||
export type UniversalTarget = Target & {
|
||||
arch: 'universal';
|
||||
subtargets: Target[];
|
||||
};
|
||||
|
||||
const aarch64AppleDarwin: Target = {
|
||||
id: 'aarch64-apple-darwin',
|
||||
platform: 'darwin',
|
||||
arch: 'arm64',
|
||||
};
|
||||
|
||||
const x8664AppleDarwin: Target = {
|
||||
id: 'x86_64-apple-darwin',
|
||||
platform: 'darwin',
|
||||
arch: 'x64',
|
||||
};
|
||||
|
||||
const universalAppleDarwin: UniversalTarget = {
|
||||
id: 'universal-apple-darwin',
|
||||
platform: 'darwin',
|
||||
arch: 'universal',
|
||||
subtargets: [
|
||||
aarch64AppleDarwin,
|
||||
x8664AppleDarwin,
|
||||
],
|
||||
};
|
||||
|
||||
const i686PcWindowsMsvc: WindowsTarget = {
|
||||
id: 'i686-pc-windows-msvc',
|
||||
platform: 'win32',
|
||||
arch: 'ia32',
|
||||
vcVarsArch: 'x86',
|
||||
};
|
||||
|
||||
const x8664PcWindowsMsvc: WindowsTarget = {
|
||||
id: 'x86_64-pc-windows-msvc',
|
||||
platform: 'win32',
|
||||
arch: 'x64',
|
||||
vcVarsArch: 'amd64',
|
||||
};
|
||||
|
||||
const x8664UnknownLinuxGnu: Target = {
|
||||
id: 'x86_64-unknown-linux-gnu',
|
||||
platform: 'linux',
|
||||
arch: 'x64',
|
||||
};
|
||||
|
||||
export const TARGETS: Record<TargetId, Target> = {
|
||||
'aarch64-apple-darwin': aarch64AppleDarwin,
|
||||
'x86_64-apple-darwin': x8664AppleDarwin,
|
||||
'universal-apple-darwin': universalAppleDarwin,
|
||||
'i686-pc-windows-msvc': i686PcWindowsMsvc,
|
||||
'x86_64-pc-windows-msvc': x8664PcWindowsMsvc,
|
||||
'x86_64-unknown-linux-gnu': x8664UnknownLinuxGnu,
|
||||
};
|
||||
|
||||
// The set of targets we build by default, sorted by increasing complexity so
|
||||
// that we fail fast when the native host target fails.
|
||||
export const ENABLED_TARGETS: Target[] = [
|
||||
TARGETS['universal-apple-darwin'],
|
||||
TARGETS['x86_64-unknown-linux-gnu'],
|
||||
TARGETS['x86_64-pc-windows-msvc'],
|
||||
];
|
||||
|
||||
export function getHost(): Target {
|
||||
return Object.values(TARGETS).find(target => (
|
||||
target.platform === process.platform &&
|
||||
target.arch === process.arch
|
||||
));
|
||||
}
|
||||
|
||||
export function isHostId(id: TargetId): boolean {
|
||||
return getHost()?.id === id;
|
||||
}
|
||||
|
||||
export function isHost(target: Target): boolean {
|
||||
return getHost()?.id === target.id;
|
||||
}
|
||||
18
scripts/hak/tsconfig.json
Normal file
18
scripts/hak/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"sourceMap": false,
|
||||
"lib": [
|
||||
"es2019",
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"./**/*.ts"
|
||||
],
|
||||
"ts-node": {
|
||||
"transpileOnly": true
|
||||
}
|
||||
}
|
||||
@@ -7,8 +7,9 @@ if [ $? != 0 ]; then
|
||||
fi
|
||||
|
||||
# Taken from https://www.electron.build/multi-platform-build#docker
|
||||
# Pass through any vars prefixed with INDOCKER_, removing the prefix
|
||||
docker run --rm -ti \
|
||||
--env-file <(env | grep -iE '^BUILDKITE_API_KEY=') \
|
||||
--env-file <(env | grep -E '^INDOCKER_' | sed -e 's/^INDOCKER_//') \
|
||||
--env ELECTRON_CACHE="/root/.cache/electron" \
|
||||
--env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \
|
||||
-v ${PWD}:/project \
|
||||
|
||||
@@ -17,13 +17,19 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Squirrel on windows starts the app with various flags
|
||||
// as hooks to tell us when we've been installed/uninstalled
|
||||
// etc.
|
||||
import { checkSquirrelHooks } from "./squirrelhooks";
|
||||
if (checkSquirrelHooks()) process.exit(1);
|
||||
|
||||
import { app, ipcMain, powerSaveBlocker, BrowserWindow, Menu, autoUpdater, protocol, dialog } from "electron";
|
||||
// Squirrel on windows starts the app with various flags as hooks to tell us when we've been installed/uninstalled etc.
|
||||
import "./squirrelhooks";
|
||||
import {
|
||||
app,
|
||||
ipcMain,
|
||||
powerSaveBlocker,
|
||||
BrowserWindow,
|
||||
Menu,
|
||||
autoUpdater,
|
||||
protocol,
|
||||
dialog,
|
||||
desktopCapturer,
|
||||
} from "electron";
|
||||
import AutoLaunch from "auto-launch";
|
||||
import path from "path";
|
||||
import windowStateKeeper from 'electron-window-state';
|
||||
@@ -329,7 +335,12 @@ process.on('uncaughtException', function(error) {
|
||||
|
||||
let focusHandlerAttached = false;
|
||||
ipcMain.on('setBadgeCount', function(ev, count) {
|
||||
app.badgeCount = count;
|
||||
if (process.platform !== 'win32') {
|
||||
// only set badgeCount on Mac/Linux, the docs say that only those platforms support it but turns out Electron
|
||||
// has some Windows support too, and in some Windows environments this leads to two badges rendering atop
|
||||
// each other. See https://github.com/vector-im/element-web/issues/16942
|
||||
app.badgeCount = count;
|
||||
}
|
||||
if (count === 0 && mainWindow) {
|
||||
mainWindow.flashFrame(false);
|
||||
}
|
||||
@@ -501,6 +512,13 @@ ipcMain.on('ipcCall', async function(ev, payload) {
|
||||
await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`);
|
||||
} catch (e) {}
|
||||
break;
|
||||
case 'getDesktopCapturerSources':
|
||||
ret = (await desktopCapturer.getSources(args[0])).map((source) => ({
|
||||
id: source.id,
|
||||
name: source.name,
|
||||
thumbnailURL: source.thumbnail.toDataURL(),
|
||||
}));
|
||||
break;
|
||||
|
||||
default:
|
||||
mainWindow.webContents.send('ipcReply', {
|
||||
@@ -784,6 +802,9 @@ ipcMain.on('seshat', async function(ev, payload) {
|
||||
});
|
||||
|
||||
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
|
||||
if (!app.commandLine.hasSwitch('enable-features')) {
|
||||
app.commandLine.appendSwitch('enable-features', 'WebRTCPipeWireCapturer');
|
||||
}
|
||||
|
||||
const gotLock = app.requestSingleInstanceLock();
|
||||
if (!gotLock) {
|
||||
@@ -935,9 +956,8 @@ app.on('ready', async () => {
|
||||
preload: preloadScript,
|
||||
nodeIntegration: false,
|
||||
//sandbox: true, // We enable sandboxing from app.enableSandbox() above
|
||||
enableRemoteModule: false,
|
||||
contextIsolation: true,
|
||||
webgl: false,
|
||||
webgl: true,
|
||||
},
|
||||
});
|
||||
mainWindow.loadURL('vector://vector/webapp/');
|
||||
|
||||
@@ -1,12 +1,46 @@
|
||||
{
|
||||
"File": "مَلَفّ",
|
||||
"Close": "إغلاق",
|
||||
"Actual Size": "الحَجمُ الفِعلي",
|
||||
"View": "الاِطِّلاع",
|
||||
"Select All": "تَحدِيدُ الكُل",
|
||||
"Delete": "حَذف",
|
||||
"Copy": "نَسخ",
|
||||
"Edit": "تَحرير",
|
||||
"Close Element": "إغلَاقُ Element",
|
||||
"Cancel": "إلغَاء"
|
||||
"File": "ملف",
|
||||
"Close": "أغلِق",
|
||||
"Actual Size": "المقاس الفعلي",
|
||||
"View": "منظور",
|
||||
"Select All": "حدّد الكل",
|
||||
"Delete": "احذف",
|
||||
"Copy": "انسخ",
|
||||
"Edit": "تحرير",
|
||||
"Close Element": "أغلِق Element",
|
||||
"Cancel": "ألغِ",
|
||||
"Bring All to Front": "ضَع الكل في المقدّمة",
|
||||
"Speech": "نطق",
|
||||
"Add to dictionary": "أضِف إلى القاموس",
|
||||
"The image failed to save": "فشل حفظ الصورة",
|
||||
"Failed to save image": "فشل حفظ الصورة",
|
||||
"Save image as...": "احفظ الصورة كَ...",
|
||||
"Copy link address": "انسخ عنوان الرابط",
|
||||
"Copy email address": "انسخ عنوان البريد الإلكتروني",
|
||||
"Copy image": "انسخ الصورة",
|
||||
"Zoom": "تقريب",
|
||||
"Stop Speaking": "أوقِف النطق",
|
||||
"Start Speaking": "ابدأ النطق",
|
||||
"Unhide": "اعرض",
|
||||
"Hide Others": "أخفِ البقية",
|
||||
"Hide": "أخفِ",
|
||||
"Services": "الخدمات",
|
||||
"About": "عن",
|
||||
"Element Help": "مساعدة Element",
|
||||
"Help": "مساعدة",
|
||||
"Minimize": "صغّر",
|
||||
"Window": "نافذة",
|
||||
"Toggle Developer Tools": "فعّل/عطّل أدوات المطوّرين",
|
||||
"Toggle Full Screen": "فعّل/عطّل ملء الشاشة",
|
||||
"Preferences": "التفضيلات",
|
||||
"Zoom In": "قرّب",
|
||||
"Zoom Out": "بعّد",
|
||||
"Paste and Match Style": "ألصِق وطابِق النمط",
|
||||
"Paste": "ألصِق",
|
||||
"Cut": "قصّ",
|
||||
"Redo": "أعِد",
|
||||
"Undo": "تراجَع",
|
||||
"Quit": "غادِر",
|
||||
"Show/Hide": "اعرض/أخفِ",
|
||||
"Are you sure you want to quit?": "أمتأكّد من الإغلاق؟"
|
||||
}
|
||||
|
||||
46
src/i18n/strings/be.json
Normal file
46
src/i18n/strings/be.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Add to dictionary": "Дадаць у слоўнік",
|
||||
"The image failed to save": "Не атрымалася захаваць малюнак",
|
||||
"Failed to save image": "Не атрымалася захаваць малюнак",
|
||||
"Save image as...": "Захаваць малюнак як...",
|
||||
"Copy link address": "Скапіраваць спасылку",
|
||||
"Copy email address": "Скапіраваць адрас пошты",
|
||||
"Copy image": "Скапіраваць малюнак",
|
||||
"File": "Файл",
|
||||
"Bring All to Front": "Вынесці ўсё наперад",
|
||||
"Zoom": "Маштаб",
|
||||
"Stop Speaking": "Перастаць гаварыць",
|
||||
"Start Speaking": "Гаварыць",
|
||||
"Speech": "Голас",
|
||||
"Unhide": "Паказаць",
|
||||
"Hide Others": "Схаваць іншыя",
|
||||
"Hide": "Схаваць",
|
||||
"Services": "Сервісы",
|
||||
"About": "Аб праграме",
|
||||
"Element Help": "Даведка Element",
|
||||
"Help": "Даведка",
|
||||
"Close": "Зачыніць",
|
||||
"Minimize": "Згарнуць",
|
||||
"Window": "Акно",
|
||||
"Toggle Developer Tools": "Пераключэнне інструментаў распрацоўніка",
|
||||
"Toggle Full Screen": "Пераключэнне на ўвесь экран",
|
||||
"Preferences": "Параметры",
|
||||
"Zoom Out": "Паменшыць",
|
||||
"Zoom In": "Павялічыць",
|
||||
"Actual Size": "Фактычны Памер",
|
||||
"View": "Прагляд",
|
||||
"Select All": "Выбраць усё",
|
||||
"Delete": "Выдаліць",
|
||||
"Paste and Match Style": "Уставіць і супаставіць стыль",
|
||||
"Paste": "Уставіць",
|
||||
"Copy": "Капіяваць",
|
||||
"Cut": "Выразаць",
|
||||
"Redo": "Паўтарыць",
|
||||
"Undo": "Адмяніць",
|
||||
"Edit": "Змяніць",
|
||||
"Quit": "Выйсці",
|
||||
"Show/Hide": "Паказаць / схаваць",
|
||||
"Are you sure you want to quit?": "Вы ўпэўненыя, што хочаце выйсці?",
|
||||
"Close Element": "Зачыніць Element",
|
||||
"Cancel": "Адмена"
|
||||
}
|
||||
46
src/i18n/strings/ca.json
Normal file
46
src/i18n/strings/ca.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Add to dictionary": "Afegeix al diccionari",
|
||||
"The image failed to save": "S'ha fallat en desar la imatge",
|
||||
"Failed to save image": "S'ha fallat en desar la imatge",
|
||||
"Save image as...": "Anomena i desa la imatge...",
|
||||
"Copy link address": "Copia l'adreça de l'enllaç",
|
||||
"Copy email address": "Copia l'adreça de correu electrònic",
|
||||
"Copy image": "Copia la imatge",
|
||||
"File": "Fitxer",
|
||||
"Bring All to Front": "Porta-ho tot al davant",
|
||||
"Zoom": "Escala",
|
||||
"Stop Speaking": "Para la veu",
|
||||
"Start Speaking": "Comença la veu",
|
||||
"Speech": "Veu",
|
||||
"Unhide": "Deixa d'amagar",
|
||||
"Hide Others": "Amaga les altres",
|
||||
"Hide": "Amaga",
|
||||
"Services": "Serveis",
|
||||
"About": "Quant a",
|
||||
"Element Help": "Ajuda sobre l'Element",
|
||||
"Help": "Ajuda",
|
||||
"Close": "Tanca",
|
||||
"Minimize": "Minimitza",
|
||||
"Window": "Finestra",
|
||||
"Toggle Developer Tools": "Commuta les eines per a desenvolupadors",
|
||||
"Toggle Full Screen": "Commuta la pantalla completa",
|
||||
"Preferences": "Preferències",
|
||||
"Zoom Out": "Allunya",
|
||||
"Zoom In": "Apropia",
|
||||
"Actual Size": "Mida real",
|
||||
"View": "Visualitza",
|
||||
"Select All": "Selecciona-ho tot",
|
||||
"Delete": "Suprimeix",
|
||||
"Paste and Match Style": "Enganxa i fes coincidir l'estil",
|
||||
"Paste": "Enganxa",
|
||||
"Copy": "Copia",
|
||||
"Cut": "Retalla",
|
||||
"Redo": "Refés",
|
||||
"Undo": "Desfés",
|
||||
"Edit": "Edita",
|
||||
"Quit": "Surt",
|
||||
"Show/Hide": "Mostra/Amaga",
|
||||
"Are you sure you want to quit?": "Esteu segur que voleu sortir?",
|
||||
"Close Element": "Tanca l'Element",
|
||||
"Cancel": "Cancel·la"
|
||||
}
|
||||
@@ -26,7 +26,7 @@
|
||||
"Window": "Fenster",
|
||||
"Toggle Developer Tools": "Developer-Tools an/aus",
|
||||
"Toggle Full Screen": "Vollbildschirm an/aus",
|
||||
"Preferences": "Einstellungen",
|
||||
"Preferences": "Präferenzen",
|
||||
"Zoom Out": "Verkleinern",
|
||||
"Zoom In": "Vergrößern",
|
||||
"Actual Size": "Tatsächliche Größe",
|
||||
@@ -42,5 +42,6 @@
|
||||
"Quit": "Beenden",
|
||||
"Show/Hide": "Anzeigen/Ausblenden",
|
||||
"Close Element": "Element schließen",
|
||||
"Cancel": "Abbrechen"
|
||||
"Cancel": "Abbrechen",
|
||||
"Copy image address": "Bild-Adresse kopieren"
|
||||
}
|
||||
|
||||
47
src/i18n/strings/el.json
Normal file
47
src/i18n/strings/el.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Are you sure you want to quit?": "Είστε βέβαιος ότι θέλετε να εγκαταλείψετε;",
|
||||
"Zoom": "Ζουμ",
|
||||
"Unhide": "Εμφάνιση",
|
||||
"Window": "Παράθυρο",
|
||||
"Toggle Developer Tools": "Άνοιγμα Εργαλείων Προγραμματιστή",
|
||||
"Toggle Full Screen": "Εναλλαγή σε Πλήρη Οθόνη",
|
||||
"Copy email address": "Αντιγραφή διεύθυνσης email",
|
||||
"File": "Αρχείο",
|
||||
"Bring All to Front": "Μεταφορά Όλων στο Προσκήνιο",
|
||||
"Stop Speaking": "Τερματίστε να μιλάτε",
|
||||
"Start Speaking": "Ξεκινήστε να μιλάτε",
|
||||
"Speech": "Ομιλία",
|
||||
"Hide Others": "Απόκρυψη Άλλων",
|
||||
"Hide": "Απόκρυψη",
|
||||
"Services": "Υπηρεσίες",
|
||||
"About": "Σχετικά με",
|
||||
"Element Help": "Βοήθεια για το Element",
|
||||
"Help": "Βοήθεια",
|
||||
"Close": "Κλείσιμο",
|
||||
"Minimize": "Ελαχιστοποίηση",
|
||||
"Preferences": "Προτιμήσεις",
|
||||
"Zoom Out": "Σμίκρυνση",
|
||||
"Zoom In": "Μεγέθυνση",
|
||||
"Actual Size": "Πραγματικό Μέγεθος",
|
||||
"View": "Προβολή",
|
||||
"Select All": "Επιλογή Όλων",
|
||||
"Delete": "Διαγραφή",
|
||||
"Paste and Match Style": "Επικόλληση και Ταίριασμα Στυλ",
|
||||
"Paste": "Επικόλληση",
|
||||
"Copy": "Αντιγραφή",
|
||||
"Cut": "Αποκοπή",
|
||||
"Redo": "Επανάληψη",
|
||||
"Undo": "Αναίρεση",
|
||||
"Edit": "Επεξεργασία",
|
||||
"Quit": "Κλείσιμο",
|
||||
"Show/Hide": "Eμφάνιση/Απόκρυψη",
|
||||
"Close Element": "Κλείστε το Element",
|
||||
"Cancel": "Ακύρωση",
|
||||
"Add to dictionary": "Προσθήκη στο λεξικό",
|
||||
"The image failed to save": "Η αποθήκευση της εικόνας απέτυχε",
|
||||
"Failed to save image": "Αποτυχία αποθήκευσης εικόνας",
|
||||
"Save image as...": "Αποθήκευση εικόνας ως...",
|
||||
"Copy link address": "Αντιγραφή διεύθυνσης συνδέσμου",
|
||||
"Copy image address": "Αντιγραφή διεύθυνσης εικόνας",
|
||||
"Copy image": "Αντιγραφή εικόνας"
|
||||
}
|
||||
@@ -38,6 +38,7 @@
|
||||
"File": "File",
|
||||
"Copy image": "Copy image",
|
||||
"Copy email address": "Copy email address",
|
||||
"Copy image address": "Copy image address",
|
||||
"Copy link address": "Copy link address",
|
||||
"Save image as...": "Save image as...",
|
||||
"Failed to save image": "Failed to save image",
|
||||
|
||||
46
src/i18n/strings/en_US.json
Normal file
46
src/i18n/strings/en_US.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Close": "Close",
|
||||
"Add to dictionary": "Add to dictionary",
|
||||
"The image failed to save": "The image failed to save",
|
||||
"Failed to save image": "Failed to save image",
|
||||
"Save image as...": "Save image as...",
|
||||
"Copy link address": "Copy link address",
|
||||
"Copy email address": "Copy email address",
|
||||
"Copy image": "Copy image",
|
||||
"File": "File",
|
||||
"Bring All to Front": "Bring All to Front",
|
||||
"Zoom": "Zoom",
|
||||
"Stop Speaking": "Stop Speaking",
|
||||
"Start Speaking": "Start Speaking",
|
||||
"Speech": "Speech",
|
||||
"Unhide": "Unhide",
|
||||
"Hide Others": "Hide Others",
|
||||
"Hide": "Hide",
|
||||
"Services": "Services",
|
||||
"About": "About",
|
||||
"Element Help": "Element Help",
|
||||
"Help": "Help",
|
||||
"Minimize": "Minimize",
|
||||
"Window": "Window",
|
||||
"Toggle Developer Tools": "Toggle Developer Tools",
|
||||
"Toggle Full Screen": "Toggle Full Screen",
|
||||
"Preferences": "Preferences",
|
||||
"Zoom Out": "Zoom Out",
|
||||
"Zoom In": "Zoom In",
|
||||
"Actual Size": "Actual Size",
|
||||
"View": "View",
|
||||
"Select All": "Select All",
|
||||
"Delete": "Delete",
|
||||
"Paste and Match Style": "Paste and Match Style",
|
||||
"Paste": "Paste",
|
||||
"Copy": "Copy",
|
||||
"Cut": "Cut",
|
||||
"Redo": "Redo",
|
||||
"Undo": "Undo",
|
||||
"Edit": "Edit",
|
||||
"Quit": "Quit",
|
||||
"Show/Hide": "Show/Hide",
|
||||
"Are you sure you want to quit?": "Are you sure you want to quit?",
|
||||
"Close Element": "Close Element",
|
||||
"Cancel": "Cancel"
|
||||
}
|
||||
@@ -42,5 +42,6 @@
|
||||
"Show/Hide": "Ver/Ocultar",
|
||||
"Are you sure you want to quit?": "¿Quieres salir?",
|
||||
"Close Element": "Cerrar Element",
|
||||
"Cancel": "Cancelar"
|
||||
"Cancel": "Cancelar",
|
||||
"Copy image address": "Copiar dirección de la imagen"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,6 @@
|
||||
"Show/Hide": "Näita/peida",
|
||||
"Are you sure you want to quit?": "Kas sa kindlasti soovid rakendusest väljuda?",
|
||||
"Close Element": "Sulge Element",
|
||||
"Cancel": "Tühista"
|
||||
"Cancel": "Tühista",
|
||||
"Copy image address": "Kopeeri pildi aadress"
|
||||
}
|
||||
|
||||
47
src/i18n/strings/fa.json
Normal file
47
src/i18n/strings/fa.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Paste and Match Style": "جایگذاری و تطبیق سَبک",
|
||||
"Add to dictionary": "افزودن به لغتنامه",
|
||||
"The image failed to save": "تصویر ذخیره نشد",
|
||||
"Failed to save image": "ذخیرهٔ تصویر شکست خورد",
|
||||
"Save image as...": "ذخیرهٔ تصویر به عنوان...",
|
||||
"Copy link address": "رونوشت نشانی پیوند",
|
||||
"Copy image address": "رونوشت نشانی تصویر",
|
||||
"Copy email address": "رونوشت نشانی رایانامه",
|
||||
"Copy image": "رونوشت تصویر",
|
||||
"File": "پرونده",
|
||||
"Bring All to Front": "همه را به جلو بیاورید",
|
||||
"Zoom": "بزرگنمایی",
|
||||
"Speech": "صحبت کردن",
|
||||
"Stop Speaking": "صحبت کردن را تمام کنید",
|
||||
"Start Speaking": "صحبت کردن را شروع کنید",
|
||||
"Unhide": "آشکار",
|
||||
"Hide Others": "پنهان کردن دیگران",
|
||||
"Hide": "پنهان",
|
||||
"Services": "خدمات",
|
||||
"About": "درباره",
|
||||
"Element Help": "راهنمای المنت",
|
||||
"Help": "راهنما",
|
||||
"Close": "بستن",
|
||||
"Minimize": "کمینه",
|
||||
"Window": "پنجره",
|
||||
"Toggle Developer Tools": "تغییر وضعیت ابزارهای توسعهدهنده",
|
||||
"Toggle Full Screen": "تغییر وضعیت تمامصفحه",
|
||||
"Preferences": "ترجیحات",
|
||||
"Zoom Out": "بزرگنمایی به خارج",
|
||||
"Zoom In": "بزرگنمایی به داخل",
|
||||
"Actual Size": "اندازهٔ واقعی",
|
||||
"View": "دیدن",
|
||||
"Select All": "گزینش همه",
|
||||
"Delete": "حذف",
|
||||
"Paste": "جایگذاری",
|
||||
"Copy": "رونوشت",
|
||||
"Cut": "برش",
|
||||
"Redo": "انجام دوباره",
|
||||
"Undo": "بازگردانی",
|
||||
"Edit": "ویرایش",
|
||||
"Quit": "خروج",
|
||||
"Show/Hide": "نمایش/پنهان",
|
||||
"Are you sure you want to quit?": "آیا مطمئنید که میخواهید خارج شوید؟",
|
||||
"Close Element": "بستن المنت",
|
||||
"Cancel": "لغو"
|
||||
}
|
||||
@@ -25,7 +25,7 @@
|
||||
"Minimize": "Pienennä",
|
||||
"Window": "Ikkuna",
|
||||
"Toggle Developer Tools": "Näytä tai piilota kehittäjätyökalut",
|
||||
"Toggle Full Screen": "Vaihda koko näyttö-tilaa",
|
||||
"Toggle Full Screen": "Vaihda koko näytön tilaa",
|
||||
"Preferences": "Asetukset",
|
||||
"Zoom Out": "Pienennä",
|
||||
"Zoom In": "Suurenna",
|
||||
@@ -39,8 +39,8 @@
|
||||
"Undo": "Peru",
|
||||
"Edit": "Muokkaa",
|
||||
"Quit": "Lopeta",
|
||||
"Show/Hide": "Näytä/Piilota",
|
||||
"Are you sure you want to quit?": "Oletko varma että haluat poistua?",
|
||||
"Show/Hide": "Näytä/piilota",
|
||||
"Are you sure you want to quit?": "Haluatko varmasti poistua?",
|
||||
"Close Element": "Sulje Element",
|
||||
"Cancel": "Peruuta"
|
||||
}
|
||||
|
||||
46
src/i18n/strings/fy.json
Normal file
46
src/i18n/strings/fy.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Copy image": "Ofbylding kopiearje",
|
||||
"Speech": "Spraak",
|
||||
"View": "Byld",
|
||||
"Paste and Match Style": "Plakke en lit stilen oerienkomme",
|
||||
"Add to dictionary": "Oan wurdlist tafoegje",
|
||||
"The image failed to save": "It is net slagge de ôfbylding te bewarjen",
|
||||
"Failed to save image": "Ofbylding bewarjen mislearre",
|
||||
"Save image as...": "Ofbylding bewarje as…",
|
||||
"Copy link address": "Keppeling kopiearje",
|
||||
"Copy email address": "E-mailadres kopiearje",
|
||||
"File": "Bestân",
|
||||
"Bring All to Front": "Alles nei foaren bringe",
|
||||
"Zoom": "Zoom",
|
||||
"Stop Speaking": "Stopje mei praten",
|
||||
"Start Speaking": "Begjin mei praten",
|
||||
"Unhide": "Wer toane",
|
||||
"Hide Others": "Oare ferbergje",
|
||||
"Hide": "Ferbergje",
|
||||
"Services": "Tsjinsten",
|
||||
"About": "Oer",
|
||||
"Element Help": "Element help",
|
||||
"Help": "Help",
|
||||
"Close": "Slute",
|
||||
"Minimize": "Minimalisearje",
|
||||
"Window": "Finster",
|
||||
"Toggle Developer Tools": "Untwikkelersark yn-/útskeakelje",
|
||||
"Toggle Full Screen": "Folslein skerm yn-/útskeakelje",
|
||||
"Preferences": "Foarkarren",
|
||||
"Zoom Out": "Utzoome",
|
||||
"Zoom In": "Ynzoome",
|
||||
"Actual Size": "Werklike grutte",
|
||||
"Select All": "Alles selektearje",
|
||||
"Delete": "Fuortsmite",
|
||||
"Paste": "Plakke",
|
||||
"Copy": "Kopiearje",
|
||||
"Cut": "Knippe",
|
||||
"Redo": "Opnij útfiere",
|
||||
"Undo": "Ungedien meitsje",
|
||||
"Edit": "Bewurkje",
|
||||
"Quit": "Ofslute",
|
||||
"Show/Hide": "Toane/Ferbergje",
|
||||
"Are you sure you want to quit?": "Binne jo der wis fan dat jo ôfslute wolle?",
|
||||
"Close Element": "Element ôfslute",
|
||||
"Cancel": "Annulearje"
|
||||
}
|
||||
46
src/i18n/strings/he.json
Normal file
46
src/i18n/strings/he.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Actual Size": "גודל ממשי",
|
||||
"Add to dictionary": "הוסף למילון",
|
||||
"The image failed to save": "שמירת התמונה נכשלה",
|
||||
"Failed to save image": "נכשל בשמירת התמונה",
|
||||
"Save image as...": "שמור תמונה בשם...",
|
||||
"Copy link address": "העתק קישור",
|
||||
"Copy email address": "העתק כתובת אימייל",
|
||||
"Copy image": "העתק תמונה",
|
||||
"File": "קובץ",
|
||||
"Bring All to Front": "הבא הכל לחזית",
|
||||
"Zoom": "גודל תצוגה",
|
||||
"Stop Speaking": "הפסק לדבר",
|
||||
"Start Speaking": "התחל לדבר",
|
||||
"Speech": "דיבור",
|
||||
"Unhide": "בטל הסתרה",
|
||||
"Hide Others": "הסתר אחרים",
|
||||
"Hide": "הסתר",
|
||||
"Services": "שרותים",
|
||||
"About": "אודות",
|
||||
"Element Help": "עזרה של אלמנט",
|
||||
"Help": "עזרה",
|
||||
"Close": "סגור",
|
||||
"Minimize": "מזער",
|
||||
"Window": "חלון",
|
||||
"Toggle Developer Tools": "הפעל כלי מפתחים",
|
||||
"Toggle Full Screen": "הפעל מצב מסך מלא",
|
||||
"Preferences": "העדפות",
|
||||
"Zoom Out": "התרחק",
|
||||
"Zoom In": "התקרב",
|
||||
"View": "צפה",
|
||||
"Select All": "בחר הכל",
|
||||
"Delete": "מחק",
|
||||
"Paste": "הדבק",
|
||||
"Copy": "העתק",
|
||||
"Cut": "גזור",
|
||||
"Undo": "בטל ביצוע",
|
||||
"Redo": "בצע שוב",
|
||||
"Edit": "עריכה",
|
||||
"Quit": "יציאה",
|
||||
"Show/Hide": "הצג\\הסתר",
|
||||
"Are you sure you want to quit?": "האם אתה בטוח שברצונך לצאת?",
|
||||
"Close Element": "סגור את אלמנט",
|
||||
"Cancel": "ביטול",
|
||||
"Paste and Match Style": "הדבק והתאם סגנון"
|
||||
}
|
||||
@@ -42,5 +42,6 @@
|
||||
"Show/Hide": "Megmutat/Elrejt",
|
||||
"Are you sure you want to quit?": "Biztos, hogy kilép?",
|
||||
"Close Element": "Element bezárása",
|
||||
"Cancel": "Mégsem"
|
||||
"Cancel": "Mégsem",
|
||||
"Copy image address": "Kép címének másolása"
|
||||
}
|
||||
|
||||
47
src/i18n/strings/id.json
Normal file
47
src/i18n/strings/id.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Add to dictionary": "Tambah ke kamus",
|
||||
"The image failed to save": "Gambar gagal disimpan",
|
||||
"Failed to save image": "Gagal menyimpan gambar",
|
||||
"Save image as...": "Simpan gambar sebagai...",
|
||||
"Copy link address": "Salin alamat tautan",
|
||||
"Copy email address": "Salin surel",
|
||||
"Copy image": "Salin gambar",
|
||||
"File": "File",
|
||||
"Hide Others": "Sembunyikan yang Lain",
|
||||
"Bring All to Front": "Bawa Semua ke Depan",
|
||||
"Zoom": "Perbesar",
|
||||
"Stop Speaking": "Berhenti Berbicara",
|
||||
"Start Speaking": "Mulai Berbicara",
|
||||
"Speech": "Dikte",
|
||||
"Unhide": "Tampilkan",
|
||||
"Hide": "Sembunyikan",
|
||||
"Services": "Layanan",
|
||||
"About": "Tentang",
|
||||
"Element Help": "Bantuan Element",
|
||||
"Help": "Bantuan",
|
||||
"Close": "Tutup",
|
||||
"Minimize": "Minimalkan",
|
||||
"Window": "Jendela",
|
||||
"Toggle Developer Tools": "Beralih Alat Pengembang",
|
||||
"Toggle Full Screen": "Beralih Layar Penuh",
|
||||
"Preferences": "Pengaturan",
|
||||
"Zoom Out": "Perkecil",
|
||||
"Zoom In": "Perbesar",
|
||||
"Cut": "Potong",
|
||||
"Redo": "Ulangi",
|
||||
"Undo": "Urungkan",
|
||||
"Actual Size": "Ukuran Sebenarnya",
|
||||
"View": "Tampilan",
|
||||
"Select All": "Pilih Semua",
|
||||
"Delete": "Hapus",
|
||||
"Paste and Match Style": "Tempel dan Cocokkan Gaya",
|
||||
"Paste": "Tempel",
|
||||
"Copy": "Salin",
|
||||
"Edit": "Edit",
|
||||
"Quit": "Keluar",
|
||||
"Show/Hide": "Tampilkan/Sembunyikan",
|
||||
"Are you sure you want to quit?": "Apakah Anda yakin ingin keluar?",
|
||||
"Close Element": "Tutup Element",
|
||||
"Cancel": "Batal",
|
||||
"Copy image address": "Salin alamat gambar"
|
||||
}
|
||||
@@ -1,37 +1,37 @@
|
||||
{
|
||||
"Add to dictionary": "Bæta við orðabók",
|
||||
"The image failed to save": "Myndin mistóksts að vista",
|
||||
"Add to dictionary": "Bæta við orðasafn",
|
||||
"The image failed to save": "Myndina var ekki hægt að vista",
|
||||
"Failed to save image": "Mistókst að vista mynd",
|
||||
"Save image as...": "Vista mynd sem...",
|
||||
"Copy link address": "Afrita nethlekk",
|
||||
"Copy link address": "Afrita vistfang tengils",
|
||||
"Copy email address": "Afrita tölvupóstfang",
|
||||
"Copy image": "Afrita mynd",
|
||||
"File": "Skrá",
|
||||
"Bring All to Front": "Koma Öllum að Framan",
|
||||
"Bring All to Front": "Setja allt fremst",
|
||||
"Zoom": "Stærð",
|
||||
"Stop Speaking": "Hætta Tal",
|
||||
"Start Speaking": "Byrja Tal",
|
||||
"Stop Speaking": "Hætta tali",
|
||||
"Start Speaking": "Byrja tal",
|
||||
"Speech": "Tal",
|
||||
"Unhide": "Birta",
|
||||
"Hide Others": "Fela Aðra",
|
||||
"Hide Others": "Fela aðra",
|
||||
"Hide": "Fela",
|
||||
"Services": "Þjónustur",
|
||||
"About": "Um",
|
||||
"Element Help": "Element Hjálp",
|
||||
"About": "Um hugbúnaðinn",
|
||||
"Element Help": "Hjálp við Element",
|
||||
"Help": "Hjálp",
|
||||
"Close": "Loka",
|
||||
"Minimize": "Lágmarka",
|
||||
"Window": "Gluggi",
|
||||
"Toggle Developer Tools": "Skipta Framkvæmdaraðilaverkfæri",
|
||||
"Toggle Full Screen": "Skipta um Fullskjá",
|
||||
"Toggle Developer Tools": "Víxla forritunarverkfærum af/á",
|
||||
"Toggle Full Screen": "Víxla fullum skjá af/á",
|
||||
"Preferences": "Stillingar",
|
||||
"Zoom Out": "Minnka",
|
||||
"Zoom In": "Stækka",
|
||||
"Actual Size": "Raunveruleg Stærð",
|
||||
"Actual Size": "Raunstærð",
|
||||
"View": "Skoða",
|
||||
"Select All": "Velja Allt",
|
||||
"Select All": "Velja allt",
|
||||
"Delete": "Eyða",
|
||||
"Paste and Match Style": "Líma og Passa Stíl",
|
||||
"Paste and Match Style": "Líma og samsvara stíl",
|
||||
"Paste": "Líma",
|
||||
"Copy": "Afrita",
|
||||
"Cut": "Klippa",
|
||||
@@ -42,5 +42,6 @@
|
||||
"Show/Hide": "Sýna/Fela",
|
||||
"Are you sure you want to quit?": "Ertu viss um að þú viljir hætta?",
|
||||
"Close Element": "Loka Element",
|
||||
"Cancel": "Hætta við"
|
||||
"Cancel": "Hætta við",
|
||||
"Copy image address": "Afrita slóð myndar"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,6 @@
|
||||
"Close Element": "Chiudi Element",
|
||||
"Cancel": "Annulla",
|
||||
"Stop Speaking": "Smetti di parlare",
|
||||
"Speech": "Dettatura"
|
||||
"Speech": "Dettatura",
|
||||
"Copy image address": "Copia indirizzo immagine"
|
||||
}
|
||||
|
||||
46
src/i18n/strings/lv.json
Normal file
46
src/i18n/strings/lv.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Start Speaking": "Runājiet...",
|
||||
"Add to dictionary": "Pievienot vārdnīcai",
|
||||
"The image failed to save": "Attēlu saglabāt neizdevās",
|
||||
"Failed to save image": "Neizdevās saglabāt attēlu",
|
||||
"Save image as...": "Saglabāt attēlu kā...",
|
||||
"Copy link address": "Kopēt saiti",
|
||||
"Copy email address": "Kopēt e-pastu",
|
||||
"Copy image": "Kopēt attēlu",
|
||||
"File": "Fails",
|
||||
"Bring All to Front": "Iznest visu priekšplānā",
|
||||
"Zoom": "Mērogošana",
|
||||
"Stop Speaking": "Beidziet runāt",
|
||||
"Speech": "Runa",
|
||||
"Unhide": "Rādīt",
|
||||
"Hide Others": "Slēpt citus",
|
||||
"Hide": "Slēpt",
|
||||
"Services": "Servisi/pakalpojumi",
|
||||
"About": "Par programmu",
|
||||
"Element Help": "Element palīdzība",
|
||||
"Help": "Palīdzība",
|
||||
"Close": "Aizvērt",
|
||||
"Minimize": "Minimizēt",
|
||||
"Window": "Logs",
|
||||
"Toggle Developer Tools": "Pārslēgt uz Izstrādātāja rīkiem",
|
||||
"Toggle Full Screen": "Pārslēgt uz pilnekrānu",
|
||||
"Preferences": "Parametri/iestatījumi",
|
||||
"Zoom Out": "Samazināt",
|
||||
"Zoom In": "Palielināt",
|
||||
"Actual Size": "Faktiskais izmērs",
|
||||
"View": "Skats",
|
||||
"Select All": "Atzīmēt visus",
|
||||
"Delete": "Dzēst",
|
||||
"Paste and Match Style": "Ievietot, saglabājot stilu",
|
||||
"Paste": "Ievietot",
|
||||
"Copy": "Kopēt",
|
||||
"Cut": "Izgriezt",
|
||||
"Redo": "Atatdarīt/atatgriezt (redo)",
|
||||
"Undo": "Atgreizt/atdarīt (undo)",
|
||||
"Edit": "Rediģēt",
|
||||
"Quit": "Iziet",
|
||||
"Show/Hide": "Rādīt/nerādīt",
|
||||
"Are you sure you want to quit?": "Tiešām vēlaties iziet?",
|
||||
"Close Element": "Aizvērt Elementu",
|
||||
"Cancel": "Atcelt"
|
||||
}
|
||||
@@ -1,3 +1,37 @@
|
||||
{
|
||||
"Toggle Developer Tools": "Veksle Utvikleralternativer"
|
||||
"Toggle Developer Tools": "Veksle Utvikleralternativer",
|
||||
"Add to dictionary": "Legg til i ordbok",
|
||||
"The image failed to save": "Bildet kunne ikke lagres",
|
||||
"Failed to save image": "Kunne ikke lagre bildet",
|
||||
"Save image as...": "Lagre bildet som...",
|
||||
"Copy email address": "Kopier e-postadressen",
|
||||
"Copy image": "Kopier bildet",
|
||||
"File": "Fil",
|
||||
"Stop Speaking": "Slutt å snakke",
|
||||
"Start Speaking": "Begynn å snakke",
|
||||
"Speech": "Tale",
|
||||
"Hide": "Skjul",
|
||||
"About": "Om",
|
||||
"Element Help": "Element Hjelp",
|
||||
"Help": "Hjelp",
|
||||
"Close": "Lukk",
|
||||
"Minimize": "Minimere",
|
||||
"Window": "Vindu",
|
||||
"Zoom Out": "Zoom ut",
|
||||
"Zoom In": "Zoom inn",
|
||||
"Actual Size": "Faktisk størrelse",
|
||||
"View": "Se",
|
||||
"Select All": "Velg alle",
|
||||
"Delete": "Slett",
|
||||
"Paste": "Lim inn",
|
||||
"Copy": "Kopier",
|
||||
"Undo": "Angre",
|
||||
"Edit": "Rediger",
|
||||
"Quit": "Avslutt",
|
||||
"Show/Hide": "Vis/Skjul",
|
||||
"Are you sure you want to quit?": "Er du sikker på at du vil slutte?",
|
||||
"Close Element": "Lukk Element",
|
||||
"Cancel": "Avbryt",
|
||||
"Services": "Tjenester",
|
||||
"Hide Others": "Skjul Andre"
|
||||
}
|
||||
|
||||
46
src/i18n/strings/nl.json
Normal file
46
src/i18n/strings/nl.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Add to dictionary": "Aan woordenboek toevoegen",
|
||||
"The image failed to save": "De afbeelding opslaan is mislukt",
|
||||
"Failed to save image": "Afbeelding opslaan is mislukt",
|
||||
"Save image as...": "Afbeelding opslaan als...",
|
||||
"Copy link address": "Link kopiëren",
|
||||
"Copy email address": "E-mailadres kopiëren",
|
||||
"Copy image": "Afbeelding kopiëren",
|
||||
"File": "Bestand",
|
||||
"Bring All to Front": "Alles naar voren brengen",
|
||||
"Zoom": "Zoom",
|
||||
"Stop Speaking": "Stop met praten",
|
||||
"Start Speaking": "Begin met praten",
|
||||
"Speech": "Spraak",
|
||||
"Unhide": "Weer laten zien",
|
||||
"Hide Others": "Andere verbergen",
|
||||
"Hide": "Verbergen",
|
||||
"Services": "Diensten",
|
||||
"About": "Over",
|
||||
"Element Help": "Element Help",
|
||||
"Help": "Help",
|
||||
"Close": "Sluiten",
|
||||
"Minimize": "Minimaliseren",
|
||||
"Window": "Venster",
|
||||
"Toggle Developer Tools": "Developer Tools wisselen",
|
||||
"Toggle Full Screen": "Volledig scherm wisselen",
|
||||
"Preferences": "Voorkeuren",
|
||||
"Zoom Out": "Uitzoomen",
|
||||
"Zoom In": "Inzoomen",
|
||||
"Actual Size": "Werkelijke grootte",
|
||||
"View": "Bekijken",
|
||||
"Select All": "Alles selecteren",
|
||||
"Delete": "Verwijderen",
|
||||
"Paste and Match Style": "Plakken zonder stijl",
|
||||
"Paste": "Plakken",
|
||||
"Copy": "Kopiëren",
|
||||
"Cut": "Knippen",
|
||||
"Redo": "Opnieuw doen",
|
||||
"Undo": "Ongedaan maken",
|
||||
"Edit": "Bewerken",
|
||||
"Quit": "Sluiten",
|
||||
"Show/Hide": "Tonen/Verbergen",
|
||||
"Are you sure you want to quit?": "Weet u zeker dat u wilt stoppen?",
|
||||
"Close Element": "Element sluiten",
|
||||
"Cancel": "Annuleren"
|
||||
}
|
||||
46
src/i18n/strings/nn.json
Normal file
46
src/i18n/strings/nn.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"The image failed to save": "Biletet vart ikkje lagra",
|
||||
"Paste and Match Style": "Lim inn og tilpass stil",
|
||||
"Redo": "Gjer om",
|
||||
"Undo": "Angre",
|
||||
"Are you sure you want to quit?": "Er du sikker på at du vil avslutta?",
|
||||
"Add to dictionary": "Legg til i ordlista",
|
||||
"Failed to save image": "Klarte ikkje å lagra biletet",
|
||||
"Save image as...": "Lagre bilete som…",
|
||||
"Copy link address": "Kopier lenkjeadresse",
|
||||
"Copy email address": "Kopier e-postadresse",
|
||||
"Copy image": "Kopier bilete",
|
||||
"File": "Fil",
|
||||
"Bring All to Front": "Plasser lengst fram",
|
||||
"Zoom": "Zoom",
|
||||
"Stop Speaking": "Stopp snakka",
|
||||
"Start Speaking": "Byrja snakka",
|
||||
"Speech": "Tale",
|
||||
"Unhide": "Ikkje gøym",
|
||||
"Hide Others": "Gøym andre",
|
||||
"Hide": "Gøym",
|
||||
"Services": "Tenester",
|
||||
"About": "Om",
|
||||
"Element Help": "Hjelp med Element",
|
||||
"Help": "Hjelp",
|
||||
"Close": "Lat att",
|
||||
"Minimize": "Minimer",
|
||||
"Window": "Vindauga",
|
||||
"Toggle Developer Tools": "Developer Tools av/på",
|
||||
"Toggle Full Screen": "Fullskjerm av/på",
|
||||
"Preferences": "Innstillingar",
|
||||
"Zoom Out": "Zoom ut",
|
||||
"Zoom In": "Zoom inn",
|
||||
"Actual Size": "Faktisk storleik",
|
||||
"View": "Vis",
|
||||
"Select All": "Marker alt",
|
||||
"Delete": "Slett",
|
||||
"Paste": "Lim inn",
|
||||
"Copy": "Lim inn",
|
||||
"Cut": "Klipp ut",
|
||||
"Edit": "Rediger",
|
||||
"Quit": "Avslutt",
|
||||
"Show/Hide": "Vis/Gøym",
|
||||
"Close Element": "Lat att Element",
|
||||
"Cancel": "Avbryt"
|
||||
}
|
||||
46
src/i18n/strings/pl.json
Normal file
46
src/i18n/strings/pl.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Bring All to Front": "Wyciągnij wszystko do przodu",
|
||||
"Add to dictionary": "Dodaj do słownika",
|
||||
"The image failed to save": "Obraz nie został zapisany",
|
||||
"Failed to save image": "Nie udało się zapisać obrazu",
|
||||
"Save image as...": "Zapisz obraz jako...",
|
||||
"Copy link address": "Skopiuj adres łącza",
|
||||
"Copy email address": "Skopiuj adres email",
|
||||
"Copy image": "Skopiuj obraz",
|
||||
"File": "Plik",
|
||||
"Zoom": "Powiększenie",
|
||||
"Stop Speaking": "Przestań mówić",
|
||||
"Start Speaking": "Zacznij mówić",
|
||||
"Speech": "Mowa",
|
||||
"Unhide": "Odkryj",
|
||||
"Hide Others": "Ukryj inne",
|
||||
"Hide": "Ukryj",
|
||||
"Services": "Usługi",
|
||||
"About": "O nas",
|
||||
"Element Help": "Pomoc Element",
|
||||
"Help": "Pomoc",
|
||||
"Close": "Zamknij",
|
||||
"Minimize": "Zminimalizuj",
|
||||
"Window": "Okno",
|
||||
"Toggle Developer Tools": "Przełącz na narzędzia deweloperskie",
|
||||
"Toggle Full Screen": "Przełącz na pełny ekran",
|
||||
"Preferences": "Preferencje",
|
||||
"Zoom Out": "Pomniejsz",
|
||||
"Zoom In": "Powiększ",
|
||||
"Actual Size": "Rzeczywisty rozmiar",
|
||||
"View": "Pokaż",
|
||||
"Select All": "Zaznacz wszystko",
|
||||
"Delete": "Usuń",
|
||||
"Paste and Match Style": "Wklej i dopasuj styl",
|
||||
"Paste": "Wklej",
|
||||
"Copy": "Skopiuj",
|
||||
"Cut": "Wytnij",
|
||||
"Redo": "Powtórz",
|
||||
"Undo": "Cofnij",
|
||||
"Edit": "Edytuj",
|
||||
"Quit": "Zamknij",
|
||||
"Show/Hide": "Pokaż/Ukryj",
|
||||
"Are you sure you want to quit?": "Czy na pewno chcesz zamknąć?",
|
||||
"Close Element": "Zamknij Elementa",
|
||||
"Cancel": "Anuluj"
|
||||
}
|
||||
@@ -42,5 +42,6 @@
|
||||
"Close Element": "Fechar Element",
|
||||
"Cancel": "Cancelar",
|
||||
"Bring All to Front": "Trazer Todas Para Frente",
|
||||
"Hide Others": "Esconder Outras(os)"
|
||||
"Hide Others": "Esconder Outras(os)",
|
||||
"Copy image address": "Copiar endereço de imagem"
|
||||
}
|
||||
|
||||
@@ -1 +1,43 @@
|
||||
{}
|
||||
{
|
||||
"Add to dictionary": "Adăugați la dicționar",
|
||||
"Failed to save image": "Eroare in salvarea imaginii",
|
||||
"Save image as...": "Salvează imagine ca ...",
|
||||
"Copy link address": "Copiază link",
|
||||
"Copy email address": "Copiază adresă de email",
|
||||
"Copy image": "Copiază imagine",
|
||||
"File": "Fișier",
|
||||
"Bring All to Front": "Aduce-ți totul in față",
|
||||
"Zoom": "zoom",
|
||||
"Stop Speaking": "Oprire Voce",
|
||||
"Start Speaking": "Pornire Voce",
|
||||
"Speech": "Voce",
|
||||
"Hide Others": "Ascunde restul",
|
||||
"Hide": "Ascunde",
|
||||
"Services": "Servicii",
|
||||
"About": "Despre",
|
||||
"Element Help": "Ajutor Element",
|
||||
"Help": "Ajutor",
|
||||
"Close": "Inchide",
|
||||
"Minimize": "Minimizare",
|
||||
"Window": "Fereastră",
|
||||
"Toggle Developer Tools": "Comutare unelte dezvoltator",
|
||||
"Toggle Full Screen": "Comutare pe tot ecranul",
|
||||
"Preferences": "Preferințe",
|
||||
"Zoom Out": "Micșorează",
|
||||
"Zoom In": "Mărește",
|
||||
"Actual Size": "Mărime reală",
|
||||
"View": "Vizualizează",
|
||||
"Select All": "Selectează tot",
|
||||
"Delete": "Șterge",
|
||||
"Paste and Match Style": "Lipește si potrivește stilul",
|
||||
"Paste": "Lipește",
|
||||
"Copy": "Copiere",
|
||||
"Redo": "Refă",
|
||||
"Undo": "Anulare",
|
||||
"Edit": "Editare",
|
||||
"Quit": "Închide",
|
||||
"Show/Hide": "Arată/Ascunde",
|
||||
"Are you sure you want to quit?": "Sunte-ți sigur ca doriți sa inchideți aplicația ?",
|
||||
"Close Element": "închide aplicația",
|
||||
"Cancel": "Anulare"
|
||||
}
|
||||
|
||||
@@ -42,5 +42,6 @@
|
||||
"Start Speaking": "Говорите",
|
||||
"Speech": "Голос",
|
||||
"Hide Others": "Скрыть прочие",
|
||||
"Paste and Match Style": "Вставить с тем же стилем"
|
||||
"Paste and Match Style": "Вставить с тем же стилем",
|
||||
"Copy image address": "Копировать адрес изображения"
|
||||
}
|
||||
|
||||
31
src/i18n/strings/si.json
Normal file
31
src/i18n/strings/si.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"Show/Hide": "පෙන්වන්න/සඟවන්න",
|
||||
"Are you sure you want to quit?": "ඔබට ඉවත් වීමට අවශ්ය බව විශ්වාස ද?",
|
||||
"Close Element": "ඉලමෙන්ට් වසන්න",
|
||||
"Cancel": "අවලංගු කරන්න",
|
||||
"Add to dictionary": "ශබ්ද කෝෂයට එකතු කරන්න",
|
||||
"Copy link address": "සබැඳියේ ලිපිනය පිටපත් කරන්න",
|
||||
"Copy email address": "වි-තැපෑල පිටපත් කරන්න",
|
||||
"File": "ගොනුව",
|
||||
"Zoom": "විශාල කරන්න",
|
||||
"Hide Others": "වෙනත් දෑ සඟවන්න",
|
||||
"Hide": "සඟවන්න",
|
||||
"Services": "සේවා",
|
||||
"About": "පිළිබඳව",
|
||||
"Element Help": "ඉලමෙන්ට් උපකාර",
|
||||
"Help": "උපකාර",
|
||||
"Close": "වසන්න",
|
||||
"Minimize": "හකුලන්න",
|
||||
"Window": "කවුළුව",
|
||||
"Zoom Out": "කුඩාලනය කරන්න",
|
||||
"Zoom In": "විශාලනය කරන්න",
|
||||
"Actual Size": "සැබෑ ප්රමාණය",
|
||||
"Select All": "සියල්ල තෝරන්න",
|
||||
"Paste": "අලවන්න",
|
||||
"Copy": "පිටපත්",
|
||||
"Cut": "කපන්න",
|
||||
"Redo": "පසුසේ",
|
||||
"Undo": "පෙරසේ",
|
||||
"Edit": "සංස්කරණය",
|
||||
"Quit": "ඉවත් වන්න"
|
||||
}
|
||||
47
src/i18n/strings/sk.json
Normal file
47
src/i18n/strings/sk.json
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"Unhide": "Odkryť",
|
||||
"Stop Speaking": "Zastaviť nahrávanie hlasu",
|
||||
"Start Speaking": "Spustiť nahrávanie hlasu",
|
||||
"Speech": "Reč",
|
||||
"Element Help": "Pomocník pre aplikáciu Element",
|
||||
"Paste and Match Style": "Vložiť a prispôsobiť štýl",
|
||||
"Close Element": "Zavrieť aplikáciu Element",
|
||||
"Add to dictionary": "Pridať do slovníka",
|
||||
"The image failed to save": "Obrázok sa nepodarilo uložiť",
|
||||
"Failed to save image": "Chyba pri ukladaní obrázka",
|
||||
"Save image as...": "Uložiť obrázok ako...",
|
||||
"Copy link address": "Kopírovať adresu odkazu",
|
||||
"Copy email address": "Kopírovať e-mailovú adresu",
|
||||
"Copy image": "Kopírovať obrázok",
|
||||
"File": "Súbor",
|
||||
"Bring All to Front": "Preniesť všetky do popredia",
|
||||
"Zoom": "Lupa",
|
||||
"Hide Others": "Skryť ostatné",
|
||||
"Hide": "Skryť",
|
||||
"Services": "Služby",
|
||||
"About": "O aplikácii",
|
||||
"Help": "Pomocník",
|
||||
"Close": "Zavrieť",
|
||||
"Minimize": "Minimalizovať",
|
||||
"Window": "Okno",
|
||||
"Toggle Developer Tools": "Nástroje pre vývojárov",
|
||||
"Toggle Full Screen": "Celá obrazovka",
|
||||
"Preferences": "Vlastnosti",
|
||||
"Zoom Out": "Oddialiť",
|
||||
"Zoom In": "Priblížiť",
|
||||
"Actual Size": "Aktuálna veľkosť",
|
||||
"View": "Zobraziť",
|
||||
"Select All": "Vybrať všetko",
|
||||
"Delete": "Odstrániť",
|
||||
"Paste": "Vložiť",
|
||||
"Copy": "Kopírovať",
|
||||
"Cut": "Vystrihnúť",
|
||||
"Redo": "Opakovať",
|
||||
"Undo": "Späť",
|
||||
"Edit": "Úpravy",
|
||||
"Quit": "Ukončiť",
|
||||
"Show/Hide": "Zobraziť/Skryť",
|
||||
"Are you sure you want to quit?": "Naozaj chcete zavrieť aplikáciu?",
|
||||
"Cancel": "Zrušiť",
|
||||
"Copy image address": "Kopírovať adresu obrázka"
|
||||
}
|
||||
46
src/i18n/strings/tr.json
Normal file
46
src/i18n/strings/tr.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Add to dictionary": "Sözlüğe ekle",
|
||||
"The image failed to save": "Bu resim kaydedilemedi",
|
||||
"Failed to save image": "Resim kaydedilemedi",
|
||||
"Save image as...": "Resmi ... olarak farklı kaydet",
|
||||
"Copy link address": "Bağlantılı adresi kopyala",
|
||||
"Copy email address": "E-posta adresini kopyala",
|
||||
"Copy image": "Resmi kopyala",
|
||||
"File": "Dosya",
|
||||
"Bring All to Front": "Hepsini öne getir",
|
||||
"Zoom": "Yaklaştır",
|
||||
"Stop Speaking": "Konuşmayı durdur",
|
||||
"Start Speaking": "Konuşmaya başla",
|
||||
"Speech": "Konuşma",
|
||||
"Unhide": "Gizlemeyi bırak",
|
||||
"Hide Others": "Diğerlerini gizle",
|
||||
"Hide": "Gizle",
|
||||
"Services": "Hizmetler",
|
||||
"About": "Hakkında",
|
||||
"Element Help": "Element yardımı",
|
||||
"Help": "Yardım",
|
||||
"Close": "Kapat",
|
||||
"Minimize": "Küçült",
|
||||
"Window": "Pencere",
|
||||
"Toggle Developer Tools": "Geliştirici araçları",
|
||||
"Toggle Full Screen": "Tam ekran",
|
||||
"Preferences": "Tercihler",
|
||||
"Zoom Out": "Uzaklaştır",
|
||||
"Zoom In": "Yaklaştır",
|
||||
"Actual Size": "Gerçek boyut",
|
||||
"View": "Görünüm",
|
||||
"Select All": "Tümünü seç",
|
||||
"Delete": "Sil",
|
||||
"Paste and Match Style": "Biçimiyle bir yapıştır",
|
||||
"Paste": "Yapıştır",
|
||||
"Copy": "Kopyala",
|
||||
"Cut": "Kes",
|
||||
"Redo": "Yinele",
|
||||
"Undo": "Geri al",
|
||||
"Edit": "Düzenle",
|
||||
"Quit": "Çık",
|
||||
"Show/Hide": "Göster/Gizle",
|
||||
"Are you sure you want to quit?": "Çıkmak istediğinize emin misiniz?",
|
||||
"Close Element": "Element'i kapat",
|
||||
"Cancel": "İptal"
|
||||
}
|
||||
46
src/i18n/strings/vi.json
Normal file
46
src/i18n/strings/vi.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Add to dictionary": "Thêm vào từ điển",
|
||||
"The image failed to save": "Ảnh không lưu được",
|
||||
"Failed to save image": "Lưu ảnh thất bại",
|
||||
"Save image as...": "Lưu ảnh…",
|
||||
"Copy link address": "Sao chép địa chỉ liên kết",
|
||||
"Copy email address": "Sao chép địa chỉ email",
|
||||
"Copy image": "Sao chép ảnh",
|
||||
"File": "Tệp",
|
||||
"Bring All to Front": "Đưa tất cả lên trước",
|
||||
"Zoom": "Thu phóng",
|
||||
"Stop Speaking": "Dừng nói",
|
||||
"Start Speaking": "Bắt đầu nói",
|
||||
"Speech": "Đọc màn hình",
|
||||
"Unhide": "Bỏ ẩn",
|
||||
"Hide Others": "Ẩn cái khác",
|
||||
"Hide": "Ẩn",
|
||||
"Services": "Dịch vụ",
|
||||
"About": "Giới thiệu",
|
||||
"Element Help": "Trợ giúp Element",
|
||||
"Help": "Hỗ trợ",
|
||||
"Close": "Đóng",
|
||||
"Minimize": "Thu nhỏ",
|
||||
"Window": "Cửa sổ",
|
||||
"Toggle Developer Tools": "Công cụ cho Nhà phát triển",
|
||||
"Toggle Full Screen": "Toàn màn hình",
|
||||
"Preferences": "Tùy chọn",
|
||||
"Zoom Out": "Thu nhỏ",
|
||||
"Zoom In": "Phóng to",
|
||||
"Actual Size": "Kích thước thực",
|
||||
"View": "Xem",
|
||||
"Select All": "Chọn tất cả",
|
||||
"Delete": "Xóa",
|
||||
"Paste and Match Style": "Dán và khớp kiểu",
|
||||
"Paste": "Dán",
|
||||
"Copy": "Sao chép",
|
||||
"Cut": "Cắt",
|
||||
"Redo": "Làm lại",
|
||||
"Undo": "Hoàn tác",
|
||||
"Edit": "Chỉnh sửa",
|
||||
"Quit": "Thoát",
|
||||
"Show/Hide": "Hiển thị/Ẩn",
|
||||
"Are you sure you want to quit?": "Bạn có chắc chắn muốn thoát?",
|
||||
"Close Element": "Đóng Element",
|
||||
"Cancel": "Hủy bỏ"
|
||||
}
|
||||
46
src/i18n/strings/zh_Hant.json
Normal file
46
src/i18n/strings/zh_Hant.json
Normal file
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"Bring All to Front": "全部移至最前",
|
||||
"Add to dictionary": "加入至字典",
|
||||
"The image failed to save": "儲存圖片失敗",
|
||||
"Failed to save image": "儲存圖片失敗",
|
||||
"Save image as...": "另存圖片為...",
|
||||
"Copy link address": "複製連結",
|
||||
"Copy email address": "複製電子郵件地址",
|
||||
"Copy image": "複製圖片",
|
||||
"File": "檔案",
|
||||
"Zoom": "縮放",
|
||||
"Stop Speaking": "停止說話",
|
||||
"Start Speaking": "開始說話",
|
||||
"Speech": "語音",
|
||||
"Unhide": "取消隱藏",
|
||||
"Hide Others": "隱藏其他",
|
||||
"Hide": "隱藏",
|
||||
"Services": "服務",
|
||||
"About": "關於",
|
||||
"Element Help": "Element 協助",
|
||||
"Help": "協助",
|
||||
"Close": "關閉",
|
||||
"Minimize": "最小化",
|
||||
"Window": "視窗",
|
||||
"Toggle Developer Tools": "切換開發工具",
|
||||
"Toggle Full Screen": "切換全螢幕",
|
||||
"Preferences": "偏好設定",
|
||||
"Zoom Out": "縮小",
|
||||
"Zoom In": "放大",
|
||||
"Actual Size": "實際大小",
|
||||
"View": "檢視",
|
||||
"Select All": "全選",
|
||||
"Delete": "刪除",
|
||||
"Paste and Match Style": "貼上並保留格式",
|
||||
"Paste": "貼上",
|
||||
"Copy": "複製",
|
||||
"Cut": "剪下",
|
||||
"Redo": "取消復原",
|
||||
"Undo": "復原",
|
||||
"Edit": "編輯",
|
||||
"Quit": "退出",
|
||||
"Show/Hide": "顯示/隱藏",
|
||||
"Are you sure you want to quit?": "您確定要退出嗎?",
|
||||
"Close Element": "關閉 Element",
|
||||
"Cancel": "取消"
|
||||
}
|
||||
@@ -15,6 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import counterpart from "counterpart";
|
||||
|
||||
import type Store from 'electron-store';
|
||||
|
||||
const DEFAULT_LOCALE = "en";
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { ipcRenderer, desktopCapturer, contextBridge, IpcRendererEvent, SourcesOptions } from 'electron';
|
||||
import { ipcRenderer, contextBridge, IpcRendererEvent } from 'electron';
|
||||
|
||||
// Expose only expected IPC wrapper APIs to the renderer process to avoid
|
||||
// handing out generalised messaging access.
|
||||
@@ -33,15 +33,9 @@ const CHANNELS = [
|
||||
"setBadgeCount",
|
||||
"update-downloaded",
|
||||
"userDownloadCompleted",
|
||||
"userDownloadOpen",
|
||||
"userDownloadAction",
|
||||
];
|
||||
|
||||
interface ISource {
|
||||
id: string;
|
||||
name: string;
|
||||
thumbnailURL: string;
|
||||
}
|
||||
|
||||
contextBridge.exposeInMainWorld(
|
||||
"electron",
|
||||
{
|
||||
@@ -59,19 +53,5 @@ contextBridge.exposeInMainWorld(
|
||||
}
|
||||
ipcRenderer.send(channel, ...args);
|
||||
},
|
||||
async getDesktopCapturerSources(options: SourcesOptions): Promise<ISource[]> {
|
||||
const sources = await desktopCapturer.getSources(options);
|
||||
const desktopCapturerSources: ISource[] = [];
|
||||
|
||||
for (const source of sources) {
|
||||
desktopCapturerSources.push({
|
||||
id: source.id,
|
||||
name: source.name,
|
||||
thumbnailURL: source.thumbnail.toDataURL(),
|
||||
});
|
||||
}
|
||||
|
||||
return desktopCapturerSources;
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
@@ -19,7 +19,7 @@ import { URL } from "url";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
const PROTOCOL = "element://";
|
||||
const PROTOCOL = "element:";
|
||||
const SEARCH_PARAM = "element-desktop-ssoid";
|
||||
const STORE_FILE_NAME = "sso-sessions.json";
|
||||
|
||||
@@ -28,8 +28,28 @@ const storePath = path.join(app.getPath("userData"), STORE_FILE_NAME);
|
||||
|
||||
function processUrl(url: string): void {
|
||||
if (!global.mainWindow) return;
|
||||
console.log("Handling link: ", url);
|
||||
global.mainWindow.loadURL(url.replace(PROTOCOL, "vector://"));
|
||||
|
||||
const parsed = new URL(url);
|
||||
// sanity check: we only register for the one protocol, so we shouldn't
|
||||
// be getting anything else unless the user is forcing a URL to open
|
||||
// with the Element app.
|
||||
if (parsed.protocol !== PROTOCOL) {
|
||||
console.log("Ignoring unexpected protocol: ", parsed.protocol);
|
||||
return;
|
||||
}
|
||||
|
||||
const urlToLoad = new URL("vector://vector/webapp/");
|
||||
// ignore anything other than the search (used for SSO login redirect)
|
||||
// and the hash (for general element deep links)
|
||||
// There's no reason to allow anything else, particularly other paths,
|
||||
// since this would allow things like the internal jitsi wrapper to
|
||||
// be loaded, which would get the app stuck on that page and generally
|
||||
// be a bit strange and confusing.
|
||||
urlToLoad.search = parsed.search;
|
||||
urlToLoad.hash = parsed.hash;
|
||||
|
||||
console.log("Opening URL: ", urlToLoad.href);
|
||||
global.mainWindow.loadURL(urlToLoad.href);
|
||||
}
|
||||
|
||||
function readStore(): object {
|
||||
@@ -62,10 +82,10 @@ export function recordSSOSession(sessionID: string): void {
|
||||
|
||||
export function getProfileFromDeeplink(args): string | undefined {
|
||||
// check if we are passed a profile in the SSO callback url
|
||||
const deeplinkUrl = args.find(arg => arg.startsWith('element://'));
|
||||
const deeplinkUrl = args.find(arg => arg.startsWith(PROTOCOL + '//'));
|
||||
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
|
||||
const parsedUrl = new URL(deeplinkUrl);
|
||||
if (parsedUrl.protocol === 'element:') {
|
||||
if (parsedUrl.protocol === PROTOCOL) {
|
||||
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM);
|
||||
const store = readStore();
|
||||
console.log("Forwarding to profile: ", store[ssoID]);
|
||||
@@ -96,7 +116,7 @@ export function protocolInit(): void {
|
||||
// Protocol handler for win32/Linux
|
||||
app.on('second-instance', (ev, commandLine) => {
|
||||
const url = commandLine[commandLine.length - 1];
|
||||
if (!url.startsWith(PROTOCOL)) return;
|
||||
if (!url.startsWith(PROTOCOL + '//')) return;
|
||||
processUrl(url);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -28,20 +28,18 @@ function runUpdateExe(args: string[]): Promise<void> {
|
||||
console.log(`Spawning '${updateExe}' with args '${args}'`);
|
||||
return new Promise(resolve => {
|
||||
spawn(updateExe, args, {
|
||||
detached: true,
|
||||
detached: true,
|
||||
}).on('close', resolve);
|
||||
});
|
||||
}
|
||||
|
||||
export function checkSquirrelHooks(): boolean {
|
||||
function checkSquirrelHooks(): boolean {
|
||||
if (process.platform !== 'win32') return false;
|
||||
|
||||
const cmd = process.argv[1];
|
||||
const target = path.basename(process.execPath);
|
||||
if (cmd === '--squirrel-install' || cmd === '--squirrel-updated') {
|
||||
Promise.resolve().then(() => {
|
||||
return runUpdateExe(['--createShortcut=' + target]);
|
||||
}).then(() => {
|
||||
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)
|
||||
@@ -82,3 +80,7 @@ export function checkSquirrelHooks(): boolean {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (checkSquirrelHooks()) {
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import { app, Tray, Menu, nativeImage } from "electron";
|
||||
import pngToIco from "png-to-ico";
|
||||
import path from "path";
|
||||
import fs from "fs";
|
||||
|
||||
import { _t } from "./language-helper";
|
||||
|
||||
let trayIcon: Tray = null;
|
||||
@@ -35,7 +36,7 @@ export function destroy(): void {
|
||||
}
|
||||
|
||||
function toggleWin(): void {
|
||||
if (global.mainWindow.isVisible() && !global.mainWindow.isMinimized()) {
|
||||
if (global.mainWindow.isVisible() && !global.mainWindow.isMinimized() && global.mainWindow.isFocused()) {
|
||||
global.mainWindow.hide();
|
||||
} else {
|
||||
if (global.mainWindow.isMinimized()) global.mainWindow.restore();
|
||||
|
||||
@@ -52,7 +52,7 @@ export function start(updateBaseUrl: string): void {
|
||||
// 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/${process.arch}/?localVersion=${encodeURIComponent(app.getVersion())}`;
|
||||
url = `${updateBaseUrl}macos/?localVersion=${encodeURIComponent(app.getVersion())}`;
|
||||
} else if (process.platform === 'win32') {
|
||||
url = `${updateBaseUrl}win32/${process.arch}/`;
|
||||
} else {
|
||||
|
||||
@@ -15,6 +15,7 @@ limitations under the License.
|
||||
*/
|
||||
|
||||
import { app, shell, Menu, MenuItem, MenuItemConstructorOptions } from 'electron';
|
||||
|
||||
import { _t } from './language-helper';
|
||||
|
||||
const isMac = process.platform === 'darwin';
|
||||
|
||||
@@ -33,6 +33,7 @@ import url from 'url';
|
||||
import fs from 'fs';
|
||||
import request from 'request';
|
||||
import path from 'path';
|
||||
|
||||
import { _t } from './language-helper';
|
||||
|
||||
const MAILTO_PREFIX = "mailto:";
|
||||
@@ -124,7 +125,9 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
}));
|
||||
} else {
|
||||
popupMenu.append(new MenuItem({
|
||||
label: _t('Copy link address'),
|
||||
label: params.hasImageContents
|
||||
? _t('Copy image address')
|
||||
: _t('Copy link address'),
|
||||
accelerator: 'a',
|
||||
click() {
|
||||
clipboard.writeText(url);
|
||||
@@ -245,8 +248,13 @@ function onEditableContextMenu(ev: Event, params: ContextMenuParams) {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
ipcMain.on('userDownloadOpen', function(ev: IpcMainEvent, { path }) {
|
||||
shell.openPath(path);
|
||||
let userDownloadIndex = 0;
|
||||
const userDownloadMap = new Map<number, string>(); // Map from id to path
|
||||
ipcMain.on('userDownloadAction', function(ev: IpcMainEvent, { id, open = false }) {
|
||||
if (open) {
|
||||
shell.openPath(userDownloadMap.get(id));
|
||||
}
|
||||
userDownloadMap.delete(id);
|
||||
});
|
||||
|
||||
export default (webContents: WebContents): void => {
|
||||
@@ -270,8 +278,10 @@ export default (webContents: WebContents): void => {
|
||||
item.once('done', (event, state) => {
|
||||
if (state === 'completed') {
|
||||
const savePath = item.getSavePath();
|
||||
const id = userDownloadIndex++;
|
||||
userDownloadMap.set(id, savePath);
|
||||
webContents.send('userDownloadCompleted', {
|
||||
path: savePath,
|
||||
id,
|
||||
name: path.basename(savePath),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -10,9 +10,6 @@
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
"declaration": true,
|
||||
"types": [
|
||||
"node"
|
||||
],
|
||||
"lib": [
|
||||
"es2019",
|
||||
"dom"
|
||||
|
||||
Reference in New Issue
Block a user