Compare commits

...

65 Commits

Author SHA1 Message Date
Michael Telatynski
9f00594ae3 Attempt to kill off hak
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-28 14:13:58 +00:00
Michael Telatynski
02c23e87b5 Update imports
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-28 13:28:27 +00:00
Michael Telatynski
3e7b10894a Merge remote-tracking branch 'origin/t3chguy/keytar-forked' into t3chguy/keytar-forked 2025-02-28 13:23:44 +00:00
Michael Telatynski
be9214fe0b Merge branch 't3chguy/keytar-no-hak' of https://github.com/vector-im/element-desktop into t3chguy/keytar-forked
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

# Conflicts:
#	hak/keytar-forked/build.ts
#	hak/keytar-forked/check.ts
#	hak/keytar-forked/hak.json
#	package.json
#	src/@types/keytar.d.ts
#	src/keytar.ts
2025-02-28 13:23:38 +00:00
Michael Telatynski
2219ca9ca3 Merge branch 'develop' into t3chguy/keytar-no-hak 2025-02-28 13:20:13 +00:00
Michael Telatynski
e4dac2a210 Iterate
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-28 12:33:47 +00:00
Michael Telatynski
36446c108b Merge branch 'develop' into t3chguy/keytar-forked 2025-02-28 12:30:46 +00:00
Michael Telatynski
5ee122cdae Add logging
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-28 12:14:10 +00:00
Michael Telatynski
ff7f53fb35 Use modern Dockerfile env format to silence warnings (#2171) 2025-02-28 11:39:31 +00:00
Michael Telatynski
bce251b35b Update node engines, 23.x is broken too 2025-02-28 11:17:07 +00:00
Michael Telatynski
fde278d5b5 Leverage electron-builder to build keytar rather than hak
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-28 11:15:42 +00:00
Michael Telatynski
08b61a7e3a Iterate
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-28 11:02:02 +00:00
Michael Telatynski
6ae09710c6 Test keytar-forked
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-28 10:59:16 +00:00
Michael Telatynski
a46985d91e Specify node version to avoid NAPI keytar bug (#2168) 2025-02-28 10:23:49 +00:00
Michael Telatynski
a546b28c62 Pin Node to 22.13.1 for Windows build (#2166) 2025-02-27 18:55:57 +00:00
RiotRobot
9a785738df Merge branch 'master' into develop 2025-02-27 13:31:22 +00:00
RiotRobot
6be60b69e6 v1.11.94 2025-02-27 13:30:48 +00:00
renovate[bot]
ea8bd4e062 Update electron-builder to v26.0.8 (#2159)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-25 18:21:27 +00:00
RiotRobot
37ec2b9f34 Merge branch 'master' into develop 2025-02-25 13:41:26 +00:00
RiotRobot
8ee1a04592 v1.11.93 2025-02-25 13:40:50 +00:00
Michael Telatynski
573c7d4522 Update release.yml permissions 2025-02-25 13:20:10 +00:00
Michael Telatynski
64e5a424ca Add set -x to bash for introspection build_and_deploy.yaml 2025-02-24 15:24:44 +00:00
Michael Telatynski
a02fad52bb Fix macOS nightly builds (#2158) 2025-02-24 14:54:20 +00:00
Michael Telatynski
eb3ae80142 Update triage-stale.yml 2025-02-24 10:37:04 +00:00
Michael Telatynski
12b287d639 Update triage-stale.yml 2025-02-24 10:35:29 +00:00
renovate[bot]
8f31f2ff57 Update all non-major dependencies (#2154)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-19 22:38:30 +00:00
Michael Telatynski
8f464b9450 Improve CI test signing & assert expected files (#2137) 2025-02-19 14:34:43 +00:00
Michael Telatynski
b8bb4d3316 Add Windows ARM 64 package (#624)
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-19 10:35:53 +00:00
Michael Telatynski
00f08cb443 Simplify CI workflows (#2153)
* Simplify CI workflows

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Simplify further

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Tidy

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-19 10:02:49 +00:00
renovate[bot]
6fb5202e86 Update docker (#2142)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-18 18:01:11 +00:00
renovate[bot]
e7cda8ee4e Update electron-builder to v26.0.7 (#2146)
* Update electron-builder to v26.0.6

* Update electron-builder to 26.0.7

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-18 17:43:51 +00:00
renovate[bot]
c4cddd3591 Update typescript-eslint monorepo to v8.24.0 (#2150)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 15:46:48 +00:00
renovate[bot]
f23b279633 Update electron (#2149)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 14:50:13 +00:00
renovate[bot]
4302d6106e Update dependency @types/node to v18.19.76 (#2145)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 14:49:48 +00:00
renovate[bot]
3c4138326b Update babel monorepo to v7.26.9 (#2144)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 14:49:28 +00:00
renovate[bot]
bf141856d7 Update dependency @stylistic/eslint-plugin to v3.1.0 (#2148)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 14:48:39 +00:00
renovate[bot]
da3698f6d5 Update all non-major dependencies (#2147)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 14:48:13 +00:00
renovate[bot]
c1f55a64a8 Update tj-actions/changed-files digest to dcc7a0c (#2143)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-18 14:34:45 +00:00
RiotRobot
57aa266320 v1.11.93-rc.0 2025-02-18 13:17:21 +00:00
ElementRobot
81f76fe574 Merge pull request #2138 from element-hq/actions/localazy-download
Localazy Download
2025-02-14 07:33:09 +01:00
t3chguy
af7e8a7e0f [create-pull-request] automated change 2025-02-14 06:06:20 +00:00
RiotRobot
35907d14c8 Merge branch 'master' into develop 2025-02-11 14:43:03 +00:00
Michael Telatynski
746aedab75 Test windows signing in CI (#2131)
* Test windows signing in CI

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Of course powershell is special

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-11 09:30:35 +00:00
Michael Telatynski
71154d6c9b Turn off electron-builder debug
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 17:43:53 +00:00
Michael Telatynski
f31710dd91 Roll back electron-builder to 26.0.1 to un-break windows code signing
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 17:41:41 +00:00
Michael Telatynski
3cad0d4438 Try passing WINDOWS_SIGN_WITH_PARAMS manually
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 17:28:20 +00:00
Michael Telatynski
392c66fedf Merge remote-tracking branch 'origin/develop' into develop 2025-02-07 16:52:39 +00:00
Michael Telatynski
156942caf9 Disable WINDOWS_SIGNTOOL_PATH for debugging
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 16:52:32 +00:00
Michael Telatynski
b0f4bc4e0c Close stale PRs after 180 days (#2130)
* Close stale PRs after 180 days

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Update triage-stale.yml

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 13:45:12 +00:00
Michael Telatynski
2ff445cf7b DEBUG electron builder windows signing
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 13:23:01 +00:00
Michael Telatynski
70f84181d2 Attempt to fix electron-winstaller 2025-02-07 10:21:50 +00:00
Michael Telatynski
3b4c6d43d4 Update electron-clear-data to @standardnotes/electron-clear-data (#2128)
Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-07 09:05:36 +00:00
renovate[bot]
e5bf3f1f69 Update electron-builder to v26.0.2 (#2113)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-06 23:54:00 +00:00
Michael Telatynski
5c6e0f14d0 Simplify linux builds (#2122)
* Simplify linux builds

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Try RUNNER_TEMP

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Try APP_BUILDER_TMP_DIR

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Try runner.temp instead

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Perms?

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Add workaround for https://github.com/electron-userland/electron-builder/issues/6116

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

* Iterate

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-06 10:25:02 +00:00
renovate[bot]
3e98c2c525 Update dependency eslint-plugin-matrix-org to v2.1.0 (#2121)
* Update dependency eslint-plugin-matrix-org to v2.1.0

* Delint

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>

---------

Signed-off-by: Michael Telatynski <7t3chguy@gmail.com>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-05 09:40:22 +00:00
renovate[bot]
6d0deb0a94 Update electron (#2115)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-02-04 15:46:54 +00:00
renovate[bot]
f0c98d07e9 Update typescript-eslint monorepo to v8.22.0 (#2117)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 15:03:39 +00:00
renovate[bot]
c433a33857 Update all non-major dependencies (#2114)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 14:43:38 +00:00
renovate[bot]
b6f93956bf Update dependency @stylistic/eslint-plugin to v3 (#2119)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 14:35:56 +00:00
renovate[bot]
325bcacf69 Update playwright to v1.50.1 (#2116)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 14:18:07 +00:00
renovate[bot]
28ae8f8a76 Update dependency @types/node to v18.19.74 (#2112)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 14:05:39 +00:00
renovate[bot]
0f157e656b Update babel monorepo to v7.26.7 (#2111)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 14:02:03 +00:00
renovate[bot]
289c3861bd Update docker/build-push-action digest to ca877d9 (#2110)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-02-04 14:01:46 +00:00
David Langley
3e3bad3697 Merge pull request #2109 from element-hq/langleyd/update_package_description
Update package description
2025-02-04 13:10:12 +00:00
David Langley
42f99d9088 Update package.json 2025-02-04 10:41:34 +00:00
59 changed files with 1530 additions and 2306 deletions

35
.github/SSLcom-sandbox.crt vendored Normal file
View File

@@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGBzCCA++gAwIBAgIIaI6ivggL++4wDQYJKoZIhvcNAQELBQAwgZAxCzAJBgNV
BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
CgwPU1NMIENvcnBvcmF0aW9uMUUwQwYDVQQDDDxTU0wuY29tIEVWIFJvb3QgQ2Vy
dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyIC0gRGV2ZWxvcG1lbnQwHhcNMTgw
MTE2MTIxNjM2WhcNNDMwMTE1MTIxNjM2WjCBkDELMAkGA1UEBhMCVVMxDjAMBgNV
BAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9TU0wgQ29ycG9y
YXRpb24xRTBDBgNVBAMMPFNTTC5jb20gRVYgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1
dGhvcml0eSBSU0EgUjIgLSBEZXZlbG9wbWVudDCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAK/qcD65JCkueKp0+KXG2kAw8euDHuraLR3lJoUFz4ilGK1M
t+RjSuY6dHQw8ku7TnW9ejWoSFjCBSDx7tP/fzOwOxmBW6+F1NDuV/IaUtn3G2lk
CZglVk9z3n1HuWDN10xNiLoo5nzeIlvNAoDbXDGhI4Y6Z0qouAIS607JpJMWHOqZ
OUiiOuM11gI5Kz9GtVttXCjRmwlkU8WiJVIUuVedQAQt2FChrzNQewGFFi0uIau/
wFRclx6hd4JRIImC6VMJd9lcitWsqMcM94pD3fX2ozNgWX+MVlmcDYFSN9Sv8tG4
yCj4ONS8HZGzbxeyQXJhEJSi2FnBi0j6MD/d4DNFj0hCg9wz3fgVLDGCO0pNMO0Y
oXdrzfoj1/zEv0Ibgh7zKG2JHkPfapn3ExFI5d6xi66u5tPVI8cvLxqrgybRPs7Z
y1dQA7ew3LyTPAHoGtbTMvewtx1TkTtRxxhRRm0l58owqSVbSYrixFtosNobCERo
uiknaQqoY1ZDsdKsaqFoZDbntNRYhN3Ea4OPWVqDUU5ZPz9MTIRAi3MIq854yyQo
BjX9nv+kYa+Esr19pxUW0z7BWFhbXsMVpt0QMVyhwgzXvEreaZHFwHHaGb9d5x5P
VBDhsigMmtzBk9NlbCsy+uGXWHgZA/DVefueEq0sv38VoU30uYa5Tj0FLm09AgMB
AAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUI9PCucv3G9fRoTDu
ZQ4Hw6g4PkIwHQYDVR0OBBYEFCPTwrnL9xvX0aEw7mUOB8OoOD5CMA4GA1UdDwEB
/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAk43CCrC0Zbvi7YUsSePKi+KzvyQ9
mjKa5NBU/A5/sLeZS3R+wqCX7l5euYVDsUuNgNVD/QL9jNIonuHBrvKaxkmqxE1r
IcDEaUdjy2lQ0uqD7UDoS3ctrjGkPpUahrTdr3gaKcQBtUhn9v4Y2OBm6J1hDVwI
CIKcxIzRv6AUpApOtk+++m5tzDU48t8+GzrVl1hkspSYcumA+zuHllbPDL1ADdo5
kK/bBQtZrGqzPqKzeqaB1A5Wm0Igwf++7nyzdKNdjxtv907D9vg8EB4Swavuv/Ne
5/jbpI32pz0NIzzSl5ARAHuFhILsO/cEAlloDoTHzibHqFDIeU9/59HMUsJYMOtD
Ii0/LmQ6dBE4TeukCCLJwtkFYZ2eBgDjF/LHBB+z/UBs4milRgwx+Pe5UDUEjtGe
G/XMVnTSKZTy9jMaXJD5EmfP+Cfh8EEgFgjg4AmLUbEo9gXzPxyXSLgd8JGSsjg8
EV/Ri4Mmmt4XUwlSVvEOezxxDGd17gwbottCIC+rqPHonHkGmKpLMH80Bk0uOOCs
ui1oVwSifMyIcudgCcOfRLUf/f2j2NW7N7E7Vw/Zqfn+pqp/EG0KCqOM2vfJAc0s
u3rSrOJZGtB6txgtmTjoadxApWf4U/FCi3uArt6gS5MJqZjuiRNXs/K3SlSAqLGl
5UiG52ew+VdBHzE=
-----END CERTIFICATE-----

View File

@@ -62,7 +62,7 @@ jobs:
name: Windows ${{ matrix.arch }}
strategy:
matrix:
arch: [ia32, x64]
arch: [ia32, x64, arm64]
uses: ./.github/workflows/build_windows.yaml
secrets: inherit
with:
@@ -112,6 +112,8 @@ jobs:
- name: Prepare artifacts for deployment
run: |
set -x
# Windows
for arch in x64 ia32 arm64
do
@@ -145,6 +147,8 @@ jobs:
- name: "[Nightly] Strip version from installer file"
if: needs.prepare.outputs.nightly-version != ''
run: |
set -x
# Windows
for arch in x64 ia32 arm64
do
@@ -161,6 +165,8 @@ jobs:
- name: "[Release] Prepare release latest symlink"
if: needs.prepare.outputs.nightly-version == ''
run: |
set -x
# Windows
for arch in x64 ia32 arm64
do
@@ -208,6 +214,7 @@ jobs:
- name: Deploy artifacts
if: needs.prepare.outputs.deploy == 'true'
run: |
set -x
aws s3 cp --recursive packages.element.io/ s3://$R2_BUCKET/$DEPLOYMENT_DIR --endpoint-url $R2_URL --region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
@@ -227,6 +234,8 @@ jobs:
id: deb
if: needs.linux.result == 'success'
run: |
set -x
for arch in amd64 arm64
do
echo "$arch=$(ls linux-$arch-sqlcipher-static/*.deb | tail -n1)" >> $GITHUB_OUTPUT
@@ -286,6 +295,8 @@ jobs:
- name: Copy files to S3
run: |
set -x
PREFIX="${VERSION%.*}"
for file in win-*/*.msi; do
filename=$(basename "$file")

View File

@@ -22,7 +22,7 @@ jobs:
uses: ./.github/workflows/build_windows.yaml
strategy:
matrix:
arch: [x64, ia32]
arch: [x64, ia32, arm64]
with:
arch: ${{ matrix.arch }}
@@ -97,7 +97,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: .node-version
cache: "yarn"
- name: Install Deps
@@ -121,12 +121,6 @@ jobs:
# We need sudo on Linux as it is installed in /opt/
RUN_AS: ${{ runner.os == 'Linux' && 'sudo' || '' }}
- name: Workaround macOS GHA permission issues
if: runner.os == 'macOS'
run: |
sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/usr/local/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);"
sqlite3 $HOME/Library/Application\ Support/com.apple.TCC/TCC.db "INSERT OR IGNORE INTO access VALUES ('kTCCServiceMicrophone','/opt/off/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159,NULL,NULL,'UNUSED',1687786159);"
- name: Run tests
uses: coactions/setup-xvfb@6b00cf1889f4e1d5a48635647013c0508128ee1a
timeout-minutes: 5

View File

@@ -25,16 +25,12 @@ env:
MAX_GLIBC: 2.31 # bullseye-era glibc, used by glibc-check.sh
permissions: {} # No permissions required
jobs:
# We build the hak files on native infrastructure as matrix-seshat fails to cross-compile properly
# https://github.com/matrix-org/seshat/issues/135
hak:
build:
# We build on native infrastructure as matrix-seshat fails to cross-compile properly
# https://github.com/matrix-org/seshat/issues/135
runs-on: ${{ inputs.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04' }}
env:
HAK_DOCKER_IMAGE: ghcr.io/element-hq/element-desktop-dockerbuild
outputs:
cache-key: ${{ steps.cache-key.outputs.key }}
arch: ${{ steps.config.outputs.arch }}
build-args: ${{ steps.config.outputs.build-args }}
steps:
- name: Resolve docker image tag for push
if: github.event_name == 'push'
@@ -70,112 +66,62 @@ jobs:
with:
name: webapp
- name: Calculate cache key
id: cache-key
run: |
echo "key=$CACHE_KEY" >> $GITHUB_OUTPUT
env:
CACHE_KEY: ${{ runner.os }}-${{ github.ref_name }}-${{ inputs.sqlcipher }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion', 'dockerbuild/*') }}
- name: Cache .hak
id: cache
uses: actions/cache@v4
with:
key: ${{ steps.cache-key.outputs.key }}
path: |
./.hak
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: .node-version
cache: "yarn"
env:
# Workaround for https://github.com/actions/setup-node/issues/317
FORCE_COLOR: 0
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: "Get modified files"
id: changed_files
if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request'
uses: tj-actions/changed-files@d6e91a2266cdb9d62096cebf1e8546899c6aa18f # v45
uses: tj-actions/changed-files@dcc7a0cba800f454d79fff4b993e8c3555bcc0a8 # v45
with:
files: |
dockerbuild/**
# This allows contributors to test changes to the dockerbuild image within a pull request
- name: Build docker image
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6
if: steps.changed_files.outputs.any_modified == 'true'
with:
context: dockerbuild
file: dockerbuild/Dockerfile
load: true
platforms: linux/${{ inputs.arch }}
tags: ${{ env.HAK_DOCKER_IMAGE }}
- name: Build Natives
if: steps.cache.outputs.cache-hit != 'true'
run: |
docker run \
-v ${{ github.workspace }}:/work -w /work \
-e SQLCIPHER_BUNDLED \
$HAK_DOCKER_IMAGE \
yarn build:native
- name: Check native libraries
- name: Check native libraries in hak dependencies
run: |
shopt -s globstar
for filename in ./.hak/hakModules/**/*.node; do
for filename in ./node_modules/**/*.node; do
./scripts/glibc-check.sh $filename
done
build:
needs: hak
runs-on: ubuntu-24.04
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: webapp
- name: Load .hak
id: cache
uses: actions/cache/restore@v4
with:
key: ${{ needs.hak.outputs.cache-key }}
fail-on-cache-miss: true
path: |
./.hak
- uses: actions/setup-node@v4
with:
node-version-file: package.json
cache: "yarn"
env:
# Workaround for https://github.com/actions/setup-node/issues/317
FORCE_COLOR: 0
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: "[Nightly] Resolve version"
if: inputs.version != ''
run: |
echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV
- name: Generate debian files and arguments
run: |
if [ -f changelog.Debian ]; then
echo "ED_DEBIAN_CHANGELOG=changelog.Debian" >> $GITHUB_ENV
fi
# Workaround for https://github.com/electron-userland/electron-builder/issues/6116
- name: Install fpm
if: inputs.arch == 'arm64'
run: |
sudo apt-get install ruby-dev build-essential
sudo gem install fpm
echo "USE_SYSTEM_FPM=true" >> $GITHUB_ENV
- name: Build App
run: yarn build --publish never -l ${{ needs.hak.outputs.build-args }}
run: yarn build --publish never -l ${{ steps.config.outputs.build-args }}
env:
# Only set for Nightly builds
ED_NIGHTLY: ${{ inputs.version }}
- name: Check native libraries
run: |
@@ -203,7 +149,7 @@ jobs:
./scripts/glibc-check.sh dist/linux-*unpacked/element-desktop*
env:
ARCH: ${{ needs.hak.outputs.arch }}
ARCH: ${{ steps.config.outputs.arch }}
# We exclude *-unpacked as it loses permissions and the tarball contains it with correct permissions
- name: Upload Artifacts
@@ -214,3 +160,10 @@ jobs:
dist
!dist/*-unpacked/**
retention-days: 1
- name: Assert all required files are present
run: |
test -f ./dist/element-desktop*$ARCH.deb
test -f ./dist/element-desktop*.tar.gz
env:
ARCH: ${{ inputs.arch }}

View File

@@ -39,14 +39,6 @@ jobs:
with:
name: webapp
- name: Cache .hak
id: cache
uses: actions/cache@v4
with:
key: ${{ runner.os }}-${{ hashFiles('hakHash', 'electronVersion') }}
path: |
./.hak
- name: Install Rust
if: steps.cache.outputs.cache-hit != 'true'
run: |
@@ -62,10 +54,9 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: .node-version
cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
@@ -74,12 +65,6 @@ jobs:
run: |
# Python 3.12 drops distutils which keytar relies on
pip3 install setuptools
yarn build:native:universal
- name: "[Nightly] Resolve version"
if: inputs.version != ''
run: |
echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV
# We split these because electron-builder gets upset if we set CSC_LINK even to an empty string
- name: "[Signed] Build App"
@@ -92,6 +77,8 @@ jobs:
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.APPLE_CSC_LINK }}
# Only set for Nightly builds
ED_NIGHTLY: ${{ inputs.version }}
- name: Check app was signed & notarised successfully
if: inputs.sign != ''
@@ -143,3 +130,8 @@ jobs:
dist
!dist/mac-universal/**
retention-days: 1
- name: Assert all required files are present
run: |
test -f ./dist/Element*.dmg
test -f ./dist/Element*-mac.zip

View File

@@ -56,7 +56,7 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: .node-version
cache: "yarn"
- name: Install Deps

View File

@@ -3,6 +3,8 @@
# the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch.
# Windows GHA runner by default uses the pwsh shell which breaks codeSigningCert in the workflow
# We always sign using eSignerCKA to ensure it keeps working, but aside from release & nightlies we use demo credentials
# which do not yield trusted signatures.
defaults:
run:
shell: powershell
@@ -64,19 +66,6 @@ jobs:
with:
name: webapp
- name: Cache .hak
id: cache
uses: actions/cache@v4
with:
key: ${{ runner.os }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion') }}
path: |
./.hak
- name: Set up build tools
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
with:
arch: ${{ steps.config.outputs.arch || inputs.arch }}
# ActiveTCL package on choco is from 2015,
# this one is newer but includes more than we need
- name: Choco install tclsh
@@ -102,21 +91,25 @@ jobs:
- uses: actions/setup-node@v4
with:
node-version-file: package.json
node-version-file: .node-version
cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Build Natives
if: steps.cache.outputs.cache-hit != 'true'
- name: Set up sqlcipher macros
if: steps.cache.outputs.cache-hit != 'true' && contains(inputs.arch, 'arm')
shell: pwsh
run: |
refreshenv
yarn build:native --target ${{ steps.config.outputs.target }}
echo "NCC=${{ github.workspace }}\scripts\cl.bat" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Set up build tools
if: steps.cache.outputs.cache-hit != 'true'
uses: ilammy/msvc-dev-cmd@0b201ec74fa43914dc39ae48a89fd1d8cb592756 # v1.13.0
with:
arch: ${{ steps.config.outputs.arch || inputs.arch }}
- name: Install and configure eSigner CKA
if: inputs.sign
run: |
Set-StrictMode -Version 'Latest'
@@ -134,8 +127,13 @@ jobs:
$LogConfig[0] = '<log4net threshold="OFF">'
$LogConfig | Set-Content -Path ${{ env.INSTALL_DIR }}/log4net.config
# Configure
${{ env.INSTALL_DIR }}/eSignerCKATool.exe config -mode product -user "${{ secrets.ESIGNER_USER_NAME }}" -pass "${{ secrets.ESIGNER_USER_PASSWORD }}" -totp "${{ secrets.ESIGNER_USER_TOTP }}" -key "${{ env.MASTER_KEY_FILE }}" -r
# Configure - default credentials from https://www.ssl.com/guide/esigner-demo-credentials-and-certificates/
${{ env.INSTALL_DIR }}/eSignerCKATool.exe config `
-mode ${{ vars.ESIGNER_MODE || 'sandbox' }} `
-user "${{ secrets.ESIGNER_USER_NAME || 'esigner_demo' }}" `
-pass "${{ secrets.ESIGNER_USER_PASSWORD || 'esignerDemo#1' }}" `
-totp "${{ secrets.ESIGNER_USER_TOTP || 'RDXYgV9qju+6/7GnMf1vCbKexXVJmUVr+86Wq/8aIGg=' }}" `
-key "${{ env.MASTER_KEY_FILE }}" -r
${{ env.INSTALL_DIR }}/eSignerCKATool.exe unload
${{ env.INSTALL_DIR }}/eSignerCKATool.exe load
@@ -154,24 +152,25 @@ jobs:
INSTALL_DIR: C:\Users\runneradmin\eSignerCKA
MASTER_KEY_FILE: C:\Users\runneradmin\eSignerCKA\master.key
- name: "[Nightly] Resolve version"
if: inputs.version != ''
shell: bash
run: |
echo "ED_NIGHTLY=${{ inputs.version }}" >> $GITHUB_ENV
# XXX: For whatever reason if we use `yarn build ...` it freezes, but splitting it into parts it is fine
- run: yarn run build:ts
- run: yarn run build:res
- name: Build App
run: yarn build --publish never -w ${{ steps.config.outputs.build-args }}
env:
# Only set for Nightly builds
ED_NIGHTLY: ${{ inputs.version }}
- name: Trust eSigner sandbox cert
if: inputs.sign == ''
run: |
yarn electron-builder --publish never -w ${{ steps.config.outputs.build-args }}
Set-StrictMode -Version 'Latest'
Import-Certificate -CertStoreLocation Cert:\LocalMachine\Root -FilePath .github/SSLcom-sandbox.crt
- name: Check app was signed successfully
if: inputs.sign != ''
run: |
. "$env:SIGNTOOL_PATH" verify /pa (get-item ./dist/squirrel-windows*/*.exe)
Set-StrictMode -Version 'Latest'
Get-ChildItem `
-Recurse dist `
-Include *.exe, *.msi `
| ForEach-Object -Process {. $env:SIGNTOOL_PATH verify /pa $_.FullName; if(!$?) { throw }}
- name: Upload Artifacts
uses: actions/upload-artifact@v4
@@ -180,3 +179,11 @@ jobs:
path: |
dist
retention-days: 1
- name: Assert all required files are present
run: |
Test-Path './dist/win-*unpacked/Element*.exe'
Test-Path './dist/squirrel-windows*/Element Setup*.exe'
Test-Path './dist/squirrel-windows*/element-desktop-*-full.nupkg'
Test-Path './dist/squirrel-windows*/RELEASES'
Test-Path './dist/Element*.msi'

View File

@@ -22,17 +22,17 @@ jobs:
- uses: actions/checkout@v4
- name: Set up QEMU
uses: docker/setup-qemu-action@53851d14592bedcffcf25ea515637cff71ef929a # v3
uses: docker/setup-qemu-action@4574d27a4764455b42196d70a065bc6853246a25 # v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5 # v3
uses: docker/setup-buildx-action@f7ce87c1d6bead3e36075b2ce75da1f6cc28aaca # v3
with:
install: true
- name: Build test image
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6
with:
context: dockerbuild
file: dockerbuild/Dockerfile
push: false
load: true
tags: element-desktop-dockerbuild
@@ -61,9 +61,9 @@ jobs:
- name: Build and push Docker image
if: github.event_name != 'pull_request'
uses: docker/build-push-action@67a2d409c0a876cbe6b11854e3e25193efe4e62d # v6
uses: docker/build-push-action@ca877d9245402d1537745e0e356eab47c3520991 # v6
with:
context: dockerbuild
file: dockerbuild/Dockerfile
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -19,6 +19,7 @@ jobs:
contents: write
issues: write
pull-requests: read
id-token: write
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }}

22
.github/workflows/triage-stale.yml vendored Normal file
View File

@@ -0,0 +1,22 @@
name: Close stale PRs
on:
workflow_dispatch: {}
schedule:
- cron: "30 1 * * *"
permissions: {}
jobs:
close:
runs-on: ubuntu-24.04
permissions:
actions: write
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
with:
operations-per-run: 250
days-before-issue-stale: -1
days-before-issue-close: -1
days-before-pr-stale: 180
days-before-pr-close: 0
close-pr-message: "This PR has been automatically closed because it has been stale for 180 days. If you wish to continue working on this PR, please ping a maintainer to reopen it."

1
.node-version Normal file
View File

@@ -0,0 +1 @@
v22.14.0

View File

@@ -1,3 +1,44 @@
Changes in [1.11.94](https://github.com/element-hq/element-desktop/releases/tag/v1.11.94) (2025-02-27)
======================================================================================================
* No changes
## 🐛 Bug Fixes
* [Backport staging] fix: /tmp/element-web-config may already exist preventing the container from booting up ([#29377](https://github.com/element-hq/element-web/pull/29377)). Contributed by @RiotRobot.
Changes in [1.11.93](https://github.com/element-hq/element-desktop/releases/tag/v1.11.93) (2025-02-25)
======================================================================================================
## ✨ Features
* [backport] Dynamically load Element Web modules in Docker entrypoint ([#29358](https://github.com/element-hq/element-web/pull/29358)). Contributed by @t3chguy.
* ChangeRecoveryKey: error handling ([#29262](https://github.com/element-hq/element-web/pull/29262)). Contributed by @richvdh.
* Dehydration: enable dehydrated device on "Set up recovery" ([#29265](https://github.com/element-hq/element-web/pull/29265)). Contributed by @richvdh.
* Render reason for invite rejection. ([#29257](https://github.com/element-hq/element-web/pull/29257)). Contributed by @Half-Shot.
* New room list: add search section ([#29251](https://github.com/element-hq/element-web/pull/29251)). Contributed by @florianduros.
* New room list: hide favourites and people meta spaces ([#29241](https://github.com/element-hq/element-web/pull/29241)). Contributed by @florianduros.
* New Room List: Create new labs flag ([#29239](https://github.com/element-hq/element-web/pull/29239)). Contributed by @MidhunSureshR.
* Stop URl preview from covering message box ([#29215](https://github.com/element-hq/element-web/pull/29215)). Contributed by @edent.
* Rename "security key" into "recovery key" ([#29217](https://github.com/element-hq/element-web/pull/29217)). Contributed by @florianduros.
* Add new verification section to user profile ([#29200](https://github.com/element-hq/element-web/pull/29200)). Contributed by @MidhunSureshR.
* Initial support for runtime modules ([#29104](https://github.com/element-hq/element-web/pull/29104)). Contributed by @t3chguy.
* Add `Forgot recovery key?` button to encryption tab ([#29202](https://github.com/element-hq/element-web/pull/29202)). Contributed by @florianduros.
* Add KeyIcon to key storage out of sync toast ([#29201](https://github.com/element-hq/element-web/pull/29201)). Contributed by @florianduros.
* Improve rendering of empty topics in the timeline ([#29152](https://github.com/element-hq/element-web/pull/29152)). Contributed by @Half-Shot.
## 🐛 Bug Fixes
* Fix font scaling in member list ([#29285](https://github.com/element-hq/element-web/pull/29285)). Contributed by @florianduros.
* Grow member list search field when resizing the right panel ([#29267](https://github.com/element-hq/element-web/pull/29267)). Contributed by @langleyd.
* Don't reload roomview on offline connectivity check ([#29243](https://github.com/element-hq/element-web/pull/29243)). Contributed by @dbkr.
* Respect user's 12/24 hour preference consistently ([#29237](https://github.com/element-hq/element-web/pull/29237)). Contributed by @t3chguy.
* Restore the accessibility role on call views ([#29225](https://github.com/element-hq/element-web/pull/29225)). Contributed by @robintown.
* Revert `GoToHome` keyboard shortcut to `Ctrl``Shift``H` on macOS ([#28577](https://github.com/element-hq/element-web/pull/28577)). Contributed by @gy-mate.
* Encryption tab: display correct encryption panel when user cancels the reset identity flow ([#29216](https://github.com/element-hq/element-web/pull/29216)). Contributed by @florianduros.
Changes in [1.11.92](https://github.com/element-hq/element-desktop/releases/tag/v1.11.92) (2025-02-11)
======================================================================================================
## ✨ Features

View File

@@ -2,7 +2,7 @@
# with broader compatibility, down to Debian bullseye & Ubuntu focal.
FROM rust:bullseye
ENV DEBIAN_FRONTEND noninteractive
ENV DEBIAN_FRONTEND=noninteractive
RUN curl --proto "=https" -L https://yarnpkg.com/latest.tar.gz | tar xvz && mv yarn-* /yarn && ln -s /yarn/bin/yarn /usr/bin/yarn
RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
@@ -16,13 +16,12 @@ RUN apt-get -qq update && apt-get -y -qq dist-upgrade && \
apt-get purge -y --auto-remove && rm -rf /var/lib/apt/lists/*
RUN ln -s /usr/bin/python3 /usr/bin/python & ln -s /usr/bin/pip3 /usr/bin/pip
ENV DEBUG_COLORS true
ENV FORCE_COLOR true
ENV DEBUG_COLORS=true
ENV FORCE_COLOR=true
WORKDIR /project
ENV NODE_VERSION 20.18.2
ARG TARGETOS
ARG TARGETARCH
COPY setup.sh /setup.sh
COPY .node-version dockerbuild/setup.sh /
RUN /setup.sh

View File

@@ -3,5 +3,6 @@
set -x
declare -A archMap=(["amd64"]="x64" ["arm64"]="arm64")
ARCH="${archMap["$TARGETARCH"]}"
curl --proto "=https" -L "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
NODE_VERSION=$(cat /.node-version)
curl --proto "=https" -L "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md

View File

@@ -12,6 +12,13 @@ If you want to build native modules, make sure that the following tools are inst
- [Strawberry Perl](https://strawberryperl.com/)
- [Rustup](https://rustup.rs/)
- [NASM](https://www.nasm.us/)
You can install the above tools using [Chocolatey](https://chocolatey.org/install):
```cmd
choco install --no-progress -y git nodejs-lts yarn python StrawberryPerl rustup.install nasm magicsplat-tcl-tk
```
- [Build Tools for Visual Studio 2019](https://visualstudio.microsoft.com/downloads/#build-tools-for-visual-studio-2019) with the following configuration:
- On the Workloads tab:
- Desktop & Mobile -> C++ build tools

View File

@@ -93,14 +93,7 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
afterPack: async (context: AfterPackContext) => {
await injectAsarIntegrity(context);
},
files: [
"package.json",
{
from: ".hak/hakModules",
to: "node_modules",
},
"lib/**",
],
files: ["package.json", "lib/**"],
extraResources: [
{
from: "res/img",
@@ -174,6 +167,9 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
schemes: ["io.element.desktop", "element"],
},
],
nativeRebuilder: "sequential",
nodeGypRebuild: false,
npmRebuild: true,
};
/**

View File

@@ -1,26 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import type HakEnv from "../../scripts/hak/hakEnv.js";
import type { DependencyInfo } from "../../scripts/hak/dep.js";
export default async function buildKeytar(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const env = hakEnv.makeGypEnv();
console.log("Running yarn with env", env);
await hakEnv.spawn(
path.join(moduleInfo.nodeModuleBinDir, "node-gyp"),
["rebuild", "--arch", hakEnv.getTargetArch()],
{
cwd: moduleInfo.moduleBuildDir,
env,
},
);
}

View File

@@ -1,15 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type HakEnv from "../../scripts/hak/hakEnv.js";
import type { DependencyInfo } from "../../scripts/hak/dep.js";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
// node-gyp uses python for reasons beyond comprehension
await hakEnv.checkTools([["python", "--version"]]);
}

View File

@@ -1,10 +0,0 @@
{
"scripts": {
"check": "check.ts",
"build": "build.ts"
},
"copy": "build/Release/keytar.node",
"dependencies": {
"libsecret": "0.20.3"
}
}

View File

@@ -1,34 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type HakEnv from "../../scripts/hak/hakEnv.js";
import type { DependencyInfo } from "../../scripts/hak/dep.js";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const env = hakEnv.makeGypEnv();
if (!hakEnv.isHost()) {
env.CARGO_BUILD_TARGET = hakEnv.getTargetId();
}
console.log("Running yarn install");
await hakEnv.spawn("yarn", ["install"], {
cwd: moduleInfo.moduleBuildDir,
env,
shell: true,
});
const buildTarget = hakEnv.wantsStaticSqlCipher() ? "build-bundled" : "build";
console.log("Running yarn build");
await hakEnv.spawn("yarn", ["run", buildTarget], {
cwd: moduleInfo.moduleBuildDir,
env,
shell: true,
});
}

View File

@@ -1,55 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import childProcess from "node:child_process";
import fsProm from "node:fs/promises";
import type HakEnv from "../../scripts/hak/hakEnv.js";
import type { Tool } from "../../scripts/hak/hakEnv.js";
import type { DependencyInfo } from "../../scripts/hak/dep.js";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const tools: Tool[] = [
["rustc", "--version"],
["python", "--version"], // node-gyp uses python for reasons beyond comprehension
];
if (hakEnv.isWin()) {
tools.push(["perl", "--version"]); // for openssl configure
tools.push(["nasm", "-v"]); // for openssl building
tools.push(["patch", "--version"]); // to patch sqlcipher Makefile.msc
tools.push(["nmake", "/?"]);
} else {
tools.push(["make", "--version"]);
}
await hakEnv.checkTools(tools);
// Ensure Rust target exists (nb. we avoid depending on rustup)
await new Promise((resolve, reject) => {
const rustc = childProcess.execFile(
"rustc",
["--target", hakEnv.getTargetId(), "--emit=obj", "-o", "tmp", "-"],
(err, out) => {
if (err) {
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`",
);
}
fsProm.unlink("tmp").then(resolve);
},
);
rustc.stdin!.write("fn main() {}");
rustc.stdout!.pipe(process.stdout);
rustc.stderr!.pipe(process.stderr);
rustc.stdin!.end();
});
}

View File

@@ -1,7 +0,0 @@
{
"scripts": {
"check": "check.ts",
"build": "build.ts"
},
"copy": "index.node"
}

View File

@@ -1,11 +0,0 @@
{
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"target": "es2022",
"sourceMap": false,
"strict": true,
"lib": ["es2022"]
},
"include": ["../scripts/@types/*.d.ts", "./**/*.ts"]
}

View File

@@ -5,11 +5,8 @@ export default {
project: ["**/*.{js,ts}"],
ignoreDependencies: [
// Brought in via hak scripts
"keytar",
"keytar-forked",
"matrix-seshat",
// Needed by `electron-builder`
"electron-builder-squirrel-windows",
"@types/yargs",
// Required for `action-validator`
"@action-validator/*",
// Used for git pre-commit hooks

View File

@@ -3,8 +3,8 @@
"productName": "Element",
"main": "lib/electron-main.js",
"exports": "./lib/electron-main.js",
"version": "1.11.92",
"description": "A feature-rich client for Matrix.org",
"version": "1.11.94",
"description": "Element: the future of secure communication",
"author": "Element",
"homepage": "https://element.io",
"repository": {
@@ -27,25 +27,21 @@
"asar-webapp": "asar p webapp webapp.asar",
"start": "yarn run build:ts && yarn run build:res && electron .",
"lint": "yarn lint:types && yarn lint:js && yarn lint:workflows",
"lint:js": "eslint --max-warnings 0 src hak playwright scripts && prettier --check .",
"lint:js-fix": "eslint --fix --max-warnings 0 src hak playwright scripts && prettier --log-level=warn --write .",
"lint:types": "yarn lint:types:src && yarn lint:types:test && yarn lint:types:scripts && yarn lint:types:hak",
"lint:js": "eslint --max-warnings 0 src playwright scripts && prettier --check .",
"lint:js-fix": "eslint --fix --max-warnings 0 src playwright scripts && prettier --log-level=warn --write .",
"lint:types": "yarn lint:types:src && yarn lint:types:test && yarn lint:types:scripts",
"lint:types:src": "tsc --noEmit",
"lint:types:test": "tsc --noEmit -p playwright/tsconfig.json",
"lint:types:scripts": "tsc --noEmit -p scripts/tsconfig.json",
"lint:types:hak": "tsc --noEmit -p hak/tsconfig.json",
"lint:workflows": "find .github/workflows -type f \\( -iname '*.yaml' -o -iname '*.yml' \\) | xargs -I {} sh -c 'echo \"Linting {}\"; action-validator \"{}\"'",
"lint:knip": "knip",
"build:native": "yarn run hak",
"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": "tsx scripts/copy-res.ts",
"docker:setup": "docker build --platform linux/amd64 -t element-desktop-dockerbuild dockerbuild",
"docker:build:native": "scripts/in-docker.sh yarn run hak",
"docker:setup": "docker build --platform linux/amd64 -t element-desktop-dockerbuild -f dockerbuild/Dockerfile .",
"docker:build": "scripts/in-docker.sh yarn run build",
"docker:install": "scripts/in-docker.sh yarn install",
"clean": "rimraf webapp.asar dist packages deploys lib",
@@ -53,15 +49,18 @@
"test": "playwright test",
"test:open": "yarn test --ui",
"test:screenshots:build": "docker build playwright -t element-desktop-playwright --platform linux/amd64",
"test:screenshots:run": "docker run --rm --network host -v $(pwd):/work/element-desktop -v /var/run/docker.sock:/var/run/docker.sock --platform linux/amd64 -it element-desktop-playwright"
"test:screenshots:run": "docker run --rm --network host -v $(pwd):/work/element-desktop -v /var/run/docker.sock:/var/run/docker.sock --platform linux/amd64 -it element-desktop-playwright",
"postinstall": "electron-builder install-app-deps"
},
"dependencies": {
"@sentry/electron": "^5.0.0",
"@standardnotes/electron-clear-data": "^1.0.5",
"auto-launch": "^5.0.5",
"counterpart": "^0.18.6",
"electron-clear-data": "^1.0.5",
"electron-store": "^10.0.0",
"electron-window-state": "^5.0.3",
"keytar-forked": "7.10.0",
"matrix-seshat": "https://gitpkg.vercel.app/matrix-org/seshat/seshat-node?t3chguy/binding-gyp",
"minimist": "^1.2.6",
"png-to-ico": "^2.1.1",
"uuid": "^11.0.0"
@@ -72,24 +71,22 @@
"@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6",
"@electron/asar": "3.2.18",
"@mapbox/node-pre-gyp": "^1.0.11",
"@playwright/test": "1.49.1",
"@stylistic/eslint-plugin": "^2.9.0",
"@electron/asar": "3.3.1",
"@playwright/test": "1.50.1",
"@stylistic/eslint-plugin": "^3.0.0",
"@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1",
"@types/minimist": "^1.2.1",
"@types/node": "18.19.71",
"@types/node": "18.19.76",
"@types/pacote": "^11.1.1",
"@types/yargs": "^17.0.32",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"app-builder-lib": "^26.0.1",
"app-builder-lib": "26.0.8",
"chokidar": "^4.0.0",
"detect-libc": "^2.0.0",
"electron": "34.0.1",
"electron-builder": "^26.0.1",
"electron-builder-squirrel-windows": "^26.0.1",
"electron": "34.2.0",
"electron-builder": "26.0.8",
"electron-builder-squirrel-windows": "26.0.8",
"electron-devtools-installer": "^4.0.0",
"eslint": "^8.26.0",
"eslint-config-google": "^0.14.0",
@@ -112,12 +109,8 @@
"tsx": "^4.19.2",
"typescript": "5.7.3"
},
"hakDependencies": {
"matrix-seshat": "^4.0.0",
"keytar": "^7.9.0"
},
"resolutions": {
"@types/node": "18.19.71",
"@types/node": "18.19.76",
"config-file-ts": "0.2.8-rc1"
}
}

View File

@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/playwright:v1.49.1-jammy
FROM mcr.microsoft.com/playwright:v1.50.1-jammy
WORKDIR /work/element-desktop

View File

@@ -1,11 +0,0 @@
/*
Copyright 2022-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
declare module "@mapbox/node-pre-gyp/lib/util/versioning" {
// eslint-disable-next-line @typescript-eslint/naming-convention
export function get_runtime_abi(runtime: string, version: string): string;
}

7
scripts/cl.bat Normal file
View File

@@ -0,0 +1,7 @@
REM Batch file to aid in cross-compiling sqlcipher for Windows ARM64
REM Full path should be passed to Makefile.msc as NCC env var
setlocal
call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" %VSCMD_ARG_HOST_ARCH%
cl.exe %*
endlocal

View File

@@ -1,81 +0,0 @@
# hak
This tool builds native dependencies for element-desktop. Here follows some very minimal
documentation for it.
Goals:
- Must build compiled native node modules in a shippable state
(ie. only dynamically linked against libraries that will be on the
target system, all unnecessary files removed).
- Must be able to build any native module, no matter what build system
it uses (electron-rebuild is supposed to do this job but only works
for modules that use gyp).
It's also loosely designed to be a general tool and agnostic to what it's
actually building. It's used here to build modules for the electron app
but should work equally well for building modules for normal node.
# Running
Hak is invoked with a command and a dependency, eg. `yarn run hak fetch matrix-seshat`.
If no dependencies are given, hak runs the command on all dependencies.
# Files
There are a lot of files involved:
- scripts/hak/... - The tool itself
- hak/[dependency] - Files provided by the app that tell hak how to build each of its native dependencies.
Contains a hak.json file and also some script files, each of which must be referenced in hak.json.
- .hak/ - Files generated by hak in the course of doing its job. Includes the dependency module itself and
any of the native dependency's native dependencies.
- .hak/[dependency]/build - An extracted copy of the dependency's node module used to build it.
- .hak/[dependency]/out - Another extracted copy of the dependency, this one contains only what will be shipped.
# Workings
Hak works around native node modules that try to fetch or build their native component in
the npm 'install' phase - modules that do this will typically end up with native components
targeted to the build platform and the node that npm/yarn is using, which is no good for an
electron app.
It does this by installing it with `--ignore-scripts` and then using `yarn link` to keep the
dependency module separate so yarn doesn't try to run its install / postinstall script
at other points (eg. whenever you `yarn add` a random other dependency).
This also means that the dependencies cannot be listed in `dependencies` or
`devDependencies` in the project, since this would cause npm / yarn to install them and
try to fetch their native parts. Instead, they are listed in `hakDependencies` which
hak reads to install them for you.
Hak will _not_ install dependencies for the copy of the module it links into your
project, so if your native module has javascript dependencies that are actually needed at
runtime (and not just to fetch / build the native parts), it won't work.
Hak will generate a `.yarnrc` in the project directory to set the link directory to its
own in the .hak directory (unless one already exists, in which case this is your problem).
# Lifecycle
Hak is divided into lifecycle stages, in order:
- fetch - Download and extract the source of the dependency
- link - Link the copy of the dependency into your node_modules directory
- build - The Good Stuff. Configure and build any native dependencies, then the module itself.
- copy - Copy the built artifact from the module build directory to the module output directory.
# hak.json
The scripts section contains scripts used for lifecycle stages that need them (fetch, fetchDeps, build).
It also contains 'prune' and 'copy' which are globs of files to delete from the output module directory
and copy over from the module build directory to the output module directory, respectively.
# Shortcomings
Hak doesn't know about dependencies between lifecycle stages, ie. it doesn't know that you need to
'fetch' and 'fetchDeps' before you can 'build', etc. You get to run each individually, and remember
the right order.
There is also a _lot_ of duplication in the command execution: we should abstract away
some of the boilerplate required to run commands & so forth.

View File

@@ -1,14 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js";
export default async function build(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await moduleInfo.scripts.build(hakEnv, moduleInfo);
}

View File

@@ -1,16 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js";
export default async function check(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (moduleInfo.scripts.check) {
await moduleInfo.scripts.check(hakEnv, moduleInfo);
}
}

View File

@@ -1,19 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import { rimraf } from "rimraf";
import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js";
export default async function clean(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await rimraf(moduleInfo.moduleDotHakDir);
await rimraf(path.join(hakEnv.dotHakDir, "links", moduleInfo.name));
await rimraf(path.join(hakEnv.projectRoot, "node_modules", moduleInfo.name));
}

View File

@@ -1,77 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import fsProm from "node:fs/promises";
import childProcess from "node:child_process";
import { rimraf } from "rimraf";
import { glob } from "glob";
import { mkdirp } from "mkdirp";
import type HakEnv from "./hakEnv.js";
import type { DependencyInfo } from "./dep.js";
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 {
await mkdirp(moduleInfo.moduleOutDir);
process.chdir(moduleInfo.moduleOutDir);
await rimraf(moduleInfo.cfg.prune);
} 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 glob(moduleInfo.cfg.copy, {
cwd: moduleInfo.moduleBuildDir,
});
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);
}
}
}
}

View File

@@ -1,24 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type HakEnv from "./hakEnv.js";
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>>;
}

View File

@@ -1,51 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import fsProm from "node:fs/promises";
import pacote from "pacote";
import type HakEnv from "./hakEnv.js";
import type { DependencyInfo } from "./dep.js";
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 {
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 hakEnv.spawn("yarn", ["install", "--ignore-scripts"], {
cwd: moduleInfo.moduleBuildDir,
});
// 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,
});
}

View File

@@ -1,19 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { mkdirp } from "mkdirp";
import type { DependencyInfo } from "./dep.js";
import type HakEnv from "./hakEnv.js";
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);
}
}

View File

@@ -1,147 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import os from "node:os";
import nodePreGypVersioning from "@mapbox/node-pre-gyp/lib/util/versioning";
import { getElectronVersionFromInstalled } from "app-builder-lib/out/electron/electronVersion.js";
import childProcess, { SpawnOptions } from "node:child_process";
import { Arch, Target, TARGETS, getHost, isHostId, TargetId } from "./target.js";
async function getRuntime(projectRoot: string): Promise<string> {
const electronVersion = await getElectronVersionFromInstalled(projectRoot);
return electronVersion ? "electron" : "node-webkit";
}
async function getRuntimeVersion(projectRoot: string): Promise<string> {
const electronVersion = await getElectronVersionFromInstalled(projectRoot);
if (electronVersion) {
return electronVersion;
} else {
return process.version.substr(1);
}
}
export type Tool = [cmd: string, ...args: string[]];
export default class HakEnv {
public readonly target: Target;
public runtime?: string;
public runtimeVersion?: string;
public dotHakDir: string;
public constructor(
public readonly projectRoot: string,
targetId: TargetId | null,
) {
const target = targetId ? TARGETS[targetId] : getHost();
if (!target) {
throw new Error(`Unknown target ${targetId}!`);
}
this.target = target;
this.dotHakDir = path.join(this.projectRoot, ".hak");
}
public async init(): Promise<void> {
this.runtime = await getRuntime(this.projectRoot);
this.runtimeVersion = await getRuntimeVersion(this.projectRoot);
}
public getRuntimeAbi(): string {
return nodePreGypVersioning.get_runtime_abi(this.runtime!, this.runtimeVersion!);
}
// {node_abi}-{platform}-{arch}
public getNodeTriple(): string {
return this.getRuntimeAbi() + "-" + this.target.platform + "-" + this.target.arch;
}
public getTargetId(): TargetId {
return this.target.id;
}
public isWin(): boolean {
return this.target.platform === "win32";
}
public isMac(): boolean {
return this.target.platform === "darwin";
}
public isLinux(): boolean {
return this.target.platform === "linux";
}
public isFreeBSD(): boolean {
return this.target.platform === "freebsd";
}
public getTargetArch(): Arch {
return this.target.arch;
}
public isHost(): boolean {
return isHostId(this.target.id);
}
public makeGypEnv(): Record<string, string | undefined> {
return {
...process.env,
npm_config_arch: this.target.arch,
npm_config_target_arch: this.target.arch,
npm_config_disturl: "https://electronjs.org/headers",
npm_config_runtime: this.runtime,
npm_config_target: this.runtimeVersion,
npm_config_build_from_source: "true",
npm_config_devdir: path.join(os.homedir(), ".electron-gyp"),
};
}
public wantsStaticSqlCipher(): boolean {
return !(this.isLinux() || this.isFreeBSD()) || process.env.SQLCIPHER_BUNDLED == "1";
}
public spawn(
cmd: string,
args: string[],
{ ignoreWinCmdlet, ...options }: SpawnOptions & { ignoreWinCmdlet?: boolean } = {},
): Promise<void> {
return new Promise((resolve, reject) => {
const proc = childProcess.spawn(cmd + (!ignoreWinCmdlet && this.isWin() ? ".cmd" : ""), args, {
stdio: "inherit",
// We need shell mode on Windows to be able to launch `.cmd` executables
// See https://nodejs.org/en/blog/vulnerability/april-2024-security-releases-2
shell: this.isWin(),
...options,
});
proc.on("exit", (code) => {
if (code) {
reject(code);
} else {
resolve();
}
});
});
}
public async checkTools(tools: Tool[]): Promise<void> {
for (const [tool, ...args] of tools) {
try {
await this.spawn(tool, args, {
ignoreWinCmdlet: true,
stdio: ["ignore"],
shell: false,
});
} catch {
throw new Error(`Can't find ${tool}`);
}
}
}
}

View File

@@ -1,156 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020, 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path, { dirname } from "node:path";
import { fileURLToPath } from "node:url";
import HakEnv from "./hakEnv.js";
import type { TargetId } from "./target.js";
import type { DependencyInfo } from "./dep.js";
import { loadJsonFile } from "../../src/utils.js";
import packageJson from "../../package.json";
const GENERALCOMMANDS = ["target"];
// These can only be run on specific modules
const MODULECOMMANDS = ["check", "fetch", "link", "build", "copy", "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: Record<string, string[]> = {
fetchandbuild: ["check", "fetch", "build"],
copyandlink: ["copy", "link"],
};
// Scripts valid in a hak.json 'scripts' section
const HAKSCRIPTS = ["check", "fetch", "build"];
const __dirname = dirname(fileURLToPath(import.meta.url));
async function main(): Promise<void> {
const prefix = path.join(__dirname, "..", "..");
const targetIds: TargetId[] = [];
// Apply `--target <target>` option if specified
// Can be specified multiple times for the copy command to bundle
// multiple arches into a single universal output module)
for (;;) {
// 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
targetIds.push(process.argv.splice(targetIndex, 2)[1] as 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: Record<string, DependencyInfo> = {};
const hakDepsCfg = packageJson.hakDependencies || {};
for (const dep in hakDepsCfg) {
const hakJsonPath = path.join(prefix, "hak", dep, "hak.json");
let hakJson: Record<string, any>;
try {
hakJson = loadJsonFile(hakJsonPath);
} catch {
console.error("No hak.json found for " + dep + ".");
console.log("Expecting " + hakJsonPath);
process.exit(1);
}
deps[dep] = {
name: dep,
version: hakDepsCfg[dep as keyof typeof hakDepsCfg],
cfg: hakJson,
moduleHakDir: path.join(prefix, "hak", dep),
moduleDotHakDir: path.join(hakEnv.dotHakDir, dep),
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, hakEnv.getTargetId(), "build", "node_modules", ".bin"),
depPrefix: path.join(hakEnv.dotHakDir, dep, hakEnv.getTargetId(), "opt"),
scripts: {},
};
for (const s of HAKSCRIPTS) {
if (hakJson.scripts?.[s]) {
// Shockingly, using path.join and backslashes here doesn't work on Windows
const scriptModule = await import(`../../hak/${dep}/${hakJson.scripts[s]}`);
if (scriptModule.default) {
deps[dep].scripts[s] = scriptModule.default;
} else {
deps[dep].scripts[s] = scriptModule;
}
}
}
}
let cmds: string[];
if (process.argv.length < 3) {
cmds = ["check", "fetch", "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);
for (const cmd of cmds) {
if (GENERALCOMMANDS.includes(cmd)) {
if (cmd === "target") {
console.log(hakEnv.getNodeTriple());
}
return;
}
if (!MODULECOMMANDS.includes(cmd)) {
console.error("Unknown command: " + cmd);
console.log("Commands I know about:");
for (const cmd of MODULECOMMANDS) {
console.log("\t" + cmd);
}
process.exit(1);
}
const cmdFunc = (await import("./" + cmd)).default;
for (const mod of modules) {
const depInfo = deps[mod];
if (depInfo === undefined) {
console.log("Module " + mod + " not found - is it in hakDependencies " + "in your package.json?");
process.exit(1);
}
console.log("hak " + cmd + ": " + mod);
await cmdFunc(hakEnv, depInfo);
}
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

View File

@@ -1,47 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2020 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import path from "node:path";
import os from "node:os";
import fsProm from "node:fs/promises";
import HakEnv from "./hakEnv.js";
import { DependencyInfo } from "./dep.js";
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.
// We just check to see if there is a local .yarnrc at all, and assume that
// if you've put one there yourself, you probably know what you're doing and
// we won't meddle with it.
// Also we do this for each module which is unnecessary, but meh.
try {
await fsProm.stat(yarnrc);
} catch {
await fsProm.writeFile(
yarnrc,
// XXX: 1. This must be absolute, as yarn will resolve link directories
// relative to the closest project root, which means when we run it
// in the dependency project, it will put the link directory in its
// own project folder rather than the main project.
// 2. The parser gets very confused by strings with colons in them
// (ie. Windows absolute paths) but strings in quotes get parsed as
// JSON so need to be valid JSON encoded strings (ie. have the
// backslashes escaped). JSON.stringify will add quotes and escape.
"--link-folder " + JSON.stringify(path.join(hakEnv.dotHakDir, "links")) + os.EOL,
);
}
await hakEnv.spawn("yarn", ["link"], {
cwd: moduleInfo.moduleOutDir,
});
await hakEnv.spawn("yarn", ["link", moduleInfo.name], {
cwd: hakEnv.projectRoot,
});
}

View File

@@ -1,217 +0,0 @@
/*
Copyright 2024 New Vector Ltd.
Copyright 2021 The Matrix.org Foundation C.I.C.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import { GLIBC, MUSL, familySync as processLibC } from "detect-libc";
// 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"
| "aarch64-pc-windows-msvc"
| "i686-unknown-freebsd"
| "x86_64-unknown-freebsd"
| "aarch64-unknown-freebsd"
| "i686-unknown-linux-musl"
| "i686-unknown-linux-gnu"
| "x86_64-unknown-linux-musl"
| "x86_64-unknown-linux-gnu"
| "aarch64-unknown-linux-musl"
| "aarch64-unknown-linux-gnu"
| "powerpc64le-unknown-linux-musl"
| "powerpc64le-unknown-linux-gnu";
// Values are expected to match those used in `process.platform`.
export type Platform = "darwin" | "freebsd" | "linux" | "win32";
// Values are expected to match those used in `process.arch`.
export type Arch = "arm64" | "ia32" | "x64" | "ppc64" | "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 LinuxTarget = Target & {
platform: "linux";
libC: typeof GLIBC | typeof MUSL;
};
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 aarch64WindowsMsvc: WindowsTarget = {
id: "aarch64-pc-windows-msvc",
platform: "win32",
arch: "arm64",
vcVarsArch: "arm64",
};
const i686UnknownFreebsd: Target = {
id: "i686-unknown-freebsd",
platform: "freebsd",
arch: "ia32",
};
const x8664UnknownFreebsd: Target = {
id: "x86_64-unknown-freebsd",
platform: "freebsd",
arch: "x64",
};
const aarch64UnknownFreebsd: Target = {
id: "aarch64-unknown-freebsd",
platform: "freebsd",
arch: "arm64",
};
const x8664UnknownLinuxGnu: LinuxTarget = {
id: "x86_64-unknown-linux-gnu",
platform: "linux",
arch: "x64",
libC: GLIBC,
};
const x8664UnknownLinuxMusl: LinuxTarget = {
id: "x86_64-unknown-linux-musl",
platform: "linux",
arch: "x64",
libC: MUSL,
};
const i686UnknownLinuxGnu: LinuxTarget = {
id: "i686-unknown-linux-gnu",
platform: "linux",
arch: "ia32",
libC: GLIBC,
};
const i686UnknownLinuxMusl: LinuxTarget = {
id: "i686-unknown-linux-musl",
platform: "linux",
arch: "ia32",
libC: MUSL,
};
const aarch64UnknownLinuxGnu: LinuxTarget = {
id: "aarch64-unknown-linux-gnu",
platform: "linux",
arch: "arm64",
libC: GLIBC,
};
const aarch64UnknownLinuxMusl: LinuxTarget = {
id: "aarch64-unknown-linux-musl",
platform: "linux",
arch: "arm64",
libC: MUSL,
};
const powerpc64leUnknownLinuxGnu: LinuxTarget = {
id: "powerpc64le-unknown-linux-gnu",
platform: "linux",
arch: "ppc64",
libC: GLIBC,
};
const powerpc64leUnknownLinuxMusl: LinuxTarget = {
id: "powerpc64le-unknown-linux-musl",
platform: "linux",
arch: "ppc64",
libC: MUSL,
};
export const TARGETS: Record<TargetId, Target> = {
// macOS
"aarch64-apple-darwin": aarch64AppleDarwin,
"x86_64-apple-darwin": x8664AppleDarwin,
"universal-apple-darwin": universalAppleDarwin,
// Windows
"i686-pc-windows-msvc": i686PcWindowsMsvc,
"x86_64-pc-windows-msvc": x8664PcWindowsMsvc,
"aarch64-pc-windows-msvc": aarch64WindowsMsvc,
// FreeBSD
"i686-unknown-freebsd": i686UnknownFreebsd,
"x86_64-unknown-freebsd": x8664UnknownFreebsd,
"aarch64-unknown-freebsd": aarch64UnknownFreebsd,
// Linux
"i686-unknown-linux-musl": i686UnknownLinuxMusl,
"i686-unknown-linux-gnu": i686UnknownLinuxGnu,
"x86_64-unknown-linux-musl": x8664UnknownLinuxMusl,
"x86_64-unknown-linux-gnu": x8664UnknownLinuxGnu,
"aarch64-unknown-linux-musl": aarch64UnknownLinuxMusl,
"aarch64-unknown-linux-gnu": aarch64UnknownLinuxGnu,
"powerpc64le-unknown-linux-musl": powerpc64leUnknownLinuxMusl,
"powerpc64le-unknown-linux-gnu": powerpc64leUnknownLinuxGnu,
};
export function getHost(): Target | undefined {
return Object.values(TARGETS).find(
(target) =>
target.platform === process.platform &&
target.arch === process.arch &&
(process.platform !== "linux" || (target as LinuxTarget).libC === processLibC()),
);
}
export function isHostId(id: TargetId): boolean {
return getHost()?.id === id;
}
export function isHost(target: Target): boolean {
return getHost()?.id === target.id;
}

View File

@@ -17,7 +17,6 @@ docker run --rm -ti \
--env ELECTRON_BUILDER_CACHE="/root/.cache/electron-builder" \
-v ${PWD}:/project \
-v ${PWD}/docker/node_modules:/project/node_modules \
-v ${PWD}/docker/.hak:/project/.hak \
-v ${PWD}/docker/.gnupg:/root/.gnupg \
-v ~/.cache/electron:/root/.cache/electron \
-v ~/.cache/electron-builder:/root/.cache/electron-builder \

View File

@@ -5,11 +5,11 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { BrowserWindow } from "electron";
import Store from "electron-store";
import AutoLaunch from "auto-launch";
import { type BrowserWindow } from "electron";
import { AppLocalization } from "../language-helper.js";
import type Store from "electron-store";
import type AutoLaunch from "auto-launch";
import { type AppLocalization } from "../language-helper.js";
// global type extensions need to use var for whatever reason
/* eslint-disable no-var */

View File

@@ -1,54 +0,0 @@
// Based on https://github.com/atom/node-keytar/blob/master/keytar.d.ts because keytar is a hak-dependency and not a normal one
// Definitions by: Milan Burda <https://github.com/miniak>, Brendan Forster <https://github.com/shiftkey>, Hari Juturu <https://github.com/juturu>
// Adapted from DefinitelyTyped: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/keytar/index.d.ts
declare module "keytar" {
/**
* Get the stored password for the service and account.
*
* @param service The string service name.
* @param account The string account name.
*
* @returns A promise for the password string.
*/
export function getPassword(service: string, account: string): Promise<string | null>;
/**
* Add the password for the service and account to the keychain.
*
* @param service The string service name.
* @param account The string account name.
* @param password The string password.
*
* @returns A promise for the set password completion.
*/
export function setPassword(service: string, account: string, password: string): Promise<void>;
/**
* Delete the stored password for the service and account.
*
* @param service The string service name.
* @param account The string account name.
*
* @returns A promise for the deletion status. True on success.
*/
export function deletePassword(service: string, account: string): Promise<boolean>;
/**
* Find a password for the service in the keychain.
*
* @param service The string service name.
*
* @returns A promise for the password string.
*/
export function findPassword(service: string): Promise<string | null>;
/**
* Find all accounts and passwords for `service` in the keychain.
*
* @param service The string service name.
*
* @returns A promise for the array of found credentials.
*/
export function findCredentials(service: string): Promise<Array<{ account: string; password: string }>>;
}

View File

@@ -10,7 +10,7 @@ Please see LICENSE files in the repository root for full details.
// Squirrel on windows starts the app with various flags as hooks to tell us when we've been installed/uninstalled etc.
import "./squirrelhooks.js";
import { app, BrowserWindow, Menu, autoUpdater, protocol, dialog, Input, Event, session } from "electron";
import { app, BrowserWindow, Menu, autoUpdater, protocol, dialog, type Input, type Event, session } from "electron";
// eslint-disable-next-line n/file-extension-in-import
import * as Sentry from "@sentry/electron/main";
import AutoLaunch from "auto-launch";
@@ -22,7 +22,6 @@ import { URL, fileURLToPath } from "node:url";
import minimist from "minimist";
import "./ipc.js";
import "./keytar.js";
import "./seshat.js";
import "./settings.js";
import * as tray from "./tray.js";

63
src/i18n/strings/cy.json Normal file
View File

@@ -0,0 +1,63 @@
{
"action": {
"cancel": "Diddymu",
"close": "Cau",
"close_brand": "Cau %(brand)s",
"copy": "Copïo",
"cut": "Torri",
"delete": "Dileu",
"edit": "Golygu",
"minimise": "Lleihau",
"paste": "Gludo",
"paste_match_style": "Gludo a Chyfateb Arddull",
"quit": "Gadael",
"redo": "Ail-wneud",
"select_all": "Dewis y Cyfan",
"show_hide": "Dangos/Cuddio",
"undo": "Dadwneud",
"zoom_in": "Chwyddo i Mewn",
"zoom_out": "Chwyddo Allan"
},
"common": {
"about": "Ynghylch",
"brand_help": "%(brand)s Cymorth",
"help": "Cymorth",
"preferences": "Dewisiadau"
},
"confirm_quit": "Ydych chi'n siŵr eich bod am roi'r gorau iddi?",
"edit_menu": {
"speech": "Lleferydd",
"speech_start_speaking": "Cychwyn Llefaru",
"speech_stop_speaking": "Peidio Llefaru"
},
"file_menu": {
"label": "Ffeil"
},
"menu": {
"hide": "Cuddio",
"hide_others": "Cuddio'r Gweddill",
"services": "Gwasanaethau",
"unhide": "Datguddio"
},
"right_click_menu": {
"add_to_dictionary": "Ychwanegu i'r Geiriadur",
"copy_email": "Copïo cyfeiriad e-bost",
"copy_image": "Copïo delwedd",
"copy_image_url": "Copïo cyfeiriad delwedd",
"copy_link_url": "Copïo cyfeiriad y ddolen",
"save_image_as": "Cadw delwedd fel...",
"save_image_as_error_description": "Methodd y ddelwedd â chadw",
"save_image_as_error_title": "Wedi methu cadw'r ddelwedd"
},
"view_menu": {
"actual_size": "Maint Gwirioneddol",
"toggle_developer_tools": "Toggle Developer Tools",
"toggle_full_screen": "Toglo Sgrin Lawn",
"view": "Golwg"
},
"window_menu": {
"bring_all_to_front": "Popeth i'r Blaen",
"label": "Ffenestr",
"zoom": "Chwyddo"
}
}

View File

@@ -2,7 +2,7 @@
"action": {
"cancel": "Mégse",
"close": "Bezárás",
"close_brand": "%(brand)s bezárása",
"close_brand": "Az %(brand)s bezárása",
"copy": "Másolás",
"cut": "Kivágás",
"delete": "Törlés",
@@ -56,7 +56,7 @@
"view": "Megtekintés"
},
"window_menu": {
"bring_all_to_front": "Mindent előtérbe hoz",
"bring_all_to_front": "Minden előtérbe hozása",
"label": "Ablak",
"zoom": "Nagyítás"
}

63
src/i18n/strings/ka.json Normal file
View File

@@ -0,0 +1,63 @@
{
"action": {
"cancel": "გაუქმება",
"close": "დახურვა",
"close_brand": "დახურვა %(brand)s",
"copy": "კოპირება",
"cut": "მოჭრა",
"delete": "წაშალეთ",
"edit": "რედაქტირება",
"minimise": "შეამცირეთ",
"paste": "პასტა",
"paste_match_style": "ჩასვით და მატჩის სტილი",
"quit": "თავი დაანებე",
"redo": "რედო",
"select_all": "აირჩიეთ ყველა",
"show_hide": "ჩვენება/დამალვა",
"undo": "გაუქმება",
"zoom_in": "გაზარდოთ",
"zoom_out": "გაფართოება"
},
"common": {
"about": "შესახებ",
"brand_help": "%(brand)sდახმარება",
"help": "დახმარება",
"preferences": "პრეფერენციები"
},
"confirm_quit": "დარწმუნებული ხართ, რომ გსურთ დატოვება?",
"edit_menu": {
"speech": "გამოსვლა",
"speech_start_speaking": "დაიწყეთ საუბარი",
"speech_stop_speaking": "შეწყვიტე ლაპარ"
},
"file_menu": {
"label": "ფაილი"
},
"menu": {
"hide": "დამალვა",
"hide_others": "სხვების დამალვა",
"services": "მომსახურება",
"unhide": "გამოხატე"
},
"right_click_menu": {
"add_to_dictionary": "ლექსიკონში დამატება",
"copy_email": "ელ. ფოსტის მისამართის",
"copy_image": "სურათის დაკოპირება",
"copy_image_url": "გამოსახულების მისამართის კოპირ",
"copy_link_url": "ბმულის მისამართის კოპირება",
"save_image_as": "შეინახეთ სურათი როგორც...",
"save_image_as_error_description": "სურათის შენახვა ვერ შეძლო",
"save_image_as_error_title": "სურათის შენახვა ვერ შეძლ"
},
"view_menu": {
"actual_size": "რეალური ზომა",
"toggle_developer_tools": "დეველოპერის ინსტრუმენტების",
"toggle_full_screen": "სრული ეკრანის გადართვა",
"view": "ნახვა"
},
"window_menu": {
"bring_all_to_front": "ყველაფერი წინ წამოიყვანეთ",
"label": "ფანჯარა",
"zoom": "გაზუსტება"
}
}

63
src/i18n/strings/lv.json Normal file
View File

@@ -0,0 +1,63 @@
{
"action": {
"cancel": "Atcelt",
"close": "Aizvērt",
"close_brand": "Aizvērt %(brand)s",
"copy": "Kopēt",
"cut": "Izgriezt",
"delete": "Dzēst",
"edit": "Labot",
"minimise": "Samazināt",
"paste": "Ielīmēt",
"paste_match_style": "Ielīmēt un pielāgot stilu",
"quit": "Iziet",
"redo": "Atatsaukt",
"select_all": "Atzīmēt visu",
"show_hide": "Parādīt/paslēpt",
"undo": "Atsaukt",
"zoom_in": "Tuvināt",
"zoom_out": "Tālināt"
},
"common": {
"about": "Par",
"brand_help": "%(brand)s palīdzība",
"help": "Palīdzība",
"preferences": "Iestatījumi"
},
"confirm_quit": "Vai tiešām iziet?",
"edit_menu": {
"speech": "Runa",
"speech_start_speaking": "Uzsākt runāšanu",
"speech_stop_speaking": "Pārtraukt runāšanu"
},
"file_menu": {
"label": "Datne"
},
"menu": {
"hide": "Paslēpt",
"hide_others": "Paslēpt citus",
"services": "Pakalpojumi",
"unhide": "Rādīt"
},
"right_click_menu": {
"add_to_dictionary": "Pievienot vārdnīcai",
"copy_email": "Ievietot e-pasta adresi starpliktuvē",
"copy_image": "Ievietot attēlu starpliktuvē",
"copy_image_url": "Ievietot attēla adresi starpliktuvē",
"copy_link_url": "Ievietot saites adresi starpliktuvē",
"save_image_as": "Saglabāt attēlu kā...",
"save_image_as_error_description": "Attēlu neizdevās saglabāt",
"save_image_as_error_title": "Neizdevās saglabāt attēlu"
},
"view_menu": {
"actual_size": "Īstais izmērs",
"toggle_developer_tools": "Pārslēgt izstrādātāja rīkus",
"toggle_full_screen": "Pārslēgt pilnekrānu",
"view": "Skats"
},
"window_menu": {
"bring_all_to_front": "Iznest visu priekšplānā",
"label": "Logs",
"zoom": "Tālummaiņa"
}
}

View File

@@ -0,0 +1,63 @@
{
"action": {
"cancel": "Hanafoana",
"close": "Akatona",
"close_brand": "Anakatona%(brand)s",
"copy": "Dika Mitovy",
"cut": "Tapaina",
"delete": "Fafaina",
"edit": "Anova",
"minimise": "Manamaivana",
"paste": "Koba",
"paste_match_style": "Mametaka sy Mampifanandrify ny fomba",
"quit": "Mialà",
"redo": "Averina atao",
"select_all": "Isafidy ny rehetra",
"show_hide": "Aneho/Anafina",
"undo": "Ravao",
"zoom_in": "Angedao",
"zoom_out": "Hahelezo"
},
"common": {
"about": "Mombamomba",
"brand_help": "%(marques)Fanampiana",
"help": "Fanampiana",
"preferences": "Safidy manokana"
},
"confirm_quit": "Azo Antoka ve fa tena hiala ianao",
"edit_menu": {
"speech": "Fitenenana",
"speech_start_speaking": "Atomboy ny resaka/Manomboha fitenenena",
"speech_stop_speaking": "Atsaharo ny fitenenana"
},
"file_menu": {
"label": "Manapetraka/apetrao"
},
"menu": {
"hide": "Afeno",
"hide_others": "Afeno ny hafa",
"services": "Tolotra",
"unhide": "Asehoy"
},
"right_click_menu": {
"add_to_dictionary": "Ampio ao amin'ny rakibolana",
"copy_email": "Adikao ny adiresy imailaka",
"copy_image": "Andika ny sary",
"copy_image_url": "Adikao ny adiresin'ny sary",
"copy_link_url": "Adikao ny adiresy rohy",
"save_image_as": "Hitahiry ny sary ho",
"save_image_as_error_description": "Tsy voatahiry ilay sary",
"save_image_as_error_title": "Tsy nahahomby ny fitahirizana an'ilay sary"
},
"view_menu": {
"actual_size": "Habe Ankehitriny",
"toggle_developer_tools": "Amadika fitaovana fampandrosoana",
"toggle_full_screen": "Hamadika amin'ny efijery feno",
"view": "Hijery"
},
"window_menu": {
"bring_all_to_front": "Ataovy aloha ny zava-drehetra",
"label": "Varavarankely",
"zoom": "Anakaiky fahitana"
}
}

View File

@@ -0,0 +1,63 @@
{
"action": {
"cancel": "Avbryt",
"close": "Lukk",
"close_brand": "Avslutt %(brand)s",
"copy": "Kopier",
"cut": "Klipp",
"delete": "Slett",
"edit": "Rediger",
"minimise": "Minimere",
"paste": "Lim inn",
"paste_match_style": "Lim inn og match stil",
"quit": "Avslutt",
"redo": "Gjør om",
"select_all": "Velg alle",
"show_hide": "Vis/Skjul",
"undo": "Angre",
"zoom_in": "Zoom inn",
"zoom_out": "Zoom ut"
},
"common": {
"about": "Om",
"brand_help": "%(brand)s Hjelp",
"help": "Hjelp",
"preferences": "Brukervalg"
},
"confirm_quit": "Er du sikker på at du vil slutte?",
"edit_menu": {
"speech": "Tale",
"speech_start_speaking": "Begynn å snakke",
"speech_stop_speaking": "Slutt å snakke"
},
"file_menu": {
"label": "Fil"
},
"menu": {
"hide": "Skjul",
"hide_others": "Skjul andre",
"services": "Tjenester",
"unhide": "Slutt å skjule"
},
"right_click_menu": {
"add_to_dictionary": "Legg til i ordbok",
"copy_email": "Kopier e-postadressen",
"copy_image": "Kopier bildet",
"copy_image_url": "Kopier bildeadresse",
"copy_link_url": "Kopier link adresse",
"save_image_as": "Lagre bildet som...",
"save_image_as_error_description": "Bildet kunne ikke lagres",
"save_image_as_error_title": "Kunne ikke lagre bildet"
},
"view_menu": {
"actual_size": "Faktisk størrelse",
"toggle_developer_tools": "Veksle Utvikleralternativer",
"toggle_full_screen": "Veksle Fullskjerm",
"view": "Vis"
},
"window_menu": {
"bring_all_to_front": "Flytt Alt Frem",
"label": "Vindu",
"zoom": "Forstørr"
}
}

View File

@@ -20,6 +20,7 @@
},
"common": {
"about": "Sobre",
"brand_help": "%(brand)s Ajuda",
"help": "Ajuda",
"preferences": "Preferências"
},
@@ -56,6 +57,7 @@
},
"window_menu": {
"bring_all_to_front": "Trazer Todas Para Frente",
"label": "Janela"
"label": "Janela",
"zoom": "Zoom"
}
}

63
src/i18n/strings/tr.json Normal file
View File

@@ -0,0 +1,63 @@
{
"action": {
"cancel": "İptal",
"close": "Kapat",
"close_brand": "Kapat %(brand)s",
"copy": "Kopyala",
"cut": "Kes",
"delete": "Sil",
"edit": "Düzenle",
"minimise": "Küçült",
"paste": "Yapıştır",
"paste_match_style": "Stili Yapıştır ve Eşleştir",
"quit": ık",
"redo": "Yeniden yap",
"select_all": "Tümünü seç",
"show_hide": "Göster/Gizle",
"undo": "Geri al",
"zoom_in": "Yakınlaştır",
"zoom_out": "Uzaklaştır"
},
"common": {
"about": "Hakkında",
"brand_help": "%(brand)s Yardım",
"help": "Yardım",
"preferences": "Tercihler"
},
"confirm_quit": ıkmak istediğinizden emin misiniz?",
"edit_menu": {
"speech": "Konuşma",
"speech_start_speaking": "Konuşmaya başla",
"speech_stop_speaking": "Konuşmayı durdur"
},
"file_menu": {
"label": "Dosya"
},
"menu": {
"hide": "Gizle",
"hide_others": "Diğerlerini gizle",
"services": "Hizmetler",
"unhide": "Göster"
},
"right_click_menu": {
"add_to_dictionary": "Sözlüğe ekle",
"copy_email": "E-posta adresini kopyala",
"copy_image": "Resmi kopyala",
"copy_image_url": "Görsel adresini kopyala",
"copy_link_url": "Bağlantılı adresi kopyala",
"save_image_as": "Resmi farklı kaydet...",
"save_image_as_error_description": "Görüntü kaydedilemedi",
"save_image_as_error_title": "Resim kaydedilemedi"
},
"view_menu": {
"actual_size": "Gerçek boyut",
"toggle_developer_tools": "Geliştirici araçları",
"toggle_full_screen": "Tam ekran",
"view": "Görüntüle"
},
"window_menu": {
"bring_all_to_front": "Hepsini öne getir",
"label": "Pencere",
"zoom": "Yaklaştır"
}
}

View File

@@ -6,13 +6,13 @@ Please see LICENSE files in the repository root for full details.
*/
import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron";
import { relaunchApp } from "electron-clear-data";
import { relaunchApp } from "@standardnotes/electron-clear-data";
import keytar from "keytar-forked";
import IpcMainEvent = Electron.IpcMainEvent;
import { recordSSOSession } from "./protocol.js";
import { randomArray } from "./utils.js";
import { Settings } from "./settings.js";
import { keytar } from "./keytar.js";
import { getDisplayMediaCallback, setDisplayMediaCallback } from "./displayMediaCallback.js";
ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void {
@@ -141,11 +141,11 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
case "getPickleKey":
try {
ret = await keytar?.getPassword("element.io", `${args[0]}|${args[1]}`);
ret = await keytar.getPassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im)
if (ret === null) {
ret = await keytar?.getPassword("riot.im", `${args[0]}|${args[1]}`);
ret = await keytar.getPassword("riot.im", `${args[0]}|${args[1]}`);
}
} catch {
// if an error is thrown (e.g. keytar can't connect to the keychain),
@@ -161,17 +161,18 @@ ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
// rather than sending them a pickle key we did not store on their behalf.
await keytar!.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
ret = pickleKey;
} catch {
} catch (e) {
console.error("Failed to create pickle key", e);
ret = null;
}
break;
case "destroyPickleKey":
try {
await keytar?.deletePassword("element.io", `${args[0]}|${args[1]}`);
await keytar.deletePassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be
// logins from the time of riot.im)
await keytar?.deletePassword("riot.im", `${args[0]}|${args[1]}`);
await keytar.deletePassword("riot.im", `${args[0]}|${args[1]}`);
} catch {}
break;
case "getDesktopCapturerSources":

View File

@@ -1,21 +0,0 @@
/*
Copyright 2022-2024 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import type * as Keytar from "keytar"; // Hak dependency type
let keytar: typeof Keytar | undefined;
try {
({ default: keytar } = await import("keytar"));
} catch (e) {
if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
console.log("Keytar isn't installed; secure key storage is disabled.");
} else {
console.warn("Keytar unexpected error:", e);
}
}
export { keytar };

View File

@@ -6,7 +6,7 @@ Please see LICENSE files in the repository root for full details.
*/
import counterpart from "counterpart";
import { TranslationKey as TKey } from "matrix-web-i18n";
import { type TranslationKey as TKey } from "matrix-web-i18n";
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";

View File

@@ -8,6 +8,7 @@ Please see LICENSE files in the repository root for full details.
import { app, ipcMain } from "electron";
import { promises as afs } from "node:fs";
import path from "node:path";
import keytar from "keytar-forked";
import type {
Seshat as SeshatType,
@@ -16,7 +17,6 @@ import type {
} from "matrix-seshat"; // Hak dependency type
import IpcMainEvent = Electron.IpcMainEvent;
import { randomArray } from "./utils.js";
import { keytar } from "./keytar.js";
let seshatSupported = false;
let Seshat: typeof SeshatType;

View File

@@ -6,7 +6,7 @@ SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Com
Please see LICENSE files in the repository root for full details.
*/
import { app, shell, Menu, MenuItem, MenuItemConstructorOptions } from "electron";
import { app, shell, Menu, type MenuItem, type MenuItemConstructorOptions } from "electron";
import { _t } from "./language-helper.js";

View File

@@ -13,13 +13,13 @@ import {
shell,
dialog,
ipcMain,
NativeImage,
WebContents,
ContextMenuParams,
DownloadItem,
MenuItemConstructorOptions,
IpcMainEvent,
Event,
type NativeImage,
type WebContents,
type ContextMenuParams,
type DownloadItem,
type MenuItemConstructorOptions,
type IpcMainEvent,
type Event,
} from "electron";
import url from "node:url";
import fs from "node:fs";

1856
yarn.lock
View File

File diff suppressed because it is too large Load Diff