Compare commits

...

288 Commits

Author SHA1 Message Date
RiotRobot
3d215dc777 Merge branch 'master' into develop 2023-04-11 14:35:13 +01:00
RiotRobot
bbaca4413e v1.11.29 2023-04-11 14:34:54 +01:00
RiotRobot
54d1c138c7 Prepare changelog for v1.11.29 2023-04-11 14:34:54 +01:00
renovate[bot]
5e9301bdf1 Lock file maintenance (#623)
* Lock file maintenance

* Lock file maintenance

* Claw back minipass from 4.2.7 which is broken

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2023-04-11 11:19:12 +00:00
renovate[bot]
1a99740bc8 Update dependency glob to v9 (#575)
* Update dependency glob to v9

* Adjust copy.ts to promisifed glob

* Switch asar -> @electron/asar

* Update rimraf for glob v9 compatibility

* Iterate

* Iterate

* Patch @electron/asar

* Fix another way

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Janne Mareike Koschinski <jannemk@element.io>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2023-04-06 12:41:38 +00:00
renovate[bot]
cf24a95d31 Update dependency electron to v24 (#611)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-06 13:31:04 +01:00
renovate[bot]
07341a0498 Update jest monorepo to v29.5.0 (#571)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-06 11:50:50 +01:00
Michael Telatynski
f6acfb8778 Update pull_request.yaml 2023-04-06 10:41:49 +01:00
renovate[bot]
417e41668c Update dependency playwright to v1.32.1 (#621)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-06 09:12:28 +00:00
renovate[bot]
e014ccc653 Update babel monorepo to v7.21.4 (#616)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-06 08:47:49 +00:00
renovate[bot]
34d1c6fc24 Update dependency @types/node to v16.18.23 (#617)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-06 08:06:04 +00:00
renovate[bot]
fdfeb0454f Update dependency typescript to v5 (#612)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-05 20:07:37 +00:00
renovate[bot]
1ec6c6e5db Update typescript-eslint monorepo to v5.57.1 (#618)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-05 19:08:25 +00:00
renovate[bot]
8be59eba56 Update all non-major dependencies (#619)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-04-05 17:31:39 +00:00
Michael Telatynski
8b16f2d0d9 Fix error when breadcrumb image fails to load (#609) 2023-04-05 10:56:12 +00:00
RiotRobot
ce2ce8bea1 v1.11.29-rc.1 2023-04-04 12:18:48 +01:00
RiotRobot
7c3e0f4d99 Prepare changelog for v1.11.29-rc.1 2023-04-04 12:18:48 +01:00
Andy Balaam
224bccaf95 Merge pull request #608 from RiotTranslateBot/weblate-element-desktop-element-desktop
Translations update from Weblate
2023-04-04 11:41:37 +01:00
Weblate
e7e8c8e81a Merge branch 'origin/develop' into Weblate. 2023-04-04 08:09:29 +00:00
Michael Telatynski
f24e90b927 Update windows-requirements.md 2023-04-04 09:09:25 +01:00
Weblate
39b2ca0bc1 Merge branch 'origin/develop' into Weblate. 2023-04-03 15:31:20 +00:00
Michael Telatynski
077a58a2e8 Fix wrong sqlcipher build being used due to cache conflict (#606) 2023-04-03 15:31:14 +00:00
Weblate
03161c7433 Merge branch 'origin/develop' into Weblate. 2023-04-03 14:21:11 +00:00
Michael Telatynski
7c0f11914b Add grep to dockerbuild image (#607) 2023-04-03 14:21:04 +00:00
Weblate
119fdc2db3 Merge branch 'origin/develop' into Weblate. 2023-04-03 08:50:25 +00:00
Michael Telatynski
06d6f11670 Prefer env for passing github context vars (#590) 2023-04-03 08:50:20 +00:00
Weblate
9334d87ad8 Merge branch 'origin/develop' into Weblate. 2023-04-03 08:32:41 +00:00
Michael Telatynski
50d38e2abd Use branch specific linux dockerbuild tags (#601) 2023-04-03 09:32:37 +01:00
sefidel
3846f45529 Translated using Weblate (Korean)
Currently translated at 22.2% (10 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/ko/
2023-04-03 02:33:48 +00:00
sefidel
df66db90f5 Added translation using Weblate (Korean) 2023-04-02 02:24:55 +00:00
Weblate
b22d6640c2 Merge branch 'origin/develop' into Weblate. 2023-03-31 18:13:59 +00:00
Michael Telatynski
0663de091f Enable CodeQL (#603) 2023-03-31 19:13:55 +01:00
Weblate
9cb3e2b551 Merge branch 'origin/develop' into Weblate. 2023-03-31 15:17:48 +00:00
Michael Telatynski
5bd1c663e2 Use frozen lockfile instead of pure lockfile on yarn install (#605) 2023-03-31 15:17:43 +00:00
Weblate
20f9a8daf8 Merge branch 'origin/develop' into Weblate. 2023-03-31 14:42:47 +00:00
RiotRobot
19fd0b99f5 Merge branch 'master' into develop 2023-03-31 15:41:56 +01:00
RiotRobot
60171c780c v1.11.28 2023-03-31 15:39:31 +01:00
RiotRobot
75276cff7b Prepare changelog for v1.11.28 2023-03-31 15:39:31 +01:00
RiotRobot
266fc707b0 Fix broken lockfile element-web/issues/25008 2023-03-31 15:23:40 +01:00
Weblate
81a5ba677a Merge branch 'origin/develop' into Weblate. 2023-03-31 12:12:10 +00:00
RiotRobot
2ca8b7be61 Merge branch 'master' into develop 2023-03-31 12:44:40 +01:00
RiotRobot
349b5e0081 v1.11.27 2023-03-31 11:24:13 +01:00
RiotRobot
09923b3fe4 Prepare changelog for v1.11.27 2023-03-31 11:24:12 +01:00
Weblate
034bbcfa46 Merge branch 'origin/develop' into Weblate. 2023-03-31 10:00:36 +00:00
Michael Telatynski
c10e666dad Ship linux tarball with static sqlcipher (#597) 2023-03-31 11:00:30 +01:00
RiotRobot
a479c8607b Merge branch 'master' into staging 2023-03-31 10:56:21 +01:00
Andy Balaam
ae1998a024 Merge pull request #602 from vector-im/backport-599-to-staging
Run build_linux in docker using an older glibc (#599)
2023-03-31 09:55:01 +01:00
Weblate
f0c7f615ee Merge branch 'origin/develop' into Weblate. 2023-03-31 08:45:38 +00:00
renovate[bot]
743f5dc5de Update typescript-eslint monorepo to v5.57.0 (#538)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-31 09:45:33 +01:00
Michael Telatynski
ba45d84771 Run build_linux in docker using an older glibc (#599)
(cherry picked from commit 718d5a8037)
2023-03-31 09:24:02 +01:00
Weblate
675798b4c9 Merge branch 'origin/develop' into Weblate. 2023-03-31 08:18:18 +00:00
Michael Telatynski
f8aba49155 Enable gatekeeperAssess (#600) 2023-03-31 09:18:13 +01:00
Weblate
389e744cf1 Merge branch 'origin/develop' into Weblate. 2023-03-31 07:50:18 +00:00
renovate[bot]
439760f8ee Update dependency @types/node to v16.18.21 (#569)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-31 08:50:13 +01:00
Weblate
9048af7003 Merge branch 'origin/develop' into Weblate. 2023-03-30 13:23:04 +00:00
Michael Telatynski
718d5a8037 Run build_linux in docker using an older glibc (#599) 2023-03-30 14:22:58 +01:00
Weblate
dd66fb8010 Merge branch 'origin/develop' into Weblate. 2023-03-30 12:54:50 +00:00
Michael Telatynski
a9cffb8ce5 Automate pushing dockerbuild image to ghcr.io (#598) 2023-03-30 13:54:45 +01:00
Weblate
f703771a00 Merge branch 'origin/develop' into Weblate. 2023-03-29 13:23:40 +00:00
Michael Telatynski
40058d36c4 Remove element-builder specific scripts (#586) 2023-03-29 14:23:34 +01:00
Weblate
e00144015f Merge branch 'origin/develop' into Weblate. 2023-03-29 13:07:42 +00:00
Andy Balaam
762881bd8a Merge pull request #595 from vector-im/andybalaam/changelog-for-1-11-26
Update changelog for v1.11.26 now the security issue is public
2023-03-29 14:07:35 +01:00
Andy Balaam
2787266d48 Update changelog for v1.11.26 now the security issue is public 2023-03-28 21:01:53 +01:00
Andy Balaam
62e6851250 Backport package.json changes from develop 2023-03-28 17:32:29 +01:00
Michael Telatynski
201000da39 Backport more build config to master 2023-03-28 16:38:57 +01:00
Michael Telatynski
38ccd77b81 Backport packaging scripts to master 2023-03-28 16:16:24 +01:00
Weblate
61dd2e3ce4 Merge branch 'origin/develop' into Weblate. 2023-03-28 13:50:47 +00:00
waclaw66
55841e4d4d Translated using Weblate (Czech)
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/cs/
2023-03-28 13:50:47 +00:00
RiotRobot
694015f7db Merge branch 'master' into develop 2023-03-28 14:50:40 +01:00
RiotRobot
722e5ff0ac v1.11.26 2023-03-28 14:50:26 +01:00
RiotRobot
425f3186b8 Prepare changelog for v1.11.26 2023-03-28 14:50:25 +01:00
waclaw66
dd26855c15 Added translation using Weblate (Czech) 2023-03-28 08:20:06 +00:00
Claudio Satriano
b7b3708b0b Translated using Weblate (Italian)
Currently translated at 95.5% (43 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/it/
2023-03-24 15:15:44 +00:00
Weblate
4384e9b506 Merge branch 'origin/develop' into Weblate. 2023-03-23 17:03:44 +00:00
Michael Telatynski
f23892f54d Fix typo in github actions workflow (#589) 2023-03-23 17:03:39 +00:00
Weblate
7fb557cf3d Merge branch 'origin/develop' into Weblate. 2023-03-23 16:49:06 +00:00
Michael Telatynski
540bd91966 Update updates.md 2023-03-23 16:49:01 +00:00
Weblate
56cab854fc Merge branch 'origin/develop' into Weblate. 2023-03-23 15:17:13 +00:00
Michael Telatynski
f8d331c656 Switch to live R2 bucket for github actions packaging (#588) 2023-03-23 15:17:07 +00:00
Weblate
6e254a761b Merge branch 'origin/develop' into Weblate. 2023-03-23 13:22:35 +00:00
Michael Telatynski
1654030c5f Iterate ARM support in CI (#587) 2023-03-23 13:22:29 +00:00
Weblate
f34bcca76d Merge branch 'origin/develop' into Weblate. 2023-03-22 09:41:56 +00:00
Michael Telatynski
7a1a0fabdb Add support for Windows arm64 (#423) 2023-03-22 09:41:51 +00:00
Weblate
440c9862f1 Merge branch 'origin/develop' into Weblate. 2023-03-22 09:40:43 +00:00
Michael Telatynski
204945299e Use notarize support built into electron-builder (#558) 2023-03-22 09:40:39 +00:00
Weblate
2e0c0becd5 Merge branch 'origin/develop' into Weblate. 2023-03-22 09:31:48 +00:00
Michael Telatynski
3b08d4fa43 Show recent room breadcrumbs on touchbar (#183) 2023-03-22 09:31:42 +00:00
Weblate
75aa07a128 Merge branch 'origin/develop' into Weblate. 2023-03-20 08:22:05 +00:00
Michael Telatynski
775b03572c Correctly specify minimum Node version (#582) 2023-03-20 09:22:00 +01:00
Weblate
41c0be9761 Merge branch 'origin/develop' into Weblate. 2023-03-20 08:17:39 +00:00
Michael Telatynski
74579317db Switch to production ssl.com cert (#585) 2023-03-20 08:17:34 +00:00
Weblate
9ed1018f1b Merge branch 'origin/develop' into Weblate. 2023-03-17 15:33:24 +00:00
Michael Telatynski
18d80e4e9c Clear electron data when logging out (#578) 2023-03-17 15:33:19 +00:00
Weblate
d9eeeabbb4 Merge branch 'origin/develop' into Weblate. 2023-03-17 15:17:33 +00:00
Michael Telatynski
c560bb2de7 Update GPG keyring with extended validity period (#584) 2023-03-17 15:17:29 +00:00
Weblate
a276cf26c7 Merge branch 'origin/develop' into Weblate. 2023-03-16 10:31:11 +00:00
Michael Telatynski
8235275d2c Send Electron crashpad reports to Sentry from Nightly (#579)
* Send Electron crashpad reports to Sentry from Nightly

* Update electron-main.ts

* Increase timeout

* Fix preload injection breaking things

* Iterate

* Iterate

* Iterate

* iterate
2023-03-16 10:31:06 +00:00
Weblate
0d7547a417 Merge branch 'origin/develop' into Weblate. 2023-03-16 10:14:00 +00:00
Michael Telatynski
3d578e815a Fix reprepro test ipv4 vs ipv6 (#581) 2023-03-16 10:13:55 +00:00
Weblate
e302bb7fc3 Merge branch 'origin/develop' into Weblate. 2023-03-15 13:57:40 +00:00
RiotRobot
6cfbd2e932 Merge branch 'master' into develop 2023-03-15 13:57:34 +00:00
Andy Balaam
34ccea0378 Fix changelog for 1.11.25
Auto-generated changelog was accidentally committed. Replacing with the
correct one.
2023-03-15 13:50:04 +00:00
Weblate
4c1373dcb0 Merge branch 'origin/develop' into Weblate. 2023-03-15 13:46:54 +00:00
Andy Balaam
c80763c7b7 Merge pull request #580 from vector-im/andybalaam/update-changelog-1.11.25
Fix changelog for 1.11.25
2023-03-15 13:46:48 +00:00
Andy Balaam
a440bc89ec Fix changelog for 1.11.25
Auto-generated changelog was accidentally committed. Replacing with the
correct one.
2023-03-15 13:20:25 +00:00
Weblate
790afe42cb Merge branch 'origin/develop' into Weblate. 2023-03-15 13:14:48 +00:00
RiotRobot
ef91afa057 Merge branch 'master' into develop 2023-03-15 13:14:42 +00:00
RiotRobot
bb0ccfdbab v1.11.25 2023-03-15 13:14:27 +00:00
RiotRobot
5aec4945f9 Prepare changelog for v1.11.25 2023-03-15 13:14:26 +00:00
RiotRobot
51941ed766 v1.11.25-rc.3 2023-03-14 11:50:28 +00:00
RiotRobot
b503dcd9ef Prepare changelog for v1.11.25-rc.3 2023-03-14 11:50:27 +00:00
Weblate
a591b980f8 Merge branch 'origin/develop' into Weblate. 2023-03-14 11:16:50 +00:00
renovate[bot]
c9110bc3e4 Update all non-major dependencies (#568)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-14 11:16:45 +00:00
Open Culture Foundation
391e10abab Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/zh_Hant/
2023-03-14 00:33:44 +00:00
Weblate
6d12148db2 Merge branch 'origin/develop' into Weblate. 2023-03-13 08:24:05 +00:00
renovate[bot]
33429a4b1b Update dependency @aws-sdk/client-s3 to v3.288.0 (#577)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-13 08:24:00 +00:00
Weblate
67dd6b90b6 Merge branch 'origin/develop' into Weblate. 2023-03-12 20:28:20 +00:00
renovate[bot]
e1190a2210 Update dependency playwright to v1.31.2 (#570)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-12 20:28:16 +00:00
Weblate
03864ebc4f Merge branch 'origin/develop' into Weblate. 2023-03-12 19:43:10 +00:00
renovate[bot]
1b6c9092f5 Update dependency eslint-plugin-unicorn to v46 (#574)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-13 08:43:06 +13:00
Open Culture Foundation
b8606103be Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/zh_Hant/
2023-03-12 16:33:42 +00:00
Peter Chen
fc2add64cb Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/zh_Hant/
2023-03-10 17:33:41 +00:00
RiotRobot
9926ebe89e v1.11.25-rc.2 2023-03-10 15:20:00 +00:00
RiotRobot
ad08b96905 Prepare changelog for v1.11.25-rc.2 2023-03-10 15:20:00 +00:00
ElementRobot
b558bec1b5 [Backport staging] Recommend element-io-archive-keyring from our Debian package (#567)
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2023-03-10 09:52:05 +00:00
Michael Telatynski
8b110b621f Recommend element-io-archive-keyring from our Debian package (#566) 2023-03-10 09:21:02 +00:00
Michael Telatynski
14fb3f5ce4 Rename control to control 2023-03-09 10:28:53 +00:00
Michael Telatynski
2bb999ebb6 Build element-io-archive-keyring package (#565) 2023-03-09 10:26:37 +00:00
renovate[bot]
104d985c24 Update babel monorepo to v7.21.0 (#554)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-08 08:17:47 +00:00
Michael Telatynski
22fe702b83 Include changelogs in deb package (#563)
* Initial attempt at custom Debian changelogs

* Iterate

* Quotes...

* Iterate

* facepalm

* Iterate

* Remove reundant line

* Ifs

* Test

* Iterate

* Iterate

* Brackets

* inconsistent?

* Update build_and_test.yaml

* Update build_and_test.yaml
2023-03-07 15:53:53 +00:00
RiotRobot
fa6e7ce0a5 v1.11.25-rc.1 2023-03-07 12:09:39 +00:00
RiotRobot
32c5ab7df3 Prepare changelog for v1.11.25-rc.1 2023-03-07 12:09:38 +00:00
Andy Balaam
25af58e86f Merge pull request #564 from RiotTranslateBot/weblate-element-desktop-element-desktop
Translations update from Weblate
2023-03-07 10:47:15 +00:00
Weblate
9fb00348c4 Merge branch 'origin/develop' into Weblate. 2023-03-06 08:57:02 +00:00
Michael Telatynski
126d2c336b Assert release & nightly builds are signed, notarised & accessible before deployment (#559) 2023-03-06 08:56:49 +00:00
Weblate
91576f3939 Merge branch 'origin/develop' into Weblate. 2023-03-05 23:05:12 +00:00
renovate[bot]
383793640d Update dependency @aws-sdk/client-s3 to v3.281.0 (#550)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-03-06 12:05:08 +13:00
Open Culture Foundation
fe74834456 Translated using Weblate (Chinese (Traditional))
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/zh_Hant/
2023-03-05 12:33:40 +00:00
Artem Polivanchuk
9570864dd3 Added translation using Weblate (Ukrainian) 2023-03-04 14:09:44 +00:00
Andy Balaam
633805dcc2 Merge pull request #560 from vector-im/andybalaam/fix-release-notes-1.11.24
Remove items incorrectly included in changelog for 1.11.24
2023-03-03 14:28:35 +00:00
Andy Balaam
e04e500fd5 Remove items incorrectly included in changlog for 1.11.24 2023-03-03 12:52:04 +00:00
Michael Telatynski
68d2e34841 Guard reprepro db via concurrency limits (#555) 2023-03-02 16:54:57 +00:00
Michael Telatynski
88ef8deb78 Fix macOS notarisation using keychain credentials (#557) 2023-03-01 10:49:41 +00:00
RiotRobot
144d04a5ae Merge branch 'master' into develop 2023-02-28 11:24:52 +00:00
RiotRobot
75e3ea6818 v1.11.24 2023-02-28 11:24:38 +00:00
RiotRobot
248ec9cedd Prepare changelog for v1.11.24 2023-02-28 11:24:37 +00:00
Michael Telatyński
65a7871d45 Let electron-builder correctly set StartupWMClass (#526) 2023-02-27 18:04:55 +00:00
Michael Telatynski
b858e45eee Fix invalid JSON 2023-02-27 10:52:25 +00:00
Michael Telatynski
3656125552 Fix Windows deploy path 2023-02-27 10:47:40 +00:00
Michael Telatynski
20f8099253 Update base-url for macos staging builds 2023-02-27 10:17:14 +00:00
Michael Telatyński
fc961737f4 Fix build_and_deploy workflow (#553) 2023-02-27 09:52:47 +00:00
Michael Telatyński
f79713980a Update build_macos.yaml 2023-02-27 09:45:54 +00:00
renovate[bot]
8497d743cd Update dependency playwright to v1.31.1 (#536)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-24 23:47:08 +00:00
renovate[bot]
58f7c2534c Update dependency eslint-plugin-matrix-org to v1 (#551)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-24 14:27:25 +01:00
renovate[bot]
ed60ea1977 Update dependency @types/tar to v6.1.4 (#549)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-24 12:44:18 +00:00
renovate[bot]
12c6f2c268 Update all non-major dependencies (#529)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-24 11:11:19 +00:00
Andy Balaam
a528d8c7c5 Merge pull request #546 from vector-im/andybalaam/harmonise-eslintrc-tsconfig
Separate linting and compiling src+test, scripts and hak
2023-02-24 10:31:38 +00:00
Andy Balaam
3eeb8c14a9 Lint the test directory 2023-02-24 09:39:14 +00:00
Andy Balaam
51a8667b89 Share what we can with extends in eslintrc 2023-02-23 17:33:06 +00:00
Andy Balaam
f960700a2a Exclude test from eslint checking since it always was excluded, and I can't get it to check 2023-02-23 17:10:06 +00:00
Michael Telatynski
a0a9ec830c Build & EV Sign Windows builds (#517
* Add way to provide apple ID and app password to notarise script

* Add utility to generate electron-builder.json for release & nightly builds

* Run Build & Test on staging too

* First attempt at build & deploy for macOS with signing and notarisation

* Fix quote mismatch

* use correct quotes

* add runs-on

* Fix inputs.mode usage

* remove quotes

* chmod +x

* Fix artifact paths

* Fix deploy condition

* Fix deploy condition

* Fix artifact path

* Iterate

* Fix workflow

* Fix env

* Iterate

* Fix missing env

* Fix version calculation

* Iterate

* Fix config not taking effect

* Update build_and_deploy.yaml

* Fix alignments

* delint

* Fix alignment

* Update build_macos.yaml

* Add ability to EV sign using eSigner CKA

* Initial work to build & sign Windows nightlies in CI

* Format

* Format

* Fix gha

* fix winSign

* Fix install command

* Add signtool to path

* Update build_and_deploy.yaml

* Fix quotes

* Test

* Fix comments

* Fix cmd

* Try again

* arg slashes

* Fix exe path

* Fix matrix strategy

* Use ampersand-call

* fwd slash ftw?

* ls *

* 🌲

* tree dist

* prepend path

* Specify /fd and /td to modern signtool

* /tr not /t for CKA

* Test signing

* missing comma

* 🤦‍♂️

* Fix wrong mv

* Lets sign

* Fix config gen

* Debug

* Fix typo

* Multiple drives why

* Try NVL sandbox creds

* Update

* Attempt to disable logger

* Try again

* Iterate

* Update build_macos.yaml

* Update build_and_deploy.yaml

* Update build_macos.yaml

* Update build_and_deploy.yaml

* Update build_and_deploy.yaml

* Try custom build of eSigner CKA

* Fix typos

* Update build_windows.yaml

* Update build_and_deploy.yaml

* Update build_windows.yaml

* Update build_and_deploy.yaml

* Fix symlinking

* Fix working-directory incantation

* exe

* remove debug

* Prettier

* Vendor check in SSL.com executable

* Download CKA from packages.element.io instead

* Use demo creds

* StrictMode

* Switch back to 0207 (unsigned)

* Fix call syntax

* Revert env inc

* Partial rollback

* Trace

* Trace less

* Fix CN being passed wrong

* DEBUG

* Debug 2

* Fix ConvertFrom-StringData

* 0214

* Test

* Test

* Untested

* Revert to 0207

* stash

* Try with 20230221

* Restore scripts/electron_winSign.js

* Prepare for merge

* Update build_windows.yaml

* Update build_and_deploy.yaml

* Restore .github/workflows/build_and_deploy.yaml

* Restore .github/workflows/build_and_deploy.yaml

* Fix bad restore
2023-02-22 13:51:19 +00:00
RiotRobot
c4b753c680 v1.11.24-rc.2 2023-02-22 11:48:00 +00:00
RiotRobot
3f999e2cd7 Prepare changelog for v1.11.24-rc.2 2023-02-22 11:48:00 +00:00
RiotRobot
c883e023eb Merge branch 'develop' into staging 2023-02-22 10:59:21 +00:00
RiotRobot
710f86abcd v1.11.24-rc.1 2023-02-21 13:23:56 +00:00
RiotRobot
90f5748ba7 Prepare changelog for v1.11.24-rc.1 2023-02-21 13:23:56 +00:00
Michael Telatynski
c9d7e37e09 Update pull_request.yaml 2023-02-21 12:24:58 +00:00
Andy Balaam
f53cb68cf8 Merge pull request #548 from RiotTranslateBot/weblate-element-desktop-element-desktop
Translations update from Weblate
2023-02-21 10:40:36 +00:00
Andy Balaam
26a308d8c6 Add typeRoots to try and appease CI 2023-02-20 16:25:17 +00:00
Andy Balaam
a0034c1ade Add a rootDir to try and appease the CI 2023-02-20 16:08:11 +00:00
Weblate
00b40a3e73 Merge branch 'origin/develop' into Weblate. 2023-02-20 12:09:50 +00:00
Michael Telatynski
cdbb7763bf Build & Package signed Linux builds (#527) 2023-02-20 12:09:45 +00:00
Andy Balaam
1271c22aee Separate linting and compiling src+test, scripts and hak
Inspired by the failure of https://github.com/vector-im/element-desktop/pull/529
to lint our code with the @typescript-eslint/no-base-to-string rule
turned on, I found we needed to add a parserOptions.project to our
.eslintrc.js, pointing to the tsconfig.json.

This led to more fixes, because we have 3 tsconfig.json files for
src+test, scripts and hak and the single eslintrc was complaining that
it could see more files than the tsconfig file knew about.

So, I think the right split is to have one eslintrc file and one
tsconfig for each of the three projects.
2023-02-17 12:17:42 +00:00
Andy Balaam
bd8c69ec74 Include the test directory in tsconfig. 2023-02-17 12:14:53 +00:00
Weblate
b4f418e2ac Merge branch 'origin/develop' into Weblate. 2023-02-17 10:44:55 +00:00
renovate[bot]
acaf040bfa Update jest monorepo to v29.4.3 (#537)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-17 10:44:50 +00:00
Weblate
2240302340 Merge branch 'origin/develop' into Weblate. 2023-02-16 19:43:34 +00:00
renovate[bot]
1462e87945 Update dependency electron to v23 (#541)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-16 19:43:29 +00:00
Weblate
42a50600c1 Merge branch 'origin/develop' into Weblate. 2023-02-16 16:38:31 +00:00
Will Hunt
03ebb5c51a No more ehome config (#545)
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2023-02-16 16:38:25 +00:00
Weblate
ab511d6fcc Merge branch 'origin/develop' into Weblate. 2023-02-16 14:17:00 +00:00
renovate[bot]
ea688abe3b Update dependency mkdirp to v2 (#539)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-16 15:16:56 +01:00
Weblate
e81dd4cc72 Merge branch 'origin/develop' into Weblate. 2023-02-16 14:16:25 +00:00
renovate[bot]
003d8e086e Lock file maintenance (#523)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-16 14:16:20 +00:00
Weblate
d515ff52b6 Merge branch 'origin/develop' into Weblate. 2023-02-16 14:14:47 +00:00
renovate[bot]
d6350a56dc Update dependency @types/node to v16.18.12 (#534)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-16 15:14:42 +01:00
Suguru Hirahara
8b54188e46 Translated using Weblate (Japanese)
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/ja/
2023-02-16 10:33:34 +00:00
Weblate
c3630756d7 Merge branch 'origin/develop' into Weblate. 2023-02-14 10:52:50 +00:00
RiotRobot
69392fd8da Merge branch 'master' into develop 2023-02-14 10:52:44 +00:00
RiotRobot
913a40bacd v1.11.23 2023-02-14 10:52:29 +00:00
RiotRobot
83ab73202e Prepare changelog for v1.11.23 2023-02-14 10:52:28 +00:00
Weblate
1bfb53424a Merge branch 'origin/develop' into Weblate. 2023-02-13 10:01:17 +00:00
Michael Telatynski
c1dd1dc73c Fix macos release symlinking (#543) 2023-02-13 10:01:11 +00:00
Kaede
25e857e644 Translated using Weblate (Japanese)
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/ja/
2023-02-12 15:33:33 +00:00
Kaede
119926984b Added translation using Weblate (Japanese) 2023-02-11 14:31:38 +00:00
Weblate
a60a748fd4 Merge branch 'origin/develop' into Weblate. 2023-02-07 22:58:49 +00:00
renovate[bot]
888c619d62 Update dependency @aws-sdk/client-s3 to v3.264.0 (#535)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-02-07 22:58:44 +00:00
RiotRobot
7e87dd6996 v1.11.23-rc.1 2023-02-07 12:29:16 +00:00
RiotRobot
a205d3a696 Prepare changelog for v1.11.23-rc.1 2023-02-07 12:29:16 +00:00
Weblate
1f637a82d3 Merge branch 'origin/develop' into Weblate. 2023-02-03 10:12:02 +00:00
Michael Telatynski
2ad46704af Update to Electron 22.2.0 - fix tray icons in Linux (#530) 2023-02-03 10:11:57 +00:00
bluelullaby6
bcfa82335e Translated using Weblate (French)
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/fr/
2023-02-02 23:33:30 +00:00
Weblate
2da8c2012f Merge branch 'origin/develop' into Weblate. 2023-01-31 16:10:54 +00:00
Michael Telatynski
47165ca73d Update build_macos.yaml 2023-01-31 16:10:51 +00:00
Weblate
65089492f8 Merge branch 'origin/develop' into Weblate. 2023-01-31 15:49:45 +00:00
Michael Telatynski
66d96fea2c Update build_macos.yaml 2023-01-31 15:49:41 +00:00
Weblate
e34ec05f8c Merge branch 'origin/develop' into Weblate. 2023-01-31 15:06:46 +00:00
RiotRobot
f6efaf069a Merge branch 'master' into develop 2023-01-31 15:06:41 +00:00
RiotRobot
72dfdda0e5 v1.11.22 2023-01-31 15:06:24 +00:00
RiotRobot
679cf24a85 Prepare changelog for v1.11.22 2023-01-31 15:06:23 +00:00
Weblate
ca20f91bf3 Merge branch 'origin/develop' into Weblate. 2023-01-31 13:55:12 +00:00
Michael Telatynski
3330b8485c Update build_macos.yaml 2023-01-31 13:55:09 +00:00
Weblate
08f558d345 Merge branch 'origin/develop' into Weblate. 2023-01-31 13:22:35 +00:00
Ion Nistor
20f9bb198b Translated using Weblate (Romanian)
Currently translated at 88.8% (40 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/ro/
2023-01-31 13:22:34 +00:00
Michael Telatynski
e5117f9736 Build, Sign & Notarise macOS builds (#486) 2023-01-31 13:22:30 +00:00
Weblate
51fe8ee024 Merge branch 'origin/develop' into Weblate. 2023-01-31 11:22:34 +00:00
RiotRobot
7f3bbc2156 v1.11.21 2023-01-31 11:22:12 +00:00
RiotRobot
5c650d6ee3 Prepare changelog for v1.11.21 2023-01-31 11:22:11 +00:00
RiotRobot
fb7a43569c v1.11.21-rc.1 2023-01-24 11:49:51 +00:00
RiotRobot
7620af7f70 Prepare changelog for v1.11.21-rc.1 2023-01-24 11:49:51 +00:00
RiotRobot
fe30072067 Merge branch 'master' into develop 2023-01-20 13:04:49 +00:00
RiotRobot
93331da979 v1.11.20 2023-01-20 13:04:34 +00:00
RiotRobot
af13eb8929 Prepare changelog for v1.11.20 2023-01-20 13:04:33 +00:00
Weblate
41fe92478c Merge branch 'origin/develop' into Weblate. 2023-01-20 13:01:05 +00:00
RiotRobot
b346984ab7 Merge branch 'master' into develop 2023-01-20 10:14:25 +00:00
RiotRobot
a23c6162f3 v1.11.19 2023-01-20 10:14:08 +00:00
RiotRobot
82d459a95d Prepare changelog for v1.11.19 2023-01-20 10:14:08 +00:00
Weblate
6a9f2050eb Merge branch 'origin/develop' into Weblate. 2023-01-20 10:10:42 +00:00
xrh0905
33740a99cd Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/zh_Hans/
2023-01-20 10:10:42 +00:00
Sveinn í Felli
8377e7d585 Translated using Weblate (Icelandic)
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/is/
2023-01-18 17:33:25 +00:00
Demo337
68c4f38b71 Translated using Weblate (Arabic)
Currently translated at 100.0% (45 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/ar/
2023-01-18 17:33:25 +00:00
RiotRobot
5395fee162 Merge branch 'master' into develop 2023-01-18 14:06:24 +00:00
RiotRobot
c3781b9ee4 v1.11.18 2023-01-18 14:06:08 +00:00
RiotRobot
b2d77edff2 Prepare changelog for v1.11.18 2023-01-18 14:06:07 +00:00
RiotRobot
f4be3bcda2 v1.11.18-rc.4 2023-01-17 09:50:57 +00:00
RiotRobot
5585292143 Prepare changelog for v1.11.18-rc.4 2023-01-17 09:50:56 +00:00
renovate[bot]
5a2b390f0f Update all non-major dependencies (#515)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-16 15:26:59 +00:00
RiotRobot
92e61681a9 v1.11.18-rc.3 2023-01-13 11:00:44 +00:00
RiotRobot
1a25dbfd44 Prepare changelog for v1.11.18-rc.3 2023-01-13 11:00:44 +00:00
renovate[bot]
9beaecc350 Update dependency @aws-sdk/client-s3 to v3.245.0 (#513)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-12 14:37:31 +00:00
renovate[bot]
9d74a215b7 Update dependency playwright to v1.29.2 (#511)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-12 14:37:17 +00:00
renovate[bot]
b9ac577d98 Update dependency @types/jest to v29.2.5 (#510)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-12 14:37:06 +00:00
RiotRobot
956ae15983 v1.11.18-rc.2 2023-01-12 14:26:34 +00:00
RiotRobot
e10c4a10e0 Prepare changelog for v1.11.18-rc.2 2023-01-12 14:26:34 +00:00
renovate[bot]
6032815f75 Update dependency @babel/core to v7.20.12 (#509)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-12 09:39:01 +00:00
renovate[bot]
597524a0fb Update typescript-eslint monorepo to v5.48.0 (#514)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-12 09:14:08 +00:00
renovate[bot]
a74d22a84b Update all non-major dependencies (#512)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-12 09:13:35 +00:00
RiotRobot
c33211cf7e v1.11.18-rc.1 2023-01-11 15:29:48 +00:00
RiotRobot
6eb79076c6 Prepare changelog for v1.11.18-rc.1 2023-01-11 15:29:47 +00:00
Element Translate Bot
c000c0ce52 Translations update from Weblate (#508)
* Added translation using Weblate (Tagalog)

* Translated using Weblate (Tagalog)

Currently translated at 31.1% (14 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/tl/

* Translated using Weblate (Esperanto)

Currently translated at 71.1% (32 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/eo/

Co-authored-by: Nate Gardner <natejgardner@gmail.com>
Co-authored-by: Weblate <noreply@weblate.org>
Co-authored-by: Christian Paul <info@jaller.de>
2023-01-11 13:19:49 +00:00
Andy Balaam
73fc7e957f Merge pull request #506 from vector-im/dependabot/npm_and_yarn/json5-1.0.2
Bump json5 from 1.0.1 to 1.0.2
2023-01-06 11:31:56 +00:00
dependabot[bot]
961cfc7746 Bump json5 from 1.0.1 to 1.0.2
Bumps [json5](https://github.com/json5/json5) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/json5/json5/releases)
- [Changelog](https://github.com/json5/json5/blob/main/CHANGELOG.md)
- [Commits](https://github.com/json5/json5/compare/v1.0.1...v1.0.2)

---
updated-dependencies:
- dependency-name: json5
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-01-04 20:44:25 +00:00
renovate[bot]
0ac568c137 Lock file maintenance (#505)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-01-04 13:43:51 -07:00
Michael Telatynski
629eb3958a Update environment name (#490) 2022-12-23 14:28:23 +00:00
RiotRobot
68797d393e Merge branch 'master' into develop 2022-12-21 17:31:28 +00:00
RiotRobot
723ea9d5ff v1.11.17 2022-12-21 17:31:13 +00:00
RiotRobot
b1b15e1e7b Prepare changelog for v1.11.17 2022-12-21 17:31:12 +00:00
renovate[bot]
c164f3cbe9 Update dependency @types/node to v16.18.8 (#489)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-15 22:06:26 -07:00
renovate[bot]
aa4c25016d Update typescript-eslint monorepo to v5.46.1 (#493)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-15 22:06:00 -07:00
renovate[bot]
16f253690a Update all non-major dependencies (#491)
* Update all non-major dependencies

* Add prettier

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Andy Balaam <andy.balaam@matrix.org>
2022-12-15 18:14:43 +00:00
Andy Balaam
f542491467 Merge pull request #496 from vector-im/andybalaam/format-prettier
Format all files with prettier
2022-12-15 17:24:49 +00:00
Andy Balaam
c6d44418b5 Format build.yaml 2022-12-15 16:20:32 +00:00
Andy Balaam
a99f9a6aee wip 2022-12-15 16:03:02 +00:00
Michael Telatynski
86149805b9 Fix macOS tests (#495) 2022-12-15 15:21:04 +00:00
Andy Balaam
0faac52dae Format all files with prettier 2022-12-15 11:52:12 +00:00
renovate[bot]
040344eeab Update dependency @aws-sdk/client-s3 to v3.226.0 (#492)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-14 12:53:40 +00:00
renovate[bot]
799b23e2a9 Update dependency @types/jest to v29.2.4 (#488)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-14 11:13:15 +00:00
Michael Telatynski
d766aef435 Enable strict mode on hak tsconfig (#483) 2022-12-14 10:47:35 +00:00
RiotRobot
1142160222 v1.11.17-rc.1 2022-12-14 09:52:34 +00:00
RiotRobot
c280560c2c Prepare changelog for v1.11.17-rc.1 2022-12-14 09:52:33 +00:00
Element Translate Bot
19f04d4362 Translations update from Weblate (#487)
* Translated using Weblate (Norwegian Bokmål)

Currently translated at 80.0% (36 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/nb_NO/

* Translated using Weblate (Norwegian Bokmål)

Currently translated at 80.0% (36 of 45 strings)

Translation: Element Desktop/element-desktop
Translate-URL: https://translate.element.io/projects/element-desktop/element-desktop/nb_NO/

Co-authored-by: San Jacobs <sanjacobs@protonmail.com>
Co-authored-by: Martin Berg Alstad <martin.alstad@pm.me>
Co-authored-by: Weblate <noreply@weblate.org>
2022-12-13 14:42:41 +00:00
Michael Telatynski
2f48519dce Improve build time in CI through caching native modules (#482)
* Improve caching of hak native modules

* Avoid double-hashing

* Skip native installs where cache is hit

* Include Electron version in the hash, it affects the ABI

* Add missing step IDs

* Add comments
2022-12-13 14:12:40 +00:00
renovate[bot]
6508e171db Update dependency electron to v22 (#480)
* Update dependency electron to v22

* Switch from new-window event to setWindowOpenHandler

* Stop recommending libappindicator3-1, Electron 22 stops using it

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2022-12-07 00:04:53 +00:00
RiotRobot
333361fc02 Merge branch 'master' into develop 2022-12-06 13:15:16 +00:00
RiotRobot
9d08c84331 v1.11.16 2022-12-06 13:15:02 +00:00
RiotRobot
0b67e84574 Prepare changelog for v1.11.16 2022-12-06 13:15:02 +00:00
Michael Telatynski
23fac479fe Switch macOS update mechanism to static JSON mode (#461) 2022-12-05 12:41:13 +00:00
Michael Telatynski
56370de568 Improve use of Typescript (#474)
* Switch out needle with node-fetch

* Iterate

* Update asar package and switch to canonical name

* Use ts-node for scripts

* Iterate

* Update yarn.lock

* Use node:stream.promises

* Remove logfile

* Fix types

* Fix types
2022-12-05 11:50:49 +00:00
RiotRobot
9bdb1fadd4 v1.11.16-rc.2 2022-12-02 17:08:05 +00:00
RiotRobot
86a386449f Prepare changelog for v1.11.16-rc.2 2022-12-02 17:08:04 +00:00
renovate[bot]
b52787a49e Update dependency fs-extra to v11 (#481)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-02 10:57:37 +00:00
renovate[bot]
8c91ead163 Update dependency pacote to v15 (#479)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-01 11:38:43 +00:00
renovate[bot]
9d6008519e Update dependency glob to v8 (#478)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-01 08:23:42 +00:00
renovate[bot]
d3fbf1366b Update dependency asar to v3 (#476)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-01 07:50:17 +00:00
renovate[bot]
f4bf425148 Update all non-major dependencies (#468)
* Update all non-major dependencies

* Iterate PR

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2022-12-01 07:20:55 +00:00
renovate[bot]
19351d766d Update actions/checkout action to v3 (#472)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2022-12-01 06:55:00 +00:00
RiotRobot
7c87fff295 v1.11.16-rc.1 2022-11-29 15:54:35 +00:00
RiotRobot
f5fa0ae7be Prepare changelog for v1.11.16-rc.1 2022-11-29 15:54:34 +00:00
112 changed files with 6850 additions and 5014 deletions

22
.eslintrc-hak.js Normal file
View File

@@ -0,0 +1,22 @@
module.exports = {
plugins: ["matrix-org"],
extends: [".eslintrc.js"],
parserOptions: {
project: ["hak/tsconfig.json"],
},
overrides: [
{
files: ["hak/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
],
};

22
.eslintrc-scripts.js Normal file
View File

@@ -0,0 +1,22 @@
module.exports = {
plugins: ["matrix-org"],
extends: [".eslintrc.js"],
parserOptions: {
project: ["scripts/tsconfig.json"],
},
overrides: [
{
files: ["scripts/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
],
};

22
.eslintrc-test.js Normal file
View File

@@ -0,0 +1,22 @@
module.exports = {
plugins: ["matrix-org"],
extends: [".eslintrc.js"],
parserOptions: {
project: ["test/tsconfig.json"],
},
overrides: [
{
files: ["test/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
],
};

View File

@@ -1,10 +1,9 @@
module.exports = {
plugins: ["matrix-org"],
extends: [
"plugin:matrix-org/javascript",
],
extends: ["plugin:matrix-org/javascript"],
parserOptions: {
ecmaVersion: 2021,
project: ["tsconfig.json"],
},
env: {
es6: true,
@@ -20,19 +19,19 @@ module.exports = {
"prefer-promise-reject-errors": "off",
"no-async-promise-executor": "off",
},
overrides: [{
files: ["{src,scripts,hak}/**/*.{ts,tsx}"],
extends: [
"plugin:matrix-org/typescript",
],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
overrides: [
{
files: ["src/**/*.ts"],
extends: ["plugin:matrix-org/typescript"],
rules: {
// Things we do that break the ideal style
"prefer-promise-reject-errors": "off",
"quotes": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
"@typescript-eslint/no-explicit-any": "off",
// We're okay with assertion errors when we ask for them
"@typescript-eslint/no-non-null-assertion": "off",
},
},
}],
],
};

View File

@@ -2,9 +2,9 @@
## Checklist
* [ ] Ensure your code works with manual testing
* [ ] Linter and other CI checks pass
* [ ] Sign-off given on the changes (see [CONTRIBUTING.md](https://github.com/vector-im/element-desktop/blob/develop/CONTRIBUTING.md))
- [ ] Ensure your code works with manual testing
- [ ] Linter and other CI checks pass
- [ ] Sign-off given on the changes (see [CONTRIBUTING.md](https://github.com/vector-im/element-desktop/blob/develop/CONTRIBUTING.md))
<!--
If you would like to specify text for the changelog entry other than your PR title, add the following:

View File

@@ -1,6 +1,4 @@
{
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"github>matrix-org/renovate-config-element-web"
]
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": ["github>matrix-org/renovate-config-element-web"]
}

View File

@@ -1,30 +1,30 @@
name: Backport
on:
pull_request_target:
types:
- closed
- labeled
branches:
- develop
pull_request_target:
types:
- closed
- labeled
branches:
- develop
jobs:
backport:
name: Backport
runs-on: ubuntu-latest
# Only react to merged PRs for security reasons.
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
if: >
github.event.pull_request.merged
&& (
github.event.action == 'closed'
|| (
github.event.action == 'labeled'
&& contains(github.event.label.name, 'backport')
)
)
steps:
- uses: tibdex/backport@v2
with:
labels_template: "<%= JSON.stringify([...labels, 'X-Release-Blocker']) %>"
# We can't use GITHUB_TOKEN here or CI won't run on the new PR
github_token: ${{ secrets.ELEMENT_BOT_TOKEN }}
backport:
name: Backport
runs-on: ubuntu-latest
# Only react to merged PRs for security reasons.
# See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target.
if: >
github.event.pull_request.merged
&& (
github.event.action == 'closed'
|| (
github.event.action == 'labeled'
&& contains(github.event.label.name, 'backport')
)
)
steps:
- uses: tibdex/backport@v2
with:
labels_template: "<%= JSON.stringify([...labels, 'X-Release-Blocker']) %>"
# We can't use GITHUB_TOKEN here or CI won't run on the new PR
github_token: ${{ secrets.ELEMENT_BOT_TOKEN }}

View File

@@ -1,107 +0,0 @@
name: Build and Test
on:
pull_request: { }
push:
branches: [ develop, master ]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
fetch:
uses: ./.github/workflows/build_prepare.yaml
with:
config: ${{ github.event.pull_request.base.ref == 'develop' && 'element.io/nightly' || 'element.io/release' }}
version: ${{ github.event.pull_request.base.ref == 'develop' && 'develop' || '' }}
windows:
needs: fetch
name: Windows
uses: ./.github/workflows/build_windows.yaml
strategy:
matrix:
arch: [ x64, x86 ]
with:
arch: ${{ matrix.arch }}
linux:
needs: fetch
name: Linux
uses: ./.github/workflows/build_linux.yaml
strategy:
matrix:
sqlcipher: [ system, static ]
with:
sqlcipher: ${{ matrix.sqlcipher }}
macos:
needs: fetch
name: macOS
uses: ./.github/workflows/build_macos.yaml
test:
needs:
- macos
- linux
- windows
strategy:
matrix:
include:
# Disable macOS tests for now, they fail to run in CI, needs investigation.
# - name: macOS Universal
# os: macos
# artifact: macos
# executable: "./dist/mac-universal/Element.app/Contents/MacOS/Element"
# prepare_cmd: "chmod +x ./dist/mac-universal/Element.app/Contents/MacOS/Element"
- name: 'Linux (sqlcipher: system)'
os: ubuntu
artifact: linux-sqlcipher-system
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: 'Linux (sqlcipher: static)'
os: ubuntu
artifact: linux-sqlcipher-static
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: Windows (x86)
os: windows
artifact: win-x86
executable: "./dist/win-ia32-unpacked/Element.exe"
- name: Windows (x64)
os: windows
artifact: win-x64
executable: "./dist/win-unpacked/Element.exe"
name: Test ${{ matrix.name }}
runs-on: ${{ matrix.os }}-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: "yarn"
- name: Install Deps
run: "yarn install --pure-lockfile"
- uses: actions/download-artifact@v3
with:
name: ${{ matrix.artifact }}
path: dist
- name: Prepare for tests
run: ${{ matrix.prepare_cmd }}
if: matrix.prepare_cmd
- name: Run tests
uses: GabrielBB/xvfb-action@v1
timeout-minutes: 5
with:
run: "yarn test"
env:
ELEMENT_DESKTOP_EXECUTABLE: ${{ matrix.executable }}
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.artifact }}
path: test_artifacts
retention-days: 1

156
.github/workflows/build_and_deploy.yaml vendored Normal file
View File

@@ -0,0 +1,156 @@
name: Build and Deploy
on:
# Nightly build
schedule:
- cron: "0 9 * * *"
# Manual nightly & release
workflow_dispatch:
inputs:
mode:
description: What type of build to trigger. Release builds MUST be ran from the `master` branch.
required: true
default: nightly
type: choice
options:
- nightly
- release
macos:
description: Build macOS
required: true
type: boolean
default: true
windows_32bit:
description: Build Windows 32-bit
required: true
type: boolean
default: true
windows_64bit:
description: Build Windows 64-bit
required: true
type: boolean
default: true
linux:
description: Build Linux
required: true
type: boolean
default: true
deploy:
description: Deploy artifacts
required: true
type: boolean
default: true
concurrency: ${{ github.workflow }}
env:
R2_BUCKET: "packages-element-io"
jobs:
prepare:
uses: ./.github/workflows/build_prepare.yaml
with:
config: element.io/${{ inputs.mode || 'nightly' }}
version: ${{ inputs.mode == 'release' && '' || 'develop' }}
nightly: ${{ inputs.mode != 'release' }}
secrets:
CF_R2_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
CF_R2_TOKEN: ${{ secrets.CF_R2_TOKEN }}
CF_R2_S3_API: ${{ secrets.CF_R2_S3_API }}
windows_32bit:
if: github.event_name != 'workflow_dispatch' || inputs.windows_32bit
needs: prepare
name: Windows 32-bit
uses: ./.github/workflows/build_windows.yaml
secrets: inherit
with:
sign: true
deploy-mode: true
arch: x86
version: ${{ needs.prepare.outputs.win32-x86-version }}
windows_64bit:
if: github.event_name != 'workflow_dispatch' || inputs.windows_64bit
needs: prepare
name: Windows 64-bit
uses: ./.github/workflows/build_windows.yaml
secrets: inherit
with:
sign: true
deploy-mode: true
arch: x64
version: ${{ needs.prepare.outputs.win32-x64-version }}
macos:
if: github.event_name != 'workflow_dispatch' || inputs.macos
needs: prepare
name: macOS
uses: ./.github/workflows/build_macos.yaml
secrets: inherit
with:
sign: true
deploy-mode: true
base-url: https://packages.element.io/${{ inputs.mode == 'release' && 'desktop' || 'nightly' }}
version: ${{ needs.prepare.outputs.macos-version }}
# We do not put this call into deploy-mode as we do not want it to add to the packages.element.io artifact
# We ship this build via reprepro only
linux:
if: github.event_name != 'workflow_dispatch' || inputs.linux
needs: prepare
name: Linux (sqlcipher system)
uses: ./.github/workflows/build_linux.yaml
with:
config: element.io/${{ inputs.mode || 'nightly' }}
sqlcipher: system
version: ${{ needs.prepare.outputs.linux-version }}
# We ship the static build via static tarball only
linux_static:
if: github.event_name != 'workflow_dispatch' || inputs.linux
needs: prepare
name: Linux (sqlcipher static)
uses: ./.github/workflows/build_linux.yaml
with:
deploy-mode: true
config: element.io/${{ inputs.mode || 'nightly' }}
sqlcipher: static
version: ${{ needs.prepare.outputs.linux-version }}
# This deploy job only handles Windows, macOS & linux_static as those are stateless and static.
# Linux will be deployed via reprepro after it, but we list it as a dependency to abort if it fails.
deploy:
needs:
- macos
- linux
- linux_static
- windows_32bit
- windows_64bit
runs-on: ubuntu-latest
name: Deploy
if: github.event_name != 'workflow_dispatch' || (inputs.deploy && (inputs.macos || inputs.windows_32bit || inputs.windows_64bit))
environment: packages.element.io
steps:
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: packages.element.io
path: packages.element.io
- name: Deploy artifacts
run: |
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 }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
R2_URL: ${{ secrets.CF_R2_S3_API }}
DEPLOYMENT_DIR: ${{ inputs.mode == 'release' && 'desktop' || 'nightly' }}
reprepro:
needs:
- linux
# We queue this after the other deploy stage as we want to abort if that fails
- deploy
name: Run reprepro
if: github.event_name != 'workflow_dispatch' || (inputs.deploy && inputs.linux)
uses: ./.github/workflows/reprepro.yaml
secrets: inherit
with:
artifact-name: linux-sqlcipher-system

108
.github/workflows/build_and_test.yaml vendored Normal file
View File

@@ -0,0 +1,108 @@
name: Build and Test
on:
pull_request: {}
push:
branches: [develop, staging, master]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
fetch:
uses: ./.github/workflows/build_prepare.yaml
with:
config: ${{ github.event.pull_request.base.ref == 'develop' && 'element.io/nightly' || 'element.io/release' }}
version: ${{ github.event.pull_request.base.ref == 'develop' && 'develop' || '' }}
windows:
needs: fetch
name: Windows
uses: ./.github/workflows/build_windows.yaml
strategy:
matrix:
arch: [x64, x86]
with:
arch: ${{ matrix.arch }}
linux:
needs: fetch
name: Linux
uses: ./.github/workflows/build_linux.yaml
strategy:
matrix:
sqlcipher: [system, static]
with:
config: ${{ github.event.pull_request.base.ref == 'develop' && 'element.io/nightly' || 'element.io/release' }}
sqlcipher: ${{ matrix.sqlcipher }}
macos:
needs: fetch
name: macOS
uses: ./.github/workflows/build_macos.yaml
test:
needs:
- macos
- linux
- windows
strategy:
matrix:
include:
- name: macOS Universal
os: macos
artifact: macos
executable: "./dist/mac-universal/Element.app/Contents/MacOS/Element"
prepare_cmd: "find ./dist/mac-universal/Element.app -type f | perl -lne 'print if -B' | tr '\\n' '\\0' | xargs -0 -n1 chmod 755"
- name: "Linux (sqlcipher: system)"
os: ubuntu
artifact: linux-sqlcipher-system
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: "Linux (sqlcipher: static)"
os: ubuntu
artifact: linux-sqlcipher-static
executable: "element-desktop"
prepare_cmd: "sudo apt install ./dist/*.deb"
- name: Windows (x86)
os: windows
artifact: win-x86
executable: "./dist/win-ia32-unpacked/Element.exe"
- name: Windows (x64)
os: windows
artifact: win-x64
executable: "./dist/win-unpacked/Element.exe"
name: Test ${{ matrix.name }}
runs-on: ${{ matrix.os }}-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: "yarn"
- name: Install Deps
run: "yarn install --frozen-lockfile"
- uses: actions/download-artifact@v3
with:
name: ${{ matrix.artifact }}
path: dist
- name: Prepare for tests
run: ${{ matrix.prepare_cmd }}
if: matrix.prepare_cmd
- name: Run tests
uses: coactions/setup-xvfb@b6b4fcfb9f5a895edadc3bc76318fae0ac17c8b3 # v1
timeout-minutes: 5
with:
run: "yarn test"
env:
ELEMENT_DESKTOP_EXECUTABLE: ${{ matrix.executable }}
- name: Upload Artifacts
uses: actions/upload-artifact@v3
if: always()
with:
name: ${{ matrix.artifact }}
path: test_artifacts
retention-days: 1

53
.github/workflows/build_keyring.yaml vendored Normal file
View File

@@ -0,0 +1,53 @@
name: Build Keyring package
on:
workflow_dispatch:
inputs:
deploy:
description: Deploy artifacts
required: true
type: boolean
default: true
fingerprint:
description: The expected gpg fingerprint
required: true
type: string
concurrency: ${{ github.workflow }}
jobs:
build:
name: Build Keyring package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Prepare
run: |
mkdir -p element-io-archive-keyring/usr/share/keyrings/
cp packages.element.io/debian/element-io-archive-keyring.gpg element-io-archive-keyring/usr/share/keyrings/element-io-archive-keyring.gpg
- name: Check fingerprint
run: |
gpg --import element-io-archive-keyring/usr/share/keyrings/element-io-archive-keyring.gpg
gpg --fingerprint "$FINGERPRINT"
env:
FINGERPRINT: ${{ inputs.fingerprint }}
- name: Build deb package
run: |
chmod u=rw,go=r element-io-archive-keyring/usr/share/keyrings/element-io-archive-keyring.gpg
dpkg-deb -Zxz --root-owner-group --build element-io-archive-keyring element-io-archive-keyring.deb
- name: Upload Artifact
uses: actions/upload-artifact@v3
with:
name: element-io-archive-keyring
path: "*.deb"
retention-days: 1
reprepro:
needs: build
name: Run reprepro
if: inputs.deploy
uses: ./.github/workflows/reprepro.yaml
secrets: inherit
with:
artifact-name: element-io-archive-keyring

View File

@@ -1,58 +1,137 @@
# This workflow relies on actions/cache to store the hak dependency artifacts as they take a long time to build
# Due to this extra care must be taken to only ever run all build_* scripts against the same branch to ensure
# the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch.
on:
workflow_call:
inputs:
sqlcipher:
type: string
required: true
description: "How to link sqlcipher, one of 'system' | 'static'"
workflow_call:
inputs:
config:
type: string
required: true
description: "The config directory to use"
version:
type: string
required: false
description: "Version string to override the one in package.json, used for non-release builds"
sqlcipher:
type: string
required: true
description: "How to link sqlcipher, one of 'system' | 'static'"
deploy-mode:
type: boolean
required: false
description: "Whether to arrange artifacts in the arrangement needed for deployment, skipping unrelated ones"
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
build:
runs-on: ubuntu-latest
container:
image: ghcr.io/vector-im/element-desktop-dockerbuild:${{ github.ref_name == 'master' && 'master' || 'develop' }}
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: webapp
- uses: actions/download-artifact@v3
with:
name: webapp
- name: Cache .hak
uses: actions/cache@v3
with:
key: ${{ hashFiles('./yarn.lock') }}
path: |
./.hak
- name: Cache .hak
id: cache
uses: actions/cache@v3
with:
key: ${{ runner.os }}-${{ inputs.sqlcipher }}-${{ hashFiles('hakDependencies.json', 'electronVersion') }}
path: |
./.hak
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
- uses: actions/setup-node@v3
with:
cache: "yarn"
env:
# Workaround for https://github.com/actions/setup-node/issues/317
FORCE_COLOR: 0
- name: Install libsqlcipher-dev
if: inputs.sqlcipher == 'system'
run: sudo apt-get install -y libsqlcipher-dev
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- uses: actions/setup-node@v3
with:
cache: "yarn"
- name: Build Natives
if: steps.cache.outputs.cache-hit != 'true'
run: "yarn build:native"
env:
SQLCIPHER_STATIC: ${{ inputs.sqlcipher == 'static' && '1' || '' }}
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --pure-lockfile"
- name: "[Nightly] Resolve version"
id: nightly
if: inputs.version != ''
run: |
echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT
- name: Build Natives
run: "yarn build:native"
env:
SQLCIPHER_STATIC: ${{ inputs.sqlcipher == 'static' && '1' || '' }}
- name: Generate debian files and arguments
id: debian
run: |
if [ -f changelog.Debian ]; then
echo "config-args=--deb-changelog changelog.Debian" >> $GITHUB_OUTPUT
fi
- name: Build App
run: "yarn build --publish never -l"
cp "$DIR/control.template" debcontrol
VERSION=${INPUT_VERSION:-$(cat package.json | jq -r .version)}
echo "Version: $VERSION" >> debcontrol
env:
DIR: ${{ inputs.config }}
INPUT_VERSION: ${{ inputs.version }}
- name: Install .deb
run: "sudo apt install ./dist/*.deb"
- name: Build App
run: |
npx ts-node scripts/generate-builder-config.ts \
${{ steps.nightly.outputs.config-args }} \
${{ steps.debian.outputs.config-args }} \
--deb-custom-control=debcontrol
yarn build --publish never -l --config electron-builder.json
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: linux-sqlcipher-${{ inputs.sqlcipher }}
path: dist
retention-days: 1
- name: Check ldd
run: |
ldd dist/linux-unpacked/resources/app.asar.unpacked/node_modules/matrix-seshat/native/index.node
if [ "$SQLCIPHER_STATIC" == "1" ]; then
ldd dist/linux-unpacked/resources/app.asar.unpacked/node_modules/matrix-seshat/native/index.node | grep -v libsqlcipher.so.0
ldd dist/linux-unpacked/resources/app.asar.unpacked/node_modules/matrix-seshat/native/index.node | grep libcrypto.so.1.1
else
ldd dist/linux-unpacked/resources/app.asar.unpacked/node_modules/matrix-seshat/native/index.node | grep libsqlcipher.so.0
ldd dist/linux-unpacked/resources/app.asar.unpacked/node_modules/matrix-seshat/native/index.node | grep -v libcrypto.so.1.1
fi
env:
SQLCIPHER_STATIC: ${{ inputs.sqlcipher == 'static' && '1' || '' }}
- name: Stash deb package
if: inputs.deploy-mode
uses: actions/upload-artifact@v3
with:
name: linux-sqlcipher-${{ inputs.sqlcipher }}-deb
path: dist/*.deb
retention-days: 1
- name: Prepare artifacts for deployment
if: inputs.deploy-mode
run: |
mv dist _dist
mkdir -p "dist/install/linux/glibc-x86-64/"
mv _dist/*.tar.gz "dist/install/linux/glibc-x86-64"
# We don't wish to store the tarball for every nightly ever, so we only keep the latest
- name: "[Nightly] Strip version from tarball"
if: inputs.deploy-mode && inputs.version != ''
run: |
mv dist/install/linux/glibc-x86-64/*.tar.gz "dist/install/linux/glibc-x86-64/element-desktop-nightly.tar.gz"
- name: "[Release] Prepare release latest symlink"
if: inputs.deploy-mode && inputs.version == ''
shell: bash
run: |
ln -s "$(find . -type f -iname "*.tar.gz" | xargs -0 -n1 -- basename)" "element-desktop.tar.gz"
working-directory: "dist/install/linux/glibc-x86-64"
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.deploy-mode && 'packages.element.io' || format('linux-sqlcipher-{0}', inputs.sqlcipher) }}
path: dist
retention-days: 1

View File

@@ -1,45 +1,155 @@
# This workflow relies on actions/cache to store the hak dependency artifacts as they take a long time to build
# Due to this extra care must be taken to only ever run all build_* scripts against the same branch to ensure
# the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch.
on:
workflow_call:
workflow_call:
secrets:
APPLE_ID:
required: false
APPLE_ID_PASSWORD:
required: false
APPLE_TEAM_ID:
required: false
APPLE_CSC_KEY_PASSWORD:
required: false
APPLE_CSC_LINK:
required: false
inputs:
version:
type: string
required: false
description: "Version string to override the one in package.json, used for non-release builds"
sign:
type: string
required: false
description: "Whether to sign & notarise the build, requires 'packages.element.io' environment"
deploy-mode:
type: boolean
required: false
description: "Whether to arrange artifacts in the arrangement needed for deployment, skipping unrelated ones"
base-url:
type: string
required: false
description: "The URL to which the output will be deployed, required if deploy-mode is enabled."
jobs:
build:
runs-on: macos-latest
steps:
- uses: actions/checkout@v3
build:
runs-on: macos-latest
environment: ${{ inputs.sign && 'packages.element.io' || '' }}
steps:
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: webapp
- uses: actions/download-artifact@v3
with:
name: webapp
- name: Cache .hak
uses: actions/cache@v3
with:
key: ${{ hashFiles('./yarn.lock') }}
path: |
./.hak
- name: Cache .hak
id: cache
uses: actions/cache@v3
with:
key: ${{ runner.os }}-${{ hashFiles('hakDependencies.json', 'electronVersion') }}
path: |
./.hak
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: aarch64-apple-darwin
- name: Install Rust
if: steps.cache.outputs.cache-hit != 'true'
uses: actions-rs/toolchain@v1
with:
default: true
toolchain: stable
target: aarch64-apple-darwin
- uses: actions/setup-node@v3
with:
cache: "yarn"
- uses: actions/setup-node@v3
with:
cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --pure-lockfile"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Build Natives
run: "yarn build:native:universal"
- name: Build Natives
if: steps.cache.outputs.cache-hit != 'true'
run: "yarn build:native:universal"
- name: Build App
run: "yarn build:universal --publish never"
- name: "[Nightly] Resolve version"
id: nightly
if: inputs.version != ''
run: |
echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: macos
path: dist
retention-days: 1
# We split these because electron-builder gets upset if we set CSC_LINK even to an empty string
- name: "[Signed] Build App"
if: inputs.sign != ''
run: |
scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} --notarytool-team-id='${{ secrets.APPLE_TEAM_ID }}'
yarn build:universal --publish never --config electron-builder.json
env:
APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_APP_SPECIFIC_PASSWORD: ${{ secrets.APPLE_ID_PASSWORD }}
CSC_KEY_PASSWORD: ${{ secrets.APPLE_CSC_KEY_PASSWORD }}
CSC_LINK: ${{ secrets.APPLE_CSC_LINK }}
- name: Check app was signed & notarised successfully
if: inputs.sign != ''
run: |
hdiutil attach dist/*.dmg
codesign -dv --verbose=4 /Volumes/Element*/*.app
spctl -a -vvv -t install /Volumes/Element*/*.app
hdiutil detach /Volumes/Element*
- name: "[Unsigned] Build App"
if: inputs.sign == ''
run: |
scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }}
yarn build:universal --publish never --config electron-builder.json
env:
CSC_IDENTITY_AUTO_DISCOVERY: false
- name: Prepare artifacts for deployment
if: inputs.deploy-mode
run: |
mv dist _dist
mkdir -p dist/install/macos dist/update/macos
mv _dist/*-mac.zip dist/update/macos/
mv _dist/*.dmg dist/install/macos/
PKG_JSON_VERSION=$(cat package.json | jq -r .version)
LATEST=$(find dist -type f -iname "*-mac.zip" | xargs -0 -n1 -- basename)
# Encode spaces in the URL as Squirrel.Mac complains about bad JSON otherwise
URL="${{ inputs.base-url }}/update/macos/${LATEST// /%20}"
jq -n --arg version "${VERSION:-$PKG_JSON_VERSION}" --arg url "$URL" '
{
currentRelease: $version,
releases: [{
version: $version,
updateTo: {
version: $version,
url: $url,
},
}],
}
' > dist/update/macos/releases.json
jq -n --arg url "$URL" '
{ url: $url }
' > dist/update/macos/releases-legacy.json
env:
VERSION: ${{ inputs.version }}
# We don't wish to store the installer for every nightly ever, so we only keep the latest
- name: "[Nightly] Strip version from installer file"
if: inputs.deploy-mode && inputs.version != ''
run: |
mv dist/install/macos/*.dmg "dist/install/macos/Element Nightly.dmg"
- name: "[Release] Prepare release latest symlink"
if: inputs.deploy-mode && inputs.version == ''
run: |
ln -s "$(find . -type f -iname "*.dmg" | xargs -0 -n1 -- basename)" "Element.dmg"
working-directory: "dist/install/macos"
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.deploy-mode && 'packages.element.io' || 'macos' }}
path: dist
retention-days: 1

View File

@@ -1,35 +1,127 @@
# This action helps perform common actions before the build_* actions are started in parallel.
on:
workflow_call:
inputs:
config:
type: string
required: true
description: "The config directory to use"
version:
type: string
required: false
description: "The version tag to fetch, or 'develop', will pick automatically if not passed"
workflow_call:
inputs:
config:
type: string
required: true
description: "The config directory to use"
version:
type: string
required: false
description: "The version tag to fetch, or 'develop', will pick automatically if not passed"
nightly:
type: boolean
required: false
default: false
description: "Whether the build is a Nightly and to calculate the version strings new builds should use"
secrets:
# Required if `nightly` is set
CF_R2_ACCESS_KEY_ID:
required: false
# Required if `nightly` is set
CF_R2_TOKEN:
required: false
# Required if `nightly` is set
CF_R2_S3_API:
required: false
outputs:
macos-version:
description: "The version string the next macOS Nightly should use, only output for nightly"
value: ${{ jobs.prepare.outputs.macos-version }}
linux-version:
description: "The version string the next Linux Nightly should use, only output for nightly"
value: ${{ jobs.prepare.outputs.linux-version }}
win32-x64-version:
description: "The version string the next Windows x64 Nightly should use, only output for nightly"
value: ${{ jobs.prepare.outputs.win32-x64-version }}
win32-x86-version:
description: "The version string the next Windows x86 Nightly should use, only output for nightly"
value: ${{ jobs.prepare.outputs.win32-x86-version }}
jobs:
prepare:
name: Prepare
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
prepare:
name: Prepare
environment: ${{ inputs.nightly && 'packages.element.io' || '' }}
runs-on: ubuntu-latest
outputs:
macos-version: ${{ steps.versions.outputs.macos }}
linux-version: ${{ steps.versions.outputs.linux }}
win32-x64-version: ${{ steps.versions.outputs.win_x64 }}
win32-x86-version: ${{ steps.versions.outputs.win_x86 }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: "yarn"
- uses: actions/setup-node@v3
with:
cache: "yarn"
- name: Install Deps
run: "yarn install --pure-lockfile"
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Fetch Element Web
run: yarn run fetch --noverify -d ${{ inputs.config }} ${{ inputs.version }}
- name: Fetch Element Web
run: yarn run fetch --noverify -d ${{ inputs.config }} ${{ inputs.version }}
- uses: actions/upload-artifact@v3
with:
name: webapp
retention-days: 1
path: |
webapp.asar
package.json
# We split this out to save the build_* scripts having to do it to make use of `hashFiles` in the cache action
- name: Generate cache hash files
run: |
yarn run --silent electron --version > electronVersion
cat package.json | jq -c .hakDependencies > hakDependencies.json
- name: "[Nightly] Calculate versions"
id: versions
if: inputs.nightly
run: |
MACOS=$(aws s3 cp s3://$R2_BUCKET/nightly/update/macos/releases.json - --endpoint-url $R2_URL --region auto | jq -r .currentRelease)
echo "macos=$(scripts/generate-nightly-version.ts --latest $MACOS)" >> $GITHUB_OUTPUT
LINUX=$(aws s3 cp s3://$R2_BUCKET/debian/dists/default/main/binary-amd64/Packages - --endpoint-url $R2_URL --region auto | grep "Package: element-nightly" -A 50 | grep Version -m1 | sed -n 's/Version: //p')
echo "linux=$(scripts/generate-nightly-version.ts --latest $LINUX)" >> $GITHUB_OUTPUT
WINx64=$(aws s3 cp s3://$R2_BUCKET/nightly/update/win32/x64/RELEASES - --endpoint-url $R2_URL --region auto | awk '{print $2}' | cut -d "-" -f 5 | cut -c 8-)
echo "win_x64=$(scripts/generate-nightly-version.ts --latest $WINx64)" >> $GITHUB_OUTPUT
WINx86=$(aws s3 cp s3://$R2_BUCKET/nightly/update/win32/ia32/RELEASES - --endpoint-url $R2_URL --region auto | awk '{print $2}' | cut -d "-" -f 5 | cut -c 8-)
echo "win_x86=$(scripts/generate-nightly-version.ts --latest $WINx86)" >> $GITHUB_OUTPUT
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
R2_BUCKET: "packages-element-io"
R2_URL: ${{ secrets.CF_R2_S3_API }}
- name: Check version
id: package
run: |
echo "version=$(cat package.json | jq -r .version)" >> $GITHUB_OUTPUT
- name: "[Release] Fetch release"
id: release
if: ${{ !inputs.nightly && inputs.version != 'develop' }}
uses: cardinalby/git-get-release-action@cedef2faf69cb7c55b285bad07688d04430b7ada # v1
env:
GITHUB_TOKEN: ${{ github.token }}
with:
tag: v${{ steps.package.outputs.version }}
- name: "[Release] Write changelog"
if: ${{ !inputs.nightly && inputs.version != 'develop' }}
run: |
TIME=$(date -d "$PUBLISHED_AT" -R)
echo "element-desktop ($VERSION) default; urgency=medium" >> changelog.Debian
echo "$BODY" | sed 's/^##/\n */g;s/^\*/ */g' | perl -pe 's/\[.+?]\((.+?)\)/\1/g' >> changelog.Debian
echo "" >> changelog.Debian
echo " -- $ACTOR <support@element.io> $TIME" >> changelog.Debian
env:
ACTOR: ${{ github.actor }}
VERSION: v${{ steps.package.outputs.version }}
BODY: ${{ steps.release.outputs.body }}
PUBLISHED_AT: ${{ steps.release.outputs.published_at }}
- uses: actions/upload-artifact@v3
with:
name: webapp
retention-days: 1
path: |
webapp.asar
package.json
electronVersion
hakDependencies.json
changelog.Debian

View File

@@ -1,87 +1,205 @@
# This workflow relies on actions/cache to store the hak dependency artifacts as they take a long time to build
# Due to this extra care must be taken to only ever run all build_* scripts against the same branch to ensure
# the correct cache scoping, and additional care must be taken to not run untrusted actions on the develop branch.
on:
workflow_call:
inputs:
arch:
type: string
required: true
description: "The architecture to build for, one of 'x64' | 'x86'"
workflow_call:
secrets:
ESIGNER_USER_NAME:
required: false
ESIGNER_USER_PASSWORD:
required: false
ESIGNER_USER_TOTP:
required: false
inputs:
arch:
type: string
required: true
description: "The architecture to build for, one of 'x64' | 'x86' | 'arm64'"
version:
type: string
required: false
description: "Version string to override the one in package.json, used for non-release builds"
sign:
type: string
required: false
description: "Whether to sign & notarise the build, requires 'packages.element.io' environment"
deploy-mode:
type: boolean
required: false
description: "Whether to arrange artifacts in the arrangement needed for deployment, skipping unrelated ones"
jobs:
build:
runs-on: windows-latest
steps:
- uses: kanga333/variable-mapper@master
id: config
with:
key: "${{ inputs.arch }}"
export_to: output
map: |
{
"x64": {
"target": "x86_64-pc-windows-msvc"
},
"x86": {
"target": "i686-pc-windows-msvc",
"build-args": "--ia32"
}
}
build:
runs-on: windows-latest
environment: ${{ inputs.sign && 'packages.element.io' || '' }}
env:
SIGNTOOL_PATH: "C:/Program Files (x86)/Windows Kits/10/bin/10.0.22000.0/x86/signtool.exe"
steps:
- uses: kanga333/variable-mapper@master
id: config
with:
key: "${{ inputs.arch }}"
export_to: output
map: |
{
"x64": {
"target": "x86_64-pc-windows-msvc",
"dir": "x64"
},
"arm64": {
"target": "aarch64-pc-windows-msvc",
"build-args": "--arm64",
"arch": "amd64_arm64",
"dir": "arm64"
},
"x86": {
"target": "i686-pc-windows-msvc",
"build-args": "--ia32",
"dir": "ia32"
}
}
- uses: actions/checkout@v3
- uses: actions/checkout@v3
- uses: actions/download-artifact@v3
with:
name: webapp
- uses: actions/download-artifact@v3
with:
name: webapp
- name: Cache .hak
uses: actions/cache@v3
with:
key: ${{ runner.os }}-${{ hashFiles('./yarn.lock') }}
path: |
./.hak
- name: Cache .hak
id: cache
uses: actions/cache@v3
with:
key: ${{ runner.os }}-${{ inputs.arch }}-${{ hashFiles('hakDependencies.json', 'electronVersion') }}
path: |
./.hak
- name: Set up build tools
uses: ilammy/msvc-dev-cmd@v1
with:
arch: ${{ inputs.arch }}
- name: Set up build tools
uses: ilammy/msvc-dev-cmd@v1
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
shell: pwsh
run: |
choco install -y magicsplat-tcl-tk --no-progress
echo "${HOME}/AppData/Local/Apps/Tcl86/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
# ActiveTCL package on choco is from 2015,
# this one is newer but includes more than we need
- name: Choco install tclsh
if: steps.cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
choco install -y magicsplat-tcl-tk --no-progress
echo "${HOME}/AppData/Local/Apps/Tcl86/bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Choco install NetWide Assembler
shell: pwsh
run: |
choco install -y nasm --no-progress
echo "C:/Program Files/NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Choco install NetWide Assembler
if: steps.cache.outputs.cache-hit != 'true'
shell: pwsh
run: |
choco install -y nasm --no-progress
echo "C:/Program Files/NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install Rust
uses: actions-rs/toolchain@v1
with:
toolchain: stable
target: ${{ steps.config.outputs.target }}
- name: Install Rust
if: steps.cache.outputs.cache-hit != 'true'
uses: actions-rs/toolchain@v1
with:
default: true
toolchain: stable
target: ${{ steps.config.outputs.target }}
- uses: actions/setup-node@v3
with:
cache: "yarn"
- uses: actions/setup-node@v3
with:
cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --pure-lockfile"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Build Natives
run: |
refreshenv
yarn build:native --target ${{ steps.config.outputs.target }}
- name: Build Natives
if: steps.cache.outputs.cache-hit != 'true'
run: |
refreshenv
yarn build:native --target ${{ steps.config.outputs.target }}
- name: Build App
run: "yarn build --publish never -w ${{ steps.config.outputs.build-args }}"
- name: Install and configure eSigner CKA
id: esigner
if: inputs.sign
run: |
Set-StrictMode -Version 'Latest'
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: win-${{ inputs.arch }}
path: dist
retention-days: 1
# Download
Invoke-WebRequest -OutFile eSigner_CKA.exe "https://packages.element.io/tools/SSL.COM%20eSigner%20CKA_1.0.4-build-20230221_signed.exe"
# Install
New-Item -ItemType Directory -Force -Path "$env:INSTALL_DIR"
./eSigner_CKA.exe /CURRENTUSER /VERYSILENT /SUPPRESSMSGBOXES /DIR="${{ env.INSTALL_DIR }}" | Out-Null
# Disable logger
$LogConfig = Get-Content -Path ${{ env.INSTALL_DIR }}/log4net.config
$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
${{ env.INSTALL_DIR }}/eSignerCKATool.exe unload
${{ env.INSTALL_DIR }}/eSignerCKATool.exe load
# Find certificate
$CodeSigningCert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert | Select-Object -First 1
echo Certificate: $CodeSigningCert
# Extract thumbprint and subject name
$Thumbprint = $CodeSigningCert.Thumbprint
$SubjectName = ($CodeSigningCert.Subject -replace ", ?", "`n" | ConvertFrom-StringData).CN
echo "config-args=--signtool-thumbprint '$Thumbprint' --signtool-subject-name '$SubjectName'" >> $env:GITHUB_OUTPUT
env:
INSTALL_DIR: C:\Users\runneradmin\eSignerCKA
MASTER_KEY_FILE: C:\Users\runneradmin\eSignerCKA\master.key
- name: "[Nightly] Resolve version"
id: nightly
if: inputs.version != ''
shell: bash
run: |
echo "config-args=--nightly '${{ inputs.version }}'" >> $GITHUB_OUTPUT
- name: Build App
run: |
yarn ts-node scripts/generate-builder-config.ts ${{ steps.nightly.outputs.config-args }} ${{ steps.esigner.outputs.config-args }}
yarn build --publish never -w --config electron-builder.json ${{ steps.config.outputs.build-args }}
- name: Check app was signed successfully
if: inputs.sign != ''
run: |
. "$env:SIGNTOOL_PATH" verify /pa (get-item ./dist/squirrel-windows*/*.exe)
- name: Prepare artifacts for deployment
if: inputs.deploy-mode
shell: bash
run: |
mv dist _dist
mkdir -p "dist/install/win32/$DIR/msi" "dist/update/win32/$DIR"
mv _dist/squirrel-windows*/*.exe "dist/install/win32/$DIR"
mv _dist/squirrel-windows*/*.nupkg "dist/update/win32/$DIR/"
mv _dist/squirrel-windows*/RELEASES "dist/update/win32/$DIR/"
# mv _dist/*.msi "dist/install/win32/$DIR/msi/"
env:
DIR: ${{ steps.config.outputs.dir }}
# We don't wish to store the installer for every nightly ever, so we only keep the latest
- name: "[Nightly] Strip version from installer file"
if: inputs.deploy-mode && inputs.version != ''
shell: bash
run: |
mv dist/install/win32/$DIR/*.exe "dist/install/win32/$DIR/Element Nightly Setup.exe"
# mv dist/install/win32/$DIR/msi/*.msi "dist/install/win32/$DIR/msi/Element Nightly Setup.msi"
env:
DIR: ${{ steps.config.outputs.dir }}
- name: "[Release] Prepare release latest symlink"
if: inputs.deploy-mode && inputs.version == ''
shell: bash
run: |
ln -s "$(find . -type f -iname "*.exe" | xargs -0 -n1 -- basename)" "Element Setup.exe"
working-directory: "dist/install/win32/${{ steps.config.outputs.dir }}"
- name: Upload Artifacts
uses: actions/upload-artifact@v3
with:
name: ${{ inputs.deploy-mode && 'packages.element.io' || format('win-{0}', inputs.arch) }}
path: dist
retention-days: 1

51
.github/workflows/codeql.yml vendored Normal file
View File

@@ -0,0 +1,51 @@
name: "CodeQL"
on:
push:
branches: [ "develop", master, staging ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "develop" ]
schedule:
- cron: '19 9 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
# We have a single C file for the rebrand_stub which we don't want/need to analyse
# but it prevents us from using the built-in CodeQL scanner
language: [ 'javascript' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

43
.github/workflows/dockerbuild.yaml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: Dockerbuild
on:
workflow_dispatch: {}
push:
branches: [master, develop]
paths:
- "dockerbuild/**"
concurrency: ${{ github.workflow }}-${{ github.ref_name }}
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}-dockerbuild
jobs:
build:
name: Docker Build
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- uses: actions/checkout@v3
- name: Log in to the Container registry
uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata for Docker
id: meta
uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
- name: Build and push Docker image
uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
with:
context: dockerbuild
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}

View File

@@ -1,43 +1,49 @@
name: Generate packages.element.io directory indexes
on:
# Trigger a rebuild of all indexes if the template gets updated
push:
branches: [ develop ]
paths:
- 'packages.element.io/**'
# Trigger a daily rebuild for nightlies
schedule:
- cron: '0 11 * * *'
# Manual trigger for rebuilding for releases
workflow_dispatch: { }
# Trigger a rebuild of all indexes if the template gets updated
push:
branches: [develop]
paths:
- "packages.element.io/**"
# Trigger a daily rebuild for (mac-mini built) Nightly builds
schedule:
- cron: "0 11 * * *"
# Trigger after Nightly builds are deployed
workflow_run:
workflows: ["Build and Deploy"]
types:
- completed
# Manual trigger for rebuilding for releases
workflow_dispatch: {}
jobs:
deploy:
name: "Deploy"
runs-on: ubuntu-latest
environment: develop
env:
R2_BUCKET: 'packages-element-io'
R2_URL: ${{ secrets.CF_R2_S3_API }}
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: "yarn"
- name: Install Deps
run: "yarn install --pure-lockfile"
- name: Copy static files
if: github.event_name == 'push'
run: aws s3 cp --recursive packages.element.io/ s3://$R2_BUCKET/ --endpoint-url $R2_URL --region auto
deploy:
name: "Deploy"
if: github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success'
runs-on: ubuntu-latest
environment: packages.element.io
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
R2_BUCKET: "packages-element-io"
R2_URL: ${{ secrets.CF_R2_S3_API }}
steps:
- uses: actions/checkout@v3
- name: Generate directory indexes
run: scripts/generate-packages-index.ts
env:
CF_R2_S3_API: ${{ secrets.CF_R2_S3_API }}
CF_R2_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
CF_R2_TOKEN: ${{ secrets.CF_R2_TOKEN }}
- uses: actions/setup-node@v3
with:
cache: "yarn"
- name: Install Deps
run: "yarn install --pure-lockfile"
- name: Copy static files
if: github.event_name == 'push'
run: aws s3 cp --recursive packages.element.io/ s3://$R2_BUCKET/ --endpoint-url $R2_URL --region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
- name: Generate directory indexes
run: scripts/generate-packages-index.ts
env:
CF_R2_S3_API: ${{ secrets.CF_R2_S3_API }}
CF_R2_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
CF_R2_TOKEN: ${{ secrets.CF_R2_TOKEN }}

View File

@@ -1,12 +1,9 @@
name: Pull Request
on:
pull_request_target:
types: [ opened, edited, labeled, unlabeled, synchronize ]
concurrency: ${{ github.workflow }}-${{ github.event.pull_request.head.ref }}
pull_request_target:
types: [opened, edited, labeled, unlabeled, synchronize]
jobs:
action:
uses: matrix-org/matrix-js-sdk/.github/workflows/pull_request.yaml@develop
with:
labels: "T-Defect,T-Enhancement,T-Task"
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
action:
uses: matrix-org/matrix-js-sdk/.github/workflows/pull_request.yaml@develop
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

91
.github/workflows/reprepro.yaml vendored Normal file
View File

@@ -0,0 +1,91 @@
on:
workflow_call:
inputs:
artifact-name:
type: string
required: true
description: "The name of the artifact containing the debs to include"
secrets:
GPG_PRIVATE_KEY:
required: false
GPG_PASSPHRASE:
required: false
CF_R2_ACCESS_KEY_ID:
required: false
CF_R2_TOKEN:
required: false
CF_R2_S3_API:
required: false
# Protect reprepro database using concurrency
concurrency: reprepro
jobs:
reprepro:
name: Deploy debian package
environment: packages.element.io
runs-on: ubuntu-latest
env:
R2_BUCKET: "packages-element-io"
R2_DB_BUCKET: packages-element-io-db
R2_URL: ${{ secrets.CF_R2_S3_API }}
steps:
- uses: actions/checkout@v3
- name: Download artifacts
uses: actions/download-artifact@v3
with:
name: ${{ inputs.artifact-name }}
path: dist
- name: Load GPG key
uses: crazy-max/ghaction-import-gpg@111c56156bcc6918c056dbef52164cfa583dc549 # v5
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
fingerprint: 75741890063E5E9A46135D01C2850B265AC085BD
- name: Install reprepro
run: sudo apt-get install -y reprepro
- name: Fetch database
run: aws s3 cp --recursive s3://$R2_DB_BUCKET debian/db/ --endpoint-url $R2_URL --region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
- name: Run reprepro
run: |
grep Codename debian/conf/distributions | sed -n 's/Codename: //p' | while read -r target ; do
reprepro -b debian includedeb "$target" ./dist/*.deb
done
- name: Check repository works
run: |
# Download signing keyring
sudo wget -O /usr/share/keyrings/element-io-archive-keyring.gpg https://packages.element.io/debian/element-io-archive-keyring.gpg
# Point apt at local apt repo
echo "deb [signed-by=/usr/share/keyrings/element-io-archive-keyring.gpg] http://127.0.0.1:8000/debian/ default main" | sudo tee /etc/apt/sources.list.d/element-io.list
# Start http server and fetch from it via apt
python3 -m http.server 8000 --bind 127.0.0.1 &
sudo apt-get update --allow-insecure-repositories
killall python3
# Validate the package in the repo quacks like the one we expect
info=$(dpkg --info ../dist/*.deb)
package=$(echo "$info" | grep "Package:" | sed -n 's/ Package: //p')
version=$(echo "$info" | grep "Version:" | sed -n 's/ Version: //p')
apt-cache show "$package" | grep "Version: $version"
working-directory: ./packages.element.io
- name: Deploy debian repo
run: |
aws s3 cp --recursive packages.element.io/debian/ s3://$R2_BUCKET/debian --endpoint-url $R2_URL --region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}
- name: Store database
run: aws s3 cp --recursive debian/db/ s3://$R2_DB_BUCKET --endpoint-url $R2_URL --region auto
env:
AWS_ACCESS_KEY_ID: ${{ secrets.CF_R2_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_R2_TOKEN }}

View File

@@ -1,43 +1,43 @@
name: Static Analysis
on:
pull_request: { }
push:
branches: [ develop, master ]
pull_request: {}
push:
branches: [develop, master]
jobs:
ts_lint:
name: "Typescript Syntax Check"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
ts_lint:
name: "Typescript Syntax Check"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: 'yarn'
- uses: actions/setup-node@v3
with:
cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --pure-lockfile"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Typecheck
run: "yarn run lint:types"
- name: Typecheck
run: "yarn run lint:types"
i18n_lint:
name: "i18n Check"
uses: matrix-org/matrix-react-sdk/.github/workflows/i18n_check.yml@develop
i18n_lint:
name: "i18n Check"
uses: matrix-org/matrix-react-sdk/.github/workflows/i18n_check.yml@develop
js_lint:
name: "ESLint"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
js_lint:
name: "ESLint"
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
with:
cache: 'yarn'
- uses: actions/setup-node@v3
with:
cache: "yarn"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --pure-lockfile"
# Does not need branch matching as only analyses this layer
- name: Install Deps
run: "yarn install --frozen-lockfile"
- name: Run Linter
run: "yarn run lint:js"
- name: Run Linter
run: "yarn run lint:js"

View File

@@ -1,8 +1,8 @@
name: Upgrade Dependencies
on:
workflow_dispatch: { }
workflow_dispatch: {}
jobs:
upgrade:
uses: matrix-org/matrix-js-sdk/.github/workflows/upgrade_dependencies.yml@develop
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}
upgrade:
uses: matrix-org/matrix-js-sdk/.github/workflows/upgrade_dependencies.yml@develop
secrets:
ELEMENT_BOT_TOKEN: ${{ secrets.ELEMENT_BOT_TOKEN }}

3
.gitignore vendored
View File

@@ -14,3 +14,6 @@ node_modules/
.vscode/
/test_artifacts/
/coverage/
yarn-error.log
/hak/**/*.js
/scripts/hak/**/*.js

19
.prettierignore Normal file
View File

@@ -0,0 +1,19 @@
/build/
/dockerbuild/
/lib/
/node_modules/
/packages.elememt.io/
/webapp
/src/i18n/strings
/CHANGELOG.md
/package-lock.json
/yarn.lock
**/.idea
.vscode
.vscode/
.tmp
.env
/coverage
/.npmrc
/*.log

1
.prettierrc.js Normal file
View File

@@ -0,0 +1 @@
module.exports = require("eslint-plugin-matrix-org/.prettierrc.js");

View File

@@ -1,3 +1,435 @@
Changes in [1.11.29](https://github.com/vector-im/element-desktop/releases/tag/v1.11.29) (2023-04-11)
=====================================================================================================
## ✨ Features
* Ship linux tarball with static sqlcipher ([\#597](https://github.com/vector-im/element-desktop/pull/597)). Fixes vector-im/element-web#18486.
* Show recent room breadcrumbs on touchbar ([\#183](https://github.com/vector-im/element-desktop/pull/183)). Fixes vector-im/element-web#15998.
* Clear electron data when logging out ([\#578](https://github.com/vector-im/element-desktop/pull/578)).
* Send Electron crashpad reports to Sentry from Nightly ([\#579](https://github.com/vector-im/element-desktop/pull/579)). Fixes vector-im/element-web#18263.
* Recommend element-io-archive-keyring from our Debian package ([\#566](https://github.com/vector-im/element-desktop/pull/566)).
* Allow desktop app to expose recent rooms in UI integrations ([\#16940](https://github.com/vector-im/element-web/pull/16940)).
* Add API params to mute audio and/or video in Jitsi calls by default ([\#24820](https://github.com/vector-im/element-web/pull/24820)). Contributed by @dhenneke.
* Style mentions as pills in rich text editor ([\#10448](https://github.com/matrix-org/matrix-react-sdk/pull/10448)). Contributed by @alunturner.
* Show room create icon if "UIComponent.roomCreation" is enabled ([\#10364](https://github.com/matrix-org/matrix-react-sdk/pull/10364)). Contributed by @maheichyk.
* Mentions as links rte ([\#10463](https://github.com/matrix-org/matrix-react-sdk/pull/10463)). Contributed by @alunturner.
* Better error handling in jump to date ([\#10405](https://github.com/matrix-org/matrix-react-sdk/pull/10405)). Contributed by @MadLittleMods.
* Show "Invite" menu option if "UIComponent.sendInvites" is enabled. ([\#10363](https://github.com/matrix-org/matrix-react-sdk/pull/10363)). Contributed by @maheichyk.
* Added `UserProfilesStore`, `LruCache` and user permalink profile caching ([\#10425](https://github.com/matrix-org/matrix-react-sdk/pull/10425)). Fixes vector-im/element-web#10559.
* Mentions as links rte ([\#10422](https://github.com/matrix-org/matrix-react-sdk/pull/10422)). Contributed by @alunturner.
* Implement MSC3952: intentional mentions ([\#9983](https://github.com/matrix-org/matrix-react-sdk/pull/9983)).
* Implement MSC3973: Search users in the user directory with the Widget API ([\#10269](https://github.com/matrix-org/matrix-react-sdk/pull/10269)). Contributed by @dhenneke.
* Permalinks to message are now displayed as pills ([\#10392](https://github.com/matrix-org/matrix-react-sdk/pull/10392)). Fixes vector-im/element-web#24751 and vector-im/element-web#24706.
* Show search,dial,explore in filterContainer if "UIComponent.filterContainer" is enabled ([\#10381](https://github.com/matrix-org/matrix-react-sdk/pull/10381)). Contributed by @maheichyk.
* Increase space panel collapse clickable area ([\#6084](https://github.com/matrix-org/matrix-react-sdk/pull/6084)). Fixes vector-im/element-web#17379. Contributed by @jaiwanth-v.
* Add fallback for replies to Polls ([\#10380](https://github.com/matrix-org/matrix-react-sdk/pull/10380)). Fixes vector-im/element-web#24197. Contributed by @kerryarchibald.
* Permalinks to rooms and users are now pillified ([\#10388](https://github.com/matrix-org/matrix-react-sdk/pull/10388)). Fixes vector-im/element-web#24825.
* Poll history - access poll history from room settings ([\#10356](https://github.com/matrix-org/matrix-react-sdk/pull/10356)). Contributed by @kerryarchibald.
* Add API params to mute audio and/or video in Jitsi calls by default ([\#10376](https://github.com/matrix-org/matrix-react-sdk/pull/10376)). Contributed by @dhenneke.
* Notifications: inline error message on notifications saving error ([\#10288](https://github.com/matrix-org/matrix-react-sdk/pull/10288)). Contributed by @kerryarchibald.
* Support dynamic room predecessor in SpaceProvider ([\#10348](https://github.com/matrix-org/matrix-react-sdk/pull/10348)). Contributed by @andybalaam.
* Support dynamic room predecessors for RoomProvider ([\#10346](https://github.com/matrix-org/matrix-react-sdk/pull/10346)). Contributed by @andybalaam.
* Support dynamic room predecessors in OwnBeaconStore ([\#10339](https://github.com/matrix-org/matrix-react-sdk/pull/10339)). Contributed by @andybalaam.
* Support dynamic room predecessors in ForwardDialog ([\#10344](https://github.com/matrix-org/matrix-react-sdk/pull/10344)). Contributed by @andybalaam.
* Support dynamic room predecessors in SpaceHierarchy ([\#10341](https://github.com/matrix-org/matrix-react-sdk/pull/10341)). Contributed by @andybalaam.
* Support dynamic room predecessors in AddExistingToSpaceDialog ([\#10342](https://github.com/matrix-org/matrix-react-sdk/pull/10342)). Contributed by @andybalaam.
* Support dynamic room predecessors in leave-behaviour ([\#10340](https://github.com/matrix-org/matrix-react-sdk/pull/10340)). Contributed by @andybalaam.
* Support dynamic room predecessors in StopGapWidgetDriver ([\#10338](https://github.com/matrix-org/matrix-react-sdk/pull/10338)). Contributed by @andybalaam.
* Support dynamic room predecessors in WidgetLayoutStore ([\#10326](https://github.com/matrix-org/matrix-react-sdk/pull/10326)). Contributed by @andybalaam.
* Support dynamic room predecessors in SpaceStore ([\#10332](https://github.com/matrix-org/matrix-react-sdk/pull/10332)). Contributed by @andybalaam.
* Sync polls push rules on changes to account_data ([\#10287](https://github.com/matrix-org/matrix-react-sdk/pull/10287)). Contributed by @kerryarchibald.
* Support dynamic room predecessors in BreadcrumbsStore ([\#10295](https://github.com/matrix-org/matrix-react-sdk/pull/10295)). Contributed by @andybalaam.
* Improved a11y for Field feedback and Secure Phrase input ([\#10320](https://github.com/matrix-org/matrix-react-sdk/pull/10320)). Contributed by @Sebbones.
* Support dynamic room predecessors in RoomNotificationStateStore ([\#10297](https://github.com/matrix-org/matrix-react-sdk/pull/10297)). Contributed by @andybalaam.
## 🐛 Bug Fixes
* Run build_linux in docker using an older glibc ([\#599](https://github.com/vector-im/element-desktop/pull/599)). Fixes vector-im/element-web#24981.
* Use a newly generated access_token while joining Jitsi ([\#24646](https://github.com/vector-im/element-web/pull/24646)). Fixes vector-im/element-web#24687. Contributed by @emrahcom.
* Fix cloudflare action pointing at commit hash instead of tag ([\#24777](https://github.com/vector-im/element-web/pull/24777)). Contributed by @justjanne.
* Allow editing with RTE to overflow for autocomplete visibility ([\#10499](https://github.com/matrix-org/matrix-react-sdk/pull/10499)). Contributed by @alunturner.
* Added auto focus to Github URL on opening of debug logs modal ([\#10479](https://github.com/matrix-org/matrix-react-sdk/pull/10479)). Contributed by @ShivamSpm.
* Fix detection of encryption for all users in a room ([\#10487](https://github.com/matrix-org/matrix-react-sdk/pull/10487)). Fixes vector-im/element-web#24995.
* Properly generate mentions when editing a reply with MSC3952 ([\#10486](https://github.com/matrix-org/matrix-react-sdk/pull/10486)). Fixes vector-im/element-web#24924. Contributed by @kerryarchibald.
* Improve performance of rendering a room with many hidden events ([\#10131](https://github.com/matrix-org/matrix-react-sdk/pull/10131)). Contributed by @andybalaam.
* Prevent future date selection in jump to date ([\#10419](https://github.com/matrix-org/matrix-react-sdk/pull/10419)). Fixes vector-im/element-web#20800. Contributed by @MadLittleMods.
* Add aria labels to message search bar to improve accessibility ([\#10476](https://github.com/matrix-org/matrix-react-sdk/pull/10476)). Fixes vector-im/element-web#24921.
* Fix decryption failure bar covering the timeline ([\#10360](https://github.com/matrix-org/matrix-react-sdk/pull/10360)). Fixes vector-im/element-web#24780 vector-im/element-web#24074 and vector-im/element-web#24183. Contributed by @luixxiul.
* Improve profile picture settings accessibility ([\#10470](https://github.com/matrix-org/matrix-react-sdk/pull/10470)). Fixes vector-im/element-web#24919.
* Handle group call redaction ([\#10465](https://github.com/matrix-org/matrix-react-sdk/pull/10465)).
* Display relative timestamp for threads on the same calendar day ([\#10399](https://github.com/matrix-org/matrix-react-sdk/pull/10399)). Fixes vector-im/element-web#24841. Contributed by @kerryarchibald.
* Fix timeline list and paragraph display issues ([\#10424](https://github.com/matrix-org/matrix-react-sdk/pull/10424)). Fixes vector-im/element-web#24602. Contributed by @alunturner.
* Use unique keys for voice broadcast pips ([\#10457](https://github.com/matrix-org/matrix-react-sdk/pull/10457)). Fixes vector-im/element-web#24959.
* Fix "show read receipts sent by other users" not applying to threads ([\#10445](https://github.com/matrix-org/matrix-react-sdk/pull/10445)). Fixes vector-im/element-web#24910.
* Fix joining public rooms without aliases in search dialog ([\#10437](https://github.com/matrix-org/matrix-react-sdk/pull/10437)). Fixes vector-im/element-web#23937.
* Add input validation for `m.direct` in `DMRoomMap` ([\#10436](https://github.com/matrix-org/matrix-react-sdk/pull/10436)). Fixes vector-im/element-web#24909.
* Reduce height reserved for "collapse" button's line on IRC layout ([\#10211](https://github.com/matrix-org/matrix-react-sdk/pull/10211)). Fixes vector-im/element-web#24605. Contributed by @luixxiul.
* Fix `creatorUserId is required` error when opening sticker picker ([\#10423](https://github.com/matrix-org/matrix-react-sdk/pull/10423)).
* Fix block/inline Element descendants error noise in `NewRoomIntro.tsx` ([\#10412](https://github.com/matrix-org/matrix-react-sdk/pull/10412)). Contributed by @MadLittleMods.
* Fix profile resizer to make first character of a line selectable in IRC layout ([\#10396](https://github.com/matrix-org/matrix-react-sdk/pull/10396)). Fixes vector-im/element-web#14764. Contributed by @luixxiul.
* Ensure space between wrapped lines of room name on IRC layout ([\#10188](https://github.com/matrix-org/matrix-react-sdk/pull/10188)). Fixes vector-im/element-web#24742. Contributed by @luixxiul.
* Remove unreadable alt attribute from the room status bar warning icon (nonsense to screenreaders) ([\#10402](https://github.com/matrix-org/matrix-react-sdk/pull/10402)). Contributed by @MadLittleMods.
* Fix big date separators when jump to date is enabled ([\#10404](https://github.com/matrix-org/matrix-react-sdk/pull/10404)). Fixes vector-im/element-web#22969. Contributed by @MadLittleMods.
* Fixes user authentication when registering via the module API ([\#10257](https://github.com/matrix-org/matrix-react-sdk/pull/10257)). Contributed by @maheichyk.
* Handle more edge cases in Space Hierarchy ([\#10280](https://github.com/matrix-org/matrix-react-sdk/pull/10280)). Contributed by @justjanne.
* Further improve performance with lots of hidden events ([\#10353](https://github.com/matrix-org/matrix-react-sdk/pull/10353)). Fixes vector-im/element-web#24480. Contributed by @andybalaam.
* Respect user cancelling upload flow by dismissing spinner ([\#10373](https://github.com/matrix-org/matrix-react-sdk/pull/10373)). Fixes vector-im/element-web#24667.
* When starting a DM, the end-to-end encryption status icon does now only appear if the DM can be encrypted ([\#10394](https://github.com/matrix-org/matrix-react-sdk/pull/10394)). Fixes vector-im/element-web#24397.
* Fix `[object Object]` in feedback metadata ([\#10390](https://github.com/matrix-org/matrix-react-sdk/pull/10390)).
* Fix pinned messages card saying nothing pinned while loading ([\#10385](https://github.com/matrix-org/matrix-react-sdk/pull/10385)). Fixes vector-im/element-web#24615.
* Fix import e2e key dialog staying disabled after paste ([\#10375](https://github.com/matrix-org/matrix-react-sdk/pull/10375)). Fixes vector-im/element-web#24818.
* Show all labs even if incompatible, with appropriate tooltip explaining requirements ([\#10369](https://github.com/matrix-org/matrix-react-sdk/pull/10369)). Fixes vector-im/element-web#24813.
* Fix UIFeature.Registration not applying to all paths ([\#10371](https://github.com/matrix-org/matrix-react-sdk/pull/10371)). Fixes vector-im/element-web#24814.
* Clicking on a user pill does now only open the profile in the right panel and no longer navigates to the home view. ([\#10359](https://github.com/matrix-org/matrix-react-sdk/pull/10359)). Fixes vector-im/element-web#24797.
* Fix start DM with pending third party invite ([\#10347](https://github.com/matrix-org/matrix-react-sdk/pull/10347)). Fixes vector-im/element-web#24781.
* Fix long display name overflowing reply tile on IRC layout ([\#10343](https://github.com/matrix-org/matrix-react-sdk/pull/10343)). Fixes vector-im/element-web#24738. Contributed by @luixxiul.
* Display redacted body on ThreadView in the same way as normal messages ([\#9016](https://github.com/matrix-org/matrix-react-sdk/pull/9016)). Fixes vector-im/element-web#24729. Contributed by @luixxiul.
* Handle more edge cases in ACL updates ([\#10279](https://github.com/matrix-org/matrix-react-sdk/pull/10279)). Contributed by @justjanne.
* Allow parsing png files to fail if thumbnailing is successful ([\#10308](https://github.com/matrix-org/matrix-react-sdk/pull/10308)).
Changes in [1.11.28](https://github.com/vector-im/element-desktop/releases/tag/v1.11.28) (2023-03-31)
=====================================================================================================
## 🐛 Bug Fixes
* Fix broken lockfile. Fixes vector-im/element-web#25008.
Changes in [1.11.27](https://github.com/vector-im/element-desktop/releases/tag/v1.11.27) (2023-03-31)
=====================================================================================================
## 🐛 Bug Fixes
* Run build_linux in docker using an older glibc ([\#599](https://github.com/vector-im/element-desktop/pull/599)). Fixes vector-im/element-web#24981.
* Fix detection of encryption for all users in a room ([\#10487](https://github.com/matrix-org/matrix-react-sdk/pull/10487)). Fixes vector-im/element-web#24995.
Changes in [1.11.26](https://github.com/vector-im/element-desktop/releases/tag/v1.11.26) (2023-03-28)
=====================================================================================================
## 🔒 Security
* Fixes for [CVE-2023-28427](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=CVE-2023-28427) / GHSA-mwq8-fjpf-c2gr
* Fixes for [CVE-2023-28103](https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=CVE-2023-28103) / GHSA-6g43-88cp-w5gv
Changes in [1.11.25](https://github.com/vector-im/element-desktop/releases/tag/v1.11.25) (2023-03-15)
=====================================================================================================
## ✨ Features
* Remove experimental PWA support for Firefox and Safari ([\#24630](https://github.com/vector-im/element-web/pull/24630)).
* Only allow to start a DM with one email if encryption by default is enabled ([\#10253](https://github.com/matrix-org/matrix-react-sdk/pull/10253)). Fixes vector-im/element-web#23133.
* DM rooms are now encrypted if encryption by default is enabled and only inviting a single email address. Any action in the result DM room will be blocked until the other has joined. ([\#10229](https://github.com/matrix-org/matrix-react-sdk/pull/10229)).
* Reduce bottom margin of ReplyChain on compact modern layout ([\#8972](https://github.com/matrix-org/matrix-react-sdk/pull/8972)). Fixes vector-im/element-web#22748. Contributed by @luixxiul.
* Support for v2 of MSC3903 ([\#10165](https://github.com/matrix-org/matrix-react-sdk/pull/10165)). Contributed by @hughns.
* When starting a DM, existing rooms with pending third-party invites will be reused. ([\#10256](https://github.com/matrix-org/matrix-react-sdk/pull/10256)). Fixes vector-im/element-web#23139.
* Polls push rules: synchronise poll rules with message rules ([\#10263](https://github.com/matrix-org/matrix-react-sdk/pull/10263)). Contributed by @kerryarchibald.
* New verification request toast button labels ([\#10259](https://github.com/matrix-org/matrix-react-sdk/pull/10259)).
* Remove padding around integration manager iframe ([\#10148](https://github.com/matrix-org/matrix-react-sdk/pull/10148)).
* Fix block code styling in rich text editor ([\#10246](https://github.com/matrix-org/matrix-react-sdk/pull/10246)). Contributed by @alunturner.
* Poll history: fetch more poll history ([\#10235](https://github.com/matrix-org/matrix-react-sdk/pull/10235)). Contributed by @kerryarchibald.
* Sort short/exact emoji matches before longer incomplete matches ([\#10212](https://github.com/matrix-org/matrix-react-sdk/pull/10212)). Fixes vector-im/element-web#23210. Contributed by @grimhilt.
* Poll history: detail screen ([\#10172](https://github.com/matrix-org/matrix-react-sdk/pull/10172)). Contributed by @kerryarchibald.
* Provide a more detailed error message than "No known servers" ([\#6048](https://github.com/matrix-org/matrix-react-sdk/pull/6048)). Fixes vector-im/element-web#13247. Contributed by @aaronraimist.
* Say when a call was answered from a different device ([\#10224](https://github.com/matrix-org/matrix-react-sdk/pull/10224)).
* Widget permissions customizations using module api ([\#10121](https://github.com/matrix-org/matrix-react-sdk/pull/10121)). Contributed by @maheichyk.
* Fix copy button icon overlapping with copyable text ([\#10227](https://github.com/matrix-org/matrix-react-sdk/pull/10227)). Contributed by @Adesh-Pandey.
* Support joining non-peekable rooms via the module API ([\#10154](https://github.com/matrix-org/matrix-react-sdk/pull/10154)). Contributed by @maheichyk.
* The "new login" toast does now display the same device information as in the settings. "No" does now open the device settings. "Yes, it was me" dismisses the toast. ([\#10200](https://github.com/matrix-org/matrix-react-sdk/pull/10200)).
* Do not prompt for a password when doing a „reset all“ after login ([\#10208](https://github.com/matrix-org/matrix-react-sdk/pull/10208)).
## 🐛 Bug Fixes
* Fix macOS notarisation using keychain credentials ([\#557](https://github.com/vector-im/element-desktop/pull/557)).
* Let electron-builder correctly set StartupWMClass ([\#526](https://github.com/vector-im/element-desktop/pull/526)). Fixes vector-im/element-web#13780.
* Fix incorrect copy in space creation flow ([\#10296](https://github.com/matrix-org/matrix-react-sdk/pull/10296)). Fixes vector-im/element-web#24741.
* Fix space settings dialog having rogue title tooltip ([\#10293](https://github.com/matrix-org/matrix-react-sdk/pull/10293)). Fixes vector-im/element-web#24740.
* Show spinner when starting a DM from the user profile (right panel) ([\#10290](https://github.com/matrix-org/matrix-react-sdk/pull/10290)).
* Reduce height of toggle on expanded view source event ([\#10283](https://github.com/matrix-org/matrix-react-sdk/pull/10283)). Fixes vector-im/element-web#22873. Contributed by @luixxiul.
* Pillify http and non-prefixed matrix.to links ([\#10277](https://github.com/matrix-org/matrix-react-sdk/pull/10277)). Fixes vector-im/element-web#20844.
* Fix some features not being configurable via `features` ([\#10276](https://github.com/matrix-org/matrix-react-sdk/pull/10276)).
* Fix starting a DM from the right panel in some cases ([\#10278](https://github.com/matrix-org/matrix-react-sdk/pull/10278)). Fixes vector-im/element-web#24722.
* Align info EventTile and normal EventTile on IRC layout ([\#10197](https://github.com/matrix-org/matrix-react-sdk/pull/10197)). Fixes vector-im/element-web#22782. Contributed by @luixxiul.
* Fix blowout of waveform of the voice message player on narrow UI ([\#8861](https://github.com/matrix-org/matrix-react-sdk/pull/8861)). Fixes vector-im/element-web#22604. Contributed by @luixxiul.
* Fix the hidden view source toggle on IRC layout ([\#10266](https://github.com/matrix-org/matrix-react-sdk/pull/10266)). Fixes vector-im/element-web#22872. Contributed by @luixxiul.
* Fix buttons on the room header being compressed due to long room name ([\#10155](https://github.com/matrix-org/matrix-react-sdk/pull/10155)). Contributed by @luixxiul.
* Use the room avatar as a placeholder in calls ([\#10231](https://github.com/matrix-org/matrix-react-sdk/pull/10231)).
* Fix calls showing as 'connecting' after hangup ([\#10223](https://github.com/matrix-org/matrix-react-sdk/pull/10223)).
* Prevent multiple Jitsi calls started at the same time ([\#10183](https://github.com/matrix-org/matrix-react-sdk/pull/10183)). Fixes vector-im/element-web#23009.
* Make localization keys compatible with agglutinative and/or SOV type languages ([\#10159](https://github.com/matrix-org/matrix-react-sdk/pull/10159)). Contributed by @luixxiul.
Changes in [1.11.24](https://github.com/vector-im/element-desktop/releases/tag/v1.11.24) (2023-02-28)
=====================================================================================================
## ✨ Features
* Display "The sender has blocked you from receiving this message" error message instead of "Unable to decrypt message" ([\#10202](https://github.com/matrix-org/matrix-react-sdk/pull/10202)). Contributed by @florianduros.
* Polls: show warning about undecryptable relations ([\#10179](https://github.com/matrix-org/matrix-react-sdk/pull/10179)). Contributed by @kerryarchibald.
* Poll history: fetch last 30 days of polls ([\#10157](https://github.com/matrix-org/matrix-react-sdk/pull/10157)). Contributed by @kerryarchibald.
* Poll history - ended polls list items ([\#10119](https://github.com/matrix-org/matrix-react-sdk/pull/10119)). Contributed by @kerryarchibald.
* Remove threads labs flag and the ability to disable threads ([\#9878](https://github.com/matrix-org/matrix-react-sdk/pull/9878)). Fixes vector-im/element-web#24365.
* Show a success dialog after setting up the key backup ([\#10177](https://github.com/matrix-org/matrix-react-sdk/pull/10177)). Fixes vector-im/element-web#24487.
* Release Sign in with QR out of labs ([\#10182](https://github.com/matrix-org/matrix-react-sdk/pull/10182)). Contributed by @hughns.
* Release Sign in with QR out of labs ([\#10066](https://github.com/matrix-org/matrix-react-sdk/pull/10066)). Contributed by @hughns.
* Hide indent button in rte ([\#10149](https://github.com/matrix-org/matrix-react-sdk/pull/10149)). Contributed by @alunturner.
* Add option to find own location in map views ([\#10083](https://github.com/matrix-org/matrix-react-sdk/pull/10083)).
* Render poll end events in timeline ([\#10027](https://github.com/matrix-org/matrix-react-sdk/pull/10027)). Contributed by @kerryarchibald.
## 🐛 Bug Fixes
* Stop access token overflowing the box ([\#10069](https://github.com/matrix-org/matrix-react-sdk/pull/10069)). Fixes vector-im/element-web#24023. Contributed by @sbjaj33.
* Add link to next file in the export ([\#10190](https://github.com/matrix-org/matrix-react-sdk/pull/10190)). Fixes vector-im/element-web#20272. Contributed by @grimhilt.
* Ended poll tiles: add ended the poll message ([\#10193](https://github.com/matrix-org/matrix-react-sdk/pull/10193)). Fixes vector-im/element-web#24579. Contributed by @kerryarchibald.
* Fix accidentally inverted condition for room ordering ([\#10178](https://github.com/matrix-org/matrix-react-sdk/pull/10178)). Fixes vector-im/element-web#24527. Contributed by @justjanne.
* Re-focus the composer on dialogue quit ([\#10007](https://github.com/matrix-org/matrix-react-sdk/pull/10007)). Fixes vector-im/element-web#22832. Contributed by @Ashu999.
* Try to resolve emails before creating a DM ([\#10164](https://github.com/matrix-org/matrix-react-sdk/pull/10164)).
* Disable poll response loading test ([\#10168](https://github.com/matrix-org/matrix-react-sdk/pull/10168)). Contributed by @justjanne.
* Fix email lookup in invite dialog ([\#10150](https://github.com/matrix-org/matrix-react-sdk/pull/10150)). Fixes vector-im/element-web#23353.
* Remove duplicate white space characters from translation keys ([\#10152](https://github.com/matrix-org/matrix-react-sdk/pull/10152)). Contributed by @luixxiul.
* Fix the caption of new sessions manager on Labs settings page for localization ([\#10143](https://github.com/matrix-org/matrix-react-sdk/pull/10143)). Contributed by @luixxiul.
* Prevent start another DM with a user if one already exists ([\#10127](https://github.com/matrix-org/matrix-react-sdk/pull/10127)). Fixes vector-im/element-web#23138.
* Remove white space characters before the horizontal ellipsis ([\#10130](https://github.com/matrix-org/matrix-react-sdk/pull/10130)). Contributed by @luixxiul.
* Fix Selectable Text on 'Delete All' and 'Retry All' Buttons ([\#10128](https://github.com/matrix-org/matrix-react-sdk/pull/10128)). Fixes vector-im/element-web#23232. Contributed by @akshattchhabra.
* Correctly Identify emoticons ([\#10108](https://github.com/matrix-org/matrix-react-sdk/pull/10108)). Fixes vector-im/element-web#19472. Contributed by @adarsh-sgh.
* Remove a redundant white space ([\#10129](https://github.com/matrix-org/matrix-react-sdk/pull/10129)). Contributed by @luixxiul.
Changes in [1.11.23](https://github.com/vector-im/element-desktop/releases/tag/v1.11.23) (2023-02-14)
=====================================================================================================
## ✨ Features
* Description of QR code sign in labs feature ([\#23513](https://github.com/vector-im/element-web/pull/23513)). Contributed by @hughns.
* Add option to find own location in map views ([\#10083](https://github.com/matrix-org/matrix-react-sdk/pull/10083)).
* Render poll end events in timeline ([\#10027](https://github.com/matrix-org/matrix-react-sdk/pull/10027)). Contributed by @kerryarchibald.
* Indicate unread messages in tab title ([\#10096](https://github.com/matrix-org/matrix-react-sdk/pull/10096)). Contributed by @tnt7864.
* Open message in editing mode when keyboard up is pressed (RTE) ([\#10079](https://github.com/matrix-org/matrix-react-sdk/pull/10079)). Contributed by @florianduros.
* Hide superseded rooms from the room list using dynamic room predecessors ([\#10068](https://github.com/matrix-org/matrix-react-sdk/pull/10068)). Contributed by @andybalaam.
* Support MSC3946 in RoomListStore ([\#10054](https://github.com/matrix-org/matrix-react-sdk/pull/10054)). Fixes vector-im/element-web#24325. Contributed by @andybalaam.
* Auto focus security key field ([\#10048](https://github.com/matrix-org/matrix-react-sdk/pull/10048)).
* use Poll model with relations API in poll rendering ([\#9877](https://github.com/matrix-org/matrix-react-sdk/pull/9877)). Contributed by @kerryarchibald.
* Support MSC3946 in the RoomCreate tile ([\#10041](https://github.com/matrix-org/matrix-react-sdk/pull/10041)). Fixes vector-im/element-web#24323. Contributed by @andybalaam.
* Update labs flag description for RTE ([\#10058](https://github.com/matrix-org/matrix-react-sdk/pull/10058)). Contributed by @florianduros.
* Change ul list style to disc when editing message ([\#10043](https://github.com/matrix-org/matrix-react-sdk/pull/10043)). Contributed by @alunturner.
* Improved click detection within PiP windows ([\#10040](https://github.com/matrix-org/matrix-react-sdk/pull/10040)). Fixes vector-im/element-web#24371.
* Add RTE keyboard navigation in editing ([\#9980](https://github.com/matrix-org/matrix-react-sdk/pull/9980)). Fixes vector-im/element-web#23621. Contributed by @florianduros.
* Paragraph integration for rich text editor ([\#10008](https://github.com/matrix-org/matrix-react-sdk/pull/10008)). Contributed by @alunturner.
* Add indentation increasing/decreasing to RTE ([\#10034](https://github.com/matrix-org/matrix-react-sdk/pull/10034)). Contributed by @florianduros.
* Add ignore user confirmation dialog ([\#6116](https://github.com/matrix-org/matrix-react-sdk/pull/6116)). Fixes vector-im/element-web#14746.
* Use monospace font for room, message IDs in View Source modal ([\#9956](https://github.com/matrix-org/matrix-react-sdk/pull/9956)). Fixes vector-im/element-web#21937. Contributed by @paragpoddar.
* Implement MSC3946 for AdvancedRoomSettingsTab ([\#9995](https://github.com/matrix-org/matrix-react-sdk/pull/9995)). Fixes vector-im/element-web#24322. Contributed by @andybalaam.
* Implementation of MSC3824 to make the client OIDC-aware ([\#8681](https://github.com/matrix-org/matrix-react-sdk/pull/8681)). Contributed by @hughns.
* Improves a11y for avatar uploads ([\#9985](https://github.com/matrix-org/matrix-react-sdk/pull/9985)). Contributed by @GoodGuyMarco.
* Add support for [token authenticated registration](https ([\#7275](https://github.com/matrix-org/matrix-react-sdk/pull/7275)). Fixes vector-im/element-web#18931. Contributed by @govynnus.
## 🐛 Bug Fixes
* Update to Electron 22.2.0 - fix tray icons in Linux ([\#530](https://github.com/vector-im/element-desktop/pull/530)). Fixes vector-im/element-web#23993.
* Jitsi requests 'requires_client' capability if auth token is provided ([\#24294](https://github.com/vector-im/element-web/pull/24294)). Contributed by @maheichyk.
* Remove duplicate white space characters from translation keys ([\#10152](https://github.com/matrix-org/matrix-react-sdk/pull/10152)). Contributed by @luixxiul.
* Fix the caption of new sessions manager on Labs settings page for localization ([\#10143](https://github.com/matrix-org/matrix-react-sdk/pull/10143)). Contributed by @luixxiul.
* Prevent start another DM with a user if one already exists ([\#10127](https://github.com/matrix-org/matrix-react-sdk/pull/10127)). Fixes vector-im/element-web#23138.
* Remove white space characters before the horizontal ellipsis ([\#10130](https://github.com/matrix-org/matrix-react-sdk/pull/10130)). Contributed by @luixxiul.
* Fix Selectable Text on 'Delete All' and 'Retry All' Buttons ([\#10128](https://github.com/matrix-org/matrix-react-sdk/pull/10128)). Fixes vector-im/element-web#23232. Contributed by @akshattchhabra.
* Correctly Identify emoticons ([\#10108](https://github.com/matrix-org/matrix-react-sdk/pull/10108)). Fixes vector-im/element-web#19472. Contributed by @adarsh-sgh.
* Should open new 1:1 chat room after leaving the old one ([\#9880](https://github.com/matrix-org/matrix-react-sdk/pull/9880)). Contributed by @ahmadkadri.
* Remove a redundant white space ([\#10129](https://github.com/matrix-org/matrix-react-sdk/pull/10129)). Contributed by @luixxiul.
* Fix a crash when removing persistent widgets (updated) ([\#10099](https://github.com/matrix-org/matrix-react-sdk/pull/10099)). Fixes vector-im/element-web#24412. Contributed by @andybalaam.
* Fix wrongly grouping 3pid invites into a single repeated transition ([\#10087](https://github.com/matrix-org/matrix-react-sdk/pull/10087)). Fixes vector-im/element-web#24432.
* Fix scrollbar colliding with checkbox in add to space section ([\#10093](https://github.com/matrix-org/matrix-react-sdk/pull/10093)). Fixes vector-im/element-web#23189. Contributed by @Arnabdaz.
* Add a whitespace character after 'broadcast?' ([\#10097](https://github.com/matrix-org/matrix-react-sdk/pull/10097)). Contributed by @luixxiul.
* Seekbar in broadcast PiP view is now updated when switching between different broadcasts ([\#10072](https://github.com/matrix-org/matrix-react-sdk/pull/10072)). Fixes vector-im/element-web#24415.
* Add border to "reject" button on room preview card for clickable area indication. It fixes vector-im/element-web#22623 ([\#9205](https://github.com/matrix-org/matrix-react-sdk/pull/9205)). Contributed by @gefgu.
* Element-R: fix rageshages ([\#10081](https://github.com/matrix-org/matrix-react-sdk/pull/10081)). Fixes vector-im/element-web#24430.
* Fix markdown paragraph display in timeline ([\#10071](https://github.com/matrix-org/matrix-react-sdk/pull/10071)). Fixes vector-im/element-web#24419. Contributed by @alunturner.
* Prevent the remaining broadcast time from being exceeded ([\#10070](https://github.com/matrix-org/matrix-react-sdk/pull/10070)).
* Fix cursor position when new line is created by pressing enter (RTE) ([\#10064](https://github.com/matrix-org/matrix-react-sdk/pull/10064)). Contributed by @florianduros.
* Ensure room is actually in space hierarchy when resolving its latest version ([\#10010](https://github.com/matrix-org/matrix-react-sdk/pull/10010)).
* Fix new line for inline code ([\#10062](https://github.com/matrix-org/matrix-react-sdk/pull/10062)). Contributed by @florianduros.
* Member avatars without canvas ([\#9990](https://github.com/matrix-org/matrix-react-sdk/pull/9990)). Contributed by @clarkf.
* Apply more general fix for base avatar regressions ([\#10045](https://github.com/matrix-org/matrix-react-sdk/pull/10045)). Fixes vector-im/element-web#24382 and vector-im/element-web#24370.
* Replace list, code block and quote icons by new icons ([\#10035](https://github.com/matrix-org/matrix-react-sdk/pull/10035)). Contributed by @florianduros.
* fix regional emojis converted to flags ([\#9294](https://github.com/matrix-org/matrix-react-sdk/pull/9294)). Fixes vector-im/element-web#19000. Contributed by @grimhilt.
* resolved emoji description text overflowing issue ([\#10028](https://github.com/matrix-org/matrix-react-sdk/pull/10028)). Contributed by @fahadNoufal.
* Fix MessageEditHistoryDialog crashing on complex input ([\#10018](https://github.com/matrix-org/matrix-react-sdk/pull/10018)). Fixes vector-im/element-web#23665. Contributed by @clarkf.
* Unify unread notification state determination ([\#9941](https://github.com/matrix-org/matrix-react-sdk/pull/9941)). Contributed by @clarkf.
* Fix layout and visual regressions around default avatars ([\#10031](https://github.com/matrix-org/matrix-react-sdk/pull/10031)). Fixes vector-im/element-web#24375 and vector-im/element-web#24369.
* Fix useUnreadNotifications exploding with falsey room, like in notif panel ([\#10030](https://github.com/matrix-org/matrix-react-sdk/pull/10030)). Fixes matrix-org/element-web-rageshakes#19334.
* Fix "[object Promise]" appearing in HTML exports ([\#9975](https://github.com/matrix-org/matrix-react-sdk/pull/9975)). Fixes vector-im/element-web#24272. Contributed by @clarkf.
* changing the color of message time stamp ([\#10016](https://github.com/matrix-org/matrix-react-sdk/pull/10016)). Contributed by @nawarajshah.
* Fix link creation with backward selection ([\#9986](https://github.com/matrix-org/matrix-react-sdk/pull/9986)). Fixes vector-im/element-web#24315. Contributed by @florianduros.
* Misaligned reply preview in thread composer #23396 ([\#9977](https://github.com/matrix-org/matrix-react-sdk/pull/9977)). Fixes vector-im/element-web#23396. Contributed by @mustafa-kapadia1483.
Changes in [1.11.22](https://github.com/vector-im/element-desktop/releases/tag/v1.11.22) (2023-01-31)
=====================================================================================================
## 🐛 Bug Fixes
* Bump version number to fix problems upgrading from v1.11.21-rc.1
Changes in [1.11.21](https://github.com/vector-im/element-desktop/releases/tag/v1.11.21) (2023-01-31)
=====================================================================================================
## ✨ Features
* Move pin drop out of labs ([\#22993](https://github.com/vector-im/element-web/pull/22993)).
* Quotes for rte ([\#9932](https://github.com/matrix-org/matrix-react-sdk/pull/9932)). Contributed by @alunturner.
* Show the room name in the room header during calls ([\#9942](https://github.com/matrix-org/matrix-react-sdk/pull/9942)). Fixes vector-im/element-web#24268.
* Add code blocks to rich text editor ([\#9921](https://github.com/matrix-org/matrix-react-sdk/pull/9921)). Contributed by @alunturner.
* Add new style for inline code ([\#9936](https://github.com/matrix-org/matrix-react-sdk/pull/9936)). Contributed by @florianduros.
* Add disabled button state to rich text editor ([\#9930](https://github.com/matrix-org/matrix-react-sdk/pull/9930)). Contributed by @alunturner.
* Change the rageshake "app" for auto-rageshakes ([\#9909](https://github.com/matrix-org/matrix-react-sdk/pull/9909)).
* Device manager - tweak settings display ([\#9905](https://github.com/matrix-org/matrix-react-sdk/pull/9905)). Contributed by @kerryarchibald.
* Add list functionality to rich text editor ([\#9871](https://github.com/matrix-org/matrix-react-sdk/pull/9871)). Contributed by @alunturner.
## 🐛 Bug Fixes
* Fix RTE focus behaviour in threads ([\#9969](https://github.com/matrix-org/matrix-react-sdk/pull/9969)). Fixes vector-im/element-web#23755. Contributed by @florianduros.
* #22204 Issue: Centered File info in lightbox ([\#9971](https://github.com/matrix-org/matrix-react-sdk/pull/9971)). Fixes vector-im/element-web#22204. Contributed by @Spartan09.
* Fix seekbar position for zero length audio ([\#9949](https://github.com/matrix-org/matrix-react-sdk/pull/9949)). Fixes vector-im/element-web#24248.
* Allow thread panel to be closed after being opened from notification ([\#9937](https://github.com/matrix-org/matrix-react-sdk/pull/9937)). Fixes vector-im/element-web#23764 vector-im/element-web#23852 and vector-im/element-web#24213. Contributed by @justjanne.
* Only highlight focused menu item if focus is supposed to be visible ([\#9945](https://github.com/matrix-org/matrix-react-sdk/pull/9945)). Fixes vector-im/element-web#23582.
* Prevent call durations from breaking onto multiple lines ([\#9944](https://github.com/matrix-org/matrix-react-sdk/pull/9944)).
* Tweak call lobby buttons to more closely match designs ([\#9943](https://github.com/matrix-org/matrix-react-sdk/pull/9943)).
* Do not show a broadcast as live immediately after the recording has stopped ([\#9947](https://github.com/matrix-org/matrix-react-sdk/pull/9947)). Fixes vector-im/element-web#24233.
* Clear the RTE before sending a message ([\#9948](https://github.com/matrix-org/matrix-react-sdk/pull/9948)). Contributed by @florianduros.
* Fix {enter} press in RTE ([\#9927](https://github.com/matrix-org/matrix-react-sdk/pull/9927)). Contributed by @florianduros.
* Fix the problem that the password reset email has to be confirmed twice ([\#9926](https://github.com/matrix-org/matrix-react-sdk/pull/9926)). Fixes vector-im/element-web#24226.
* replace .at() with array.length-1 ([\#9933](https://github.com/matrix-org/matrix-react-sdk/pull/9933)). Fixes matrix-org/element-web-rageshakes#19281.
* Fix broken threads list timestamp layout ([\#9922](https://github.com/matrix-org/matrix-react-sdk/pull/9922)). Fixes vector-im/element-web#24243 and vector-im/element-web#24191. Contributed by @justjanne.
* Disable multiple messages when {enter} is pressed multiple times ([\#9929](https://github.com/matrix-org/matrix-react-sdk/pull/9929)). Fixes vector-im/element-web#24249. Contributed by @florianduros.
* Fix logout devices when resetting the password ([\#9925](https://github.com/matrix-org/matrix-react-sdk/pull/9925)). Fixes vector-im/element-web#24228.
* Fix: Poll replies overflow when not enough space ([\#9924](https://github.com/matrix-org/matrix-react-sdk/pull/9924)). Fixes vector-im/element-web#24227. Contributed by @kerryarchibald.
* State event updates are not forwarded to the widget from invitation room ([\#9802](https://github.com/matrix-org/matrix-react-sdk/pull/9802)). Contributed by @maheichyk.
* Fix error when viewing source of redacted events ([\#9914](https://github.com/matrix-org/matrix-react-sdk/pull/9914)). Fixes vector-im/element-web#24165. Contributed by @clarkf.
* Replace outdated css attribute ([\#9912](https://github.com/matrix-org/matrix-react-sdk/pull/9912)). Fixes vector-im/element-web#24218. Contributed by @justjanne.
* Clear isLogin theme override when user is no longer viewing login screens ([\#9911](https://github.com/matrix-org/matrix-react-sdk/pull/9911)). Fixes vector-im/element-web#23893.
* Fix reply action in message context menu notif & file panels ([\#9895](https://github.com/matrix-org/matrix-react-sdk/pull/9895)). Fixes vector-im/element-web#23970.
* Fix issue where thread dropdown would not show up correctly ([\#9872](https://github.com/matrix-org/matrix-react-sdk/pull/9872)). Fixes vector-im/element-web#24040. Contributed by @justjanne.
* Fix unexpected composer growing ([\#9889](https://github.com/matrix-org/matrix-react-sdk/pull/9889)). Contributed by @florianduros.
* Fix misaligned timestamps for thread roots which are emotes ([\#9875](https://github.com/matrix-org/matrix-react-sdk/pull/9875)). Fixes vector-im/element-web#23897. Contributed by @justjanne.
Changes in [1.11.20](https://github.com/vector-im/element-desktop/releases/tag/v1.11.20) (2023-01-20)
=====================================================================================================
## 🐛 Bug Fixes
* (no effect on Element Desktop) (Part 2) fix crash on browsers that don't support `Array.at`
Changes in [1.11.19](https://github.com/vector-im/element-desktop/releases/tag/v1.11.19) (2023-01-20)
=====================================================================================================
## 🐛 Bug Fixes
* (no effect on Element Desktop) Fix crash on browsers that don't support `Array.at` ([\#9935](https://github.com/matrix-org/matrix-react-sdk/pull/9935)). Contributed by @andybalaam.
Changes in [1.11.18](https://github.com/vector-im/element-desktop/releases/tag/v1.11.18) (2023-01-18)
=====================================================================================================
## ✨ Features
* Switch threads on for everyone ([\#9879](https://github.com/matrix-org/matrix-react-sdk/pull/9879)).
* Make threads use new Unable to Decrypt UI ([\#9876](https://github.com/matrix-org/matrix-react-sdk/pull/9876)). Fixes vector-im/element-web#24060.
* Add edit and remove actions to link in RTE ([\#9864](https://github.com/matrix-org/matrix-react-sdk/pull/9864)).
* Remove extensible events v1 experimental rendering ([\#9881](https://github.com/matrix-org/matrix-react-sdk/pull/9881)).
* Make create poll dialog scale better (PSG-929) ([\#9873](https://github.com/matrix-org/matrix-react-sdk/pull/9873)). Fixes vector-im/element-web#21855.
* Change RTE mode icons ([\#9861](https://github.com/matrix-org/matrix-react-sdk/pull/9861)).
* Device manager - prune client information events after remote sign out ([\#9874](https://github.com/matrix-org/matrix-react-sdk/pull/9874)).
* Check connection before starting broadcast ([\#9857](https://github.com/matrix-org/matrix-react-sdk/pull/9857)).
* Enable sent receipt for poll start events (PSG-962) ([\#9870](https://github.com/matrix-org/matrix-react-sdk/pull/9870)).
* Change clear notifications to have more readable copy ([\#9867](https://github.com/matrix-org/matrix-react-sdk/pull/9867)).
* Combine search results when the query is present in multiple successive messages ([\#9855](https://github.com/matrix-org/matrix-react-sdk/pull/9855)). Fixes vector-im/element-web#3977. Contributed by @grimhilt.
* Disable bubbles for broadcasts ([\#9860](https://github.com/matrix-org/matrix-react-sdk/pull/9860)). Fixes vector-im/element-web#24140.
* Enable reactions and replies for broadcasts ([\#9856](https://github.com/matrix-org/matrix-react-sdk/pull/9856)). Fixes vector-im/element-web#24042.
* Improve switching between rich and plain editing modes ([\#9776](https://github.com/matrix-org/matrix-react-sdk/pull/9776)).
* Redesign the picture-in-picture window ([\#9800](https://github.com/matrix-org/matrix-react-sdk/pull/9800)). Fixes vector-im/element-web#23980.
* User on-boarding tasks now appear in a static order. ([\#9799](https://github.com/matrix-org/matrix-react-sdk/pull/9799)). Contributed by @GoodGuyMarco.
* Device manager - contextual menus ([\#9832](https://github.com/matrix-org/matrix-react-sdk/pull/9832)).
* If listening a non-live broadcast and changing the room, the broadcast will be paused ([\#9825](https://github.com/matrix-org/matrix-react-sdk/pull/9825)). Fixes vector-im/element-web#24078.
* Consider own broadcasts from other device as a playback ([\#9821](https://github.com/matrix-org/matrix-react-sdk/pull/9821)). Fixes vector-im/element-web#24068.
* Add link creation to rich text editor ([\#9775](https://github.com/matrix-org/matrix-react-sdk/pull/9775)).
* Add mark as read option in room setting ([\#9798](https://github.com/matrix-org/matrix-react-sdk/pull/9798)). Fixes vector-im/element-web#24053.
* Device manager - current device design and copy tweaks ([\#9801](https://github.com/matrix-org/matrix-react-sdk/pull/9801)).
* Unify notifications panel event design ([\#9754](https://github.com/matrix-org/matrix-react-sdk/pull/9754)).
* Add actions for integration manager to send and read certain events ([\#9740](https://github.com/matrix-org/matrix-react-sdk/pull/9740)).
* Device manager - design tweaks ([\#9768](https://github.com/matrix-org/matrix-react-sdk/pull/9768)).
* Change room list sorting to activity and unread first by default ([\#9773](https://github.com/matrix-org/matrix-react-sdk/pull/9773)). Fixes vector-im/element-web#24014.
* Add a config flag to enable the rust crypto-sdk ([\#9759](https://github.com/matrix-org/matrix-react-sdk/pull/9759)).
* Improve decryption error UI by consolidating error messages and providing instructions when possible ([\#9544](https://github.com/matrix-org/matrix-react-sdk/pull/9544)). Contributed by @duxovni.
* Honor font settings in Element Call ([\#9751](https://github.com/matrix-org/matrix-react-sdk/pull/9751)). Fixes vector-im/element-web#23661.
* Device manager - use deleteAccountData to prune device manager client information events ([\#9734](https://github.com/matrix-org/matrix-react-sdk/pull/9734)).
## 🐛 Bug Fixes
* Display rooms & threads as unread (bold) if threads have unread messages. ([\#9763](https://github.com/matrix-org/matrix-react-sdk/pull/9763)). Fixes vector-im/element-web#23907.
* Don't prefer STIXGeneral over the default font ([\#9711](https://github.com/matrix-org/matrix-react-sdk/pull/9711)). Fixes vector-im/element-web#23899.
* Use the same avatar colour when creating 1:1 DM rooms ([\#9850](https://github.com/matrix-org/matrix-react-sdk/pull/9850)). Fixes vector-im/element-web#23476.
* Fix space lock icon size ([\#9854](https://github.com/matrix-org/matrix-react-sdk/pull/9854)). Fixes vector-im/element-web#24128.
* Make calls automatically disconnect if the widget disappears ([\#9862](https://github.com/matrix-org/matrix-react-sdk/pull/9862)). Fixes vector-im/element-web#23664.
* Fix emoji in RTE editing ([\#9827](https://github.com/matrix-org/matrix-react-sdk/pull/9827)).
* Fix export with attachments on formats txt and json ([\#9851](https://github.com/matrix-org/matrix-react-sdk/pull/9851)). Fixes vector-im/element-web#24130. Contributed by @grimhilt.
* Fixed empty `Content-Type` for encrypted uploads ([\#9848](https://github.com/matrix-org/matrix-react-sdk/pull/9848)). Contributed by @K3das.
* Fix sign-in instead link on password reset page ([\#9820](https://github.com/matrix-org/matrix-react-sdk/pull/9820)). Fixes vector-im/element-web#24087.
* The seekbar now initially shows the current position ([\#9796](https://github.com/matrix-org/matrix-react-sdk/pull/9796)). Fixes vector-im/element-web#24051.
* Fix: Editing a poll will silently change it to a closed poll ([\#9809](https://github.com/matrix-org/matrix-react-sdk/pull/9809)). Fixes vector-im/element-web#23176.
* Make call tiles look less broken in the right panel ([\#9808](https://github.com/matrix-org/matrix-react-sdk/pull/9808)). Fixes vector-im/element-web#23716.
* Prevent unnecessary m.direct updates ([\#9805](https://github.com/matrix-org/matrix-react-sdk/pull/9805)). Fixes vector-im/element-web#24059.
* Fix checkForPreJoinUISI for thread roots ([\#9803](https://github.com/matrix-org/matrix-react-sdk/pull/9803)). Fixes vector-im/element-web#24054.
* Snap in PiP widget when content changed ([\#9797](https://github.com/matrix-org/matrix-react-sdk/pull/9797)). Fixes vector-im/element-web#24050.
* Load RTE components only when RTE labs is enabled ([\#9804](https://github.com/matrix-org/matrix-react-sdk/pull/9804)).
* Ensure that events are correctly updated when they are edited. ([\#9789](https://github.com/matrix-org/matrix-react-sdk/pull/9789)).
* When stopping a broadcast also stop the playback ([\#9795](https://github.com/matrix-org/matrix-react-sdk/pull/9795)). Fixes vector-im/element-web#24052.
* Prevent to start two broadcasts at the same time ([\#9744](https://github.com/matrix-org/matrix-react-sdk/pull/9744)). Fixes vector-im/element-web#23973.
* Correctly handle limited sync responses by resetting the thread timeline ([\#3056](https://github.com/matrix-org/matrix-js-sdk/pull/3056)). Fixes vector-im/element-web#23952.
* Fix failure to start in firefox private browser ([\#3058](https://github.com/matrix-org/matrix-js-sdk/pull/3058)). Fixes vector-im/element-web#24216.
Changes in [1.11.17](https://github.com/vector-im/element-desktop/releases/tag/v1.11.17) (2022-12-21)
=====================================================================================================
## 🚨 BREAKING CHANGES
* This allows the update server to be entirely static, such as a CDN or object store, as defined at https ([\#461](https://github.com/vector-im/element-desktop/pull/461)).
## ✨ Features
* Enable threads by default ([\#9736](https://github.com/matrix-org/matrix-react-sdk/pull/9736)). Fixes vector-im/element-web#19270 vector-im/element-web#21910 and vector-im/element-web#23946.
* Add inline code formatting to rich text editor ([\#9720](https://github.com/matrix-org/matrix-react-sdk/pull/9720)).
* Add emoji handling for plain text mode of the new rich text editor ([\#9727](https://github.com/matrix-org/matrix-react-sdk/pull/9727)).
* Overlay virtual room call events into main timeline ([\#9626](https://github.com/matrix-org/matrix-react-sdk/pull/9626)). Fixes vector-im/element-web#22929.
* Adds a new section under "Room Settings" > "Roles & Permissions" which adds the possibility to multiselect users from this room and grant them more permissions. ([\#9596](https://github.com/matrix-org/matrix-react-sdk/pull/9596)). Contributed by @GoodGuyMarco.
* Add emoji handling for rich text mode ([\#9661](https://github.com/matrix-org/matrix-react-sdk/pull/9661)).
* Add setting to hide bold notifications ([\#9705](https://github.com/matrix-org/matrix-react-sdk/pull/9705)).
* Further password reset flow enhancements ([\#9662](https://github.com/matrix-org/matrix-react-sdk/pull/9662)).
* Snooze the bulk unverified sessions reminder on dismiss ([\#9706](https://github.com/matrix-org/matrix-react-sdk/pull/9706)).
* Honor advanced audio processing settings when recording voice messages ([\#9610](https://github.com/matrix-org/matrix-react-sdk/pull/9610)). Contributed by @MrAnno.
* Improve the visual balance of bubble layout ([\#9704](https://github.com/matrix-org/matrix-react-sdk/pull/9704)).
* Add config setting to disable bulk unverified sessions nag ([\#9657](https://github.com/matrix-org/matrix-react-sdk/pull/9657)).
* Only display bulk unverified sessions nag when current sessions is verified ([\#9656](https://github.com/matrix-org/matrix-react-sdk/pull/9656)).
* Separate labs and betas more clearly ([\#8969](https://github.com/matrix-org/matrix-react-sdk/pull/8969)). Fixes vector-im/element-web#22706.
* Show user an error if we fail to create a DM for verification. ([\#9624](https://github.com/matrix-org/matrix-react-sdk/pull/9624)).
## 🐛 Bug Fixes
* Prevent unnecessary m.direct updates ([\#9805](https://github.com/matrix-org/matrix-react-sdk/pull/9805)). Fixes vector-im/element-web#24059.
* Fix checkForPreJoinUISI for thread roots ([\#9803](https://github.com/matrix-org/matrix-react-sdk/pull/9803)). Fixes vector-im/element-web#24054.
* Load RTE components only when RTE labs is enabled ([\#9804](https://github.com/matrix-org/matrix-react-sdk/pull/9804)).
* Fix issue where thread panel did not update correctly ([\#9746](https://github.com/matrix-org/matrix-react-sdk/pull/9746)). Fixes vector-im/element-web#23971.
* Remove async call to get virtual room from room load ([\#9743](https://github.com/matrix-org/matrix-react-sdk/pull/9743)). Fixes vector-im/element-web#23968.
* Check each thread for unread messages. ([\#9723](https://github.com/matrix-org/matrix-react-sdk/pull/9723)).
* Device manage - handle sessions that don't support encryption ([\#9717](https://github.com/matrix-org/matrix-react-sdk/pull/9717)). Fixes vector-im/element-web#23722.
* Fix hover state for formatting buttons (Rich text editor) (fix vector-im/element-web/issues/23832) ([\#9715](https://github.com/matrix-org/matrix-react-sdk/pull/9715)).
* Don't allow group calls to be unterminated ([\#9710](https://github.com/matrix-org/matrix-react-sdk/pull/9710)).
* Fix replies to emotes not showing as inline ([\#9707](https://github.com/matrix-org/matrix-react-sdk/pull/9707)). Fixes vector-im/element-web#23903.
* Update copy of 'Change layout' button to match Element Call ([\#9703](https://github.com/matrix-org/matrix-react-sdk/pull/9703)).
* Fix call splitbrains when switching between rooms ([\#9692](https://github.com/matrix-org/matrix-react-sdk/pull/9692)).
* bugfix: fix an issue where the Notifier would incorrectly fire for non-timeline events ([\#9664](https://github.com/matrix-org/matrix-react-sdk/pull/9664)). Fixes vector-im/element-web#17263.
* Fix power selector being wrongly disabled for admins themselves ([\#9681](https://github.com/matrix-org/matrix-react-sdk/pull/9681)). Fixes vector-im/element-web#23882.
* Show day counts in call durations ([\#9641](https://github.com/matrix-org/matrix-react-sdk/pull/9641)).
Changes in [1.11.16](https://github.com/vector-im/element-desktop/releases/tag/v1.11.16) (2022-12-06)
=====================================================================================================
## ✨ Features
* Update to Electron 21 ([\#458](https://github.com/vector-im/element-desktop/pull/458)). Fixes vector-im/element-web#23783.
* Further improve replies ([\#6396](https://github.com/matrix-org/matrix-react-sdk/pull/6396)). Fixes vector-im/element-web#19074, vector-im/element-web#18194 vector-im/element-web#18027 and vector-im/element-web#19179.
* Enable users to join group calls from multiple devices ([\#9625](https://github.com/matrix-org/matrix-react-sdk/pull/9625)).
* fix(visual): make cursor a pointer for summaries ([\#9419](https://github.com/matrix-org/matrix-react-sdk/pull/9419)). Contributed by @r00ster91.
* Add placeholder for rich text editor ([\#9613](https://github.com/matrix-org/matrix-react-sdk/pull/9613)).
* Consolidate public room search experience ([\#9605](https://github.com/matrix-org/matrix-react-sdk/pull/9605)). Fixes vector-im/element-web#22846.
* New password reset flow ([\#9581](https://github.com/matrix-org/matrix-react-sdk/pull/9581)). Fixes vector-im/element-web#23131.
* Device manager - add tooltip to device details toggle ([\#9594](https://github.com/matrix-org/matrix-react-sdk/pull/9594)).
* sliding sync: add lazy-loading member support ([\#9530](https://github.com/matrix-org/matrix-react-sdk/pull/9530)).
* Limit formatting bar offset to top of composer ([\#9365](https://github.com/matrix-org/matrix-react-sdk/pull/9365)). Fixes vector-im/element-web#12359. Contributed by @owi92.
## 🐛 Bug Fixes
* Fix issues around up arrow event edit shortcut ([\#9645](https://github.com/matrix-org/matrix-react-sdk/pull/9645)). Fixes vector-im/element-web#18497 and vector-im/element-web#18964.
* Fix search not being cleared when clicking on a result ([\#9635](https://github.com/matrix-org/matrix-react-sdk/pull/9635)). Fixes vector-im/element-web#23845.
* Fix screensharing in 1:1 calls ([\#9612](https://github.com/matrix-org/matrix-react-sdk/pull/9612)). Fixes vector-im/element-web#23808.
* Fix the background color flashing when joining a call ([\#9640](https://github.com/matrix-org/matrix-react-sdk/pull/9640)).
* Fix the size of the 'Private space' icon ([\#9638](https://github.com/matrix-org/matrix-react-sdk/pull/9638)).
* Fix reply editing in rich text editor (https ([\#9615](https://github.com/matrix-org/matrix-react-sdk/pull/9615)).
* Fix thread list jumping back down while scrolling ([\#9606](https://github.com/matrix-org/matrix-react-sdk/pull/9606)). Fixes vector-im/element-web#23727.
* Fix regression with TimelinePanel props updates not taking effect ([\#9608](https://github.com/matrix-org/matrix-react-sdk/pull/9608)). Fixes vector-im/element-web#23794.
* Fix form tooltip positioning ([\#9598](https://github.com/matrix-org/matrix-react-sdk/pull/9598)). Fixes vector-im/element-web#22861.
* Extract Search handling from RoomView into its own Component ([\#9574](https://github.com/matrix-org/matrix-react-sdk/pull/9574)). Fixes vector-im/element-web#498.
* Fix call splitbrains when switching between rooms ([\#9692](https://github.com/matrix-org/matrix-react-sdk/pull/9692)).
Changes in [1.11.15](https://github.com/vector-im/element-desktop/releases/tag/v1.11.15) (2022-11-22)
=====================================================================================================

View File

@@ -5,21 +5,20 @@
[![Vulnerabilities](https://sonarcloud.io/api/project_badges/measure?project=element-desktop&metric=vulnerabilities)](https://sonarcloud.io/summary/new_code?id=element-desktop)
[![Bugs](https://sonarcloud.io/api/project_badges/measure?project=element-desktop&metric=bugs)](https://sonarcloud.io/summary/new_code?id=element-desktop)
Element Desktop
===============
# Element Desktop
Element Desktop is a Matrix client for desktop platforms with Element Web at its core.
First Steps
===========
# First Steps
Before you do anything else, fetch the dependencies:
```
yarn install
```
Fetching Element
================
# Fetching Element
Since this package is just the Electron wrapper for Element Web, it doesn't contain any of the Element Web code,
so the first step is to get a working copy of Element Web. There are a few ways of doing this:
@@ -31,6 +30,7 @@ yarn run fetch --noverify --cfgdir ""
```
...or if you'd like to use GPG to verify the downloaded package:
```
# Fetch the Element public key from the element.io web server over a secure connection and import
# it into your local GPG keychain (you'll need GPG installed). You only need to to do this
@@ -41,6 +41,7 @@ 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.
@@ -49,6 +50,7 @@ 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
provide the `webapp` directory directly:
```
# Assuming you've checked out and built a copy of element-web in ../element-web
ln -s ../element-web/webapp ./
@@ -56,29 +58,32 @@ ln -s ../element-web/webapp ./
[TODO: add support for fetching develop builds, arbitrary URLs and arbitrary paths]
Building
========
# Building
## Native Build
TODO: List native pre-requisites
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.
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
```
This will do a couple of things:
* Run the `setversion` script to set the local package version to match whatever
version of Element you installed above.
* Run electron-builder to build a package. The package built will match the operating system
you're running the build process on.
- Run the `setversion` script to set the local package version to match whatever
version of Element you installed above.
- Run electron-builder to build a package. The package built will match the operating system
you're running the build process on.
## Docker
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
@@ -91,9 +96,10 @@ yarn run docker:build
After running, the packages should be in `dist/`.
Starting
========
# Starting
If you'd just like to run the electron app locally for development:
```
# Install electron - we don't normally need electron itself as it's provided
# by electron-builder when building packages
@@ -101,21 +107,22 @@ yarn add electron
yarn start
```
Config
======
# Config
If you'd like the packaged Element to have a configuration file, you can create a
config directory and place `config.json` in there, then specify this directory
with the `--cfgdir` option to `yarn run fetch`, eg:
```
mkdir myconfig
cp /path/to/my/config.json myconfig/
yarn run fetch --cfgdir myconfig
```
The config dir for the official Element app is in `element.io`. If you use this,
your app will auto-update itself using builds from element.io.
Profiles
========
# Profiles
To run multiple instances of the desktop app for different accounts, you can
launch the executable with the `--profile` argument followed by a unique
@@ -125,20 +132,18 @@ not interfere with the default one.
Alternatively, a custom location for the profile data can be specified using the
`--profile-dir` flag followed by the desired path.
User-specified config.json
==========================
# User-specified config.json
+ `%APPDATA%\$NAME\config.json` on Windows
+ `$XDG_CONFIG_HOME/$NAME/config.json` or `~/.config/$NAME/config.json` on Linux
+ `~/Library/Application Support/$NAME/config.json` on macOS
- `%APPDATA%\$NAME\config.json` on Windows
- `$XDG_CONFIG_HOME/$NAME/config.json` or `~/.config/$NAME/config.json` on Linux
- `~/Library/Application Support/$NAME/config.json` on macOS
In the paths above, `$NAME` is typically `Element`, unless you use `--profile
$PROFILE` in which case it becomes `Element-$PROFILE`, or it is using one of
the above created by a pre-1.7 install, in which case it will be `Riot` or
`Riot-$PROFILE`.
Translations
==========================
# Translations
To add a new translation, head to the [translating doc](https://github.com/vector-im/element-web/blob/develop/docs/translating.md).
@@ -146,9 +151,8 @@ For a developer guide, see the [translating dev doc](https://github.com/vector-i
[<img src="https://translate.element.io/widgets/element-desktop/-/multi-auto.svg" alt="translationsstatus" width="340">](https://translate.element.io/engage/element-desktop/?utm_source=widget)
Report bugs & give feedback
==========================
# Report bugs & give feedback
If you run into any bugs or have feedback you'd like to share, please let us know on GitHub.
To help avoid duplicate issues, please [view existing issues](https://github.com/vector-im/element-web/issues?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc) first (and add a +1) or [create a new issue](https://github.com/vector-im/element-web/issues/new/choose) if you can't find it. Please note that this issue tracker is associated with the [element-web](https://github.com/vector-im/element-web) repo, but is also applied to the code in this repo as well.
To help avoid duplicate issues, please [view existing issues](https://github.com/vector-im/element-web/issues?q=is%3Aopen+is%3Aissue+sort%3Areactions-%2B1-desc) first (and add a +1) or [create a new issue](https://github.com/vector-im/element-web/issues/new/choose) if you can't find it. Please note that this issue tracker is associated with the [element-web](https://github.com/vector-im/element-web) repo, but is also applied to the code in this repo as well.

View File

@@ -1,6 +1,3 @@
module.exports = {
presets: [
['@babel/preset-env', { targets: { node: 'current' } }],
'@babel/preset-typescript',
],
presets: [["@babel/preset-env", { targets: { node: "current" } }], "@babel/preset-typescript"],
};

View File

@@ -21,14 +21,6 @@ Components: main
SignWith: D7B0B66941D01538
Tracking: minimal
Origin: riot.im
Suite: stable
Codename: buster
Architectures: amd64 i386 source
Components: main
SignWith: D7B0B66941D01538
Tracking: minimal
Origin: riot.im
Suite: testing
Codename: bullseye
@@ -58,24 +50,3 @@ Architectures: amd64 i386 source
Components: main
SignWith: D7B0B66941D01538
Tracking: minimal
Origin: riot.im
Codename: cosmic
Architectures: amd64 i386 source
Components: main
SignWith: D7B0B66941D01538
Tracking: minimal
Origin: riot.im
Codename: disco
Architectures: amd64 i386 source
Components: main
SignWith: D7B0B66941D01538
Tracking: minimal
Origin: riot.im
Codename: eoan
Architectures: amd64 i386 source
Components: main
SignWith: D7B0B66941D01538
Tracking: minimal

5
debian/conf/options vendored Normal file
View File

@@ -0,0 +1,5 @@
# don't delete old debs by default
keepunreferencedfiles
# output dir
outdir +b/../packages.element.io/debian

View File

@@ -1,8 +1,9 @@
# Docker image to facilitate building Element Desktop with native bits using a glibc version with broader compatibility
FROM buildpack-deps:bionic-curl
ENV DEBIAN_FRONTEND noninteractive
RUN curl -L https://yarnpkg.com/latest.tar.gz | tar xvz && mv yarn-* /yarn && ln -s /yarn/bin/yarn /usr/bin/yarn
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 -qq dist-upgrade && \
# add repo for git-lfs
curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash && \
@@ -14,6 +15,8 @@ RUN apt-get -qq update && apt-get -qq dist-upgrade && \
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 tcl \
libsecret-1-dev libgnome-keyring-dev \
libopenjp2-tools \
# Used by github actions \
jq grep \
# Used by seshat (when not SQLCIPHER_STATIC) \
libsqlcipher-dev && \
# git-lfs
@@ -34,7 +37,7 @@ ENV FORCE_COLOR true
ENV NODE_VERSION 16.18.1
# this package is used for snapcraft and we should not clear apt list - to avoid apt-get update during snap build
RUN curl -L https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz | tar xz -C /usr/local --strip-components=1 && \
RUN curl --proto "=https" -L https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-linux-x64.tar.gz | tar xz -C /usr/local --strip-components=1 && \
unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md && \
# https://github.com/npm/npm/issues/4531
npm config set unsafe-perm true

View File

@@ -17,13 +17,14 @@ when releasing.
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
- [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
```
@@ -70,7 +71,7 @@ as usual using:
On Windows & macOS we always statically link libsqlcipher for it is not generally available.
On Linux by default we will use a system package, on debian & ubuntu this is `libsqlcipher0`,
but this is problematic for some other packages.
but this is problematic for some other packages.
By including `SQLCIPHER_STATIC=1` in the build environment, the build scripts will statically link sqlcipher,
note that this will want a `libcrypto1.1` shared library available in the system.
@@ -82,15 +83,19 @@ and https://github.com/vector-im/element-web/issues/20926.
### 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
```
@@ -105,10 +110,13 @@ 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
```
@@ -144,6 +152,6 @@ 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
$ 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
```

15
docs/updates.md Normal file
View File

@@ -0,0 +1,15 @@
The Desktop app is capable of self-updating on macOS and Windows.
The update server base url is configurable as `update_base_url` in config.json and can be served by a static file host,
CDN or object storage.
Currently all packaging & deployment is handled by [Github actions](https://github.com/vector-im/element-desktop/blob/develop/.github/workflows/build_and_deploy.yaml)
# Windows
On Windows the update mechanism used is [Squirrel.Windows](https://github.com/Squirrel/Squirrel.Windows)
and can be served by any compatible Squirrel server, such as https://github.com/Tiliq/squirrel-server
# macOS
On macOS the update mechanism used is [Squirrel.Mac](https://github.com/Squirrel/Squirrel.Mac)
using the newer JSON format as documented [here](https://github.com/Squirrel/Squirrel.Mac#update-file-json-format).

View File

@@ -1,26 +1,30 @@
# Windows
## Requirements to build native modules
We rely on Github Actions `windows-latest` plus a few extra utilities as per [the workflow](https://github.com/vector-im/element-desktop/blob/develop/.github/workflows/build_windows.yaml).
If you want to build native modules, make sure that the following tools are installed on your system.
- [Git for Windows](https://git-scm.com/download/win)
- [Node 14](https://nodejs.org)
- [Python 3](https://www.python.org/downloads/) (if you type 'python' into command prompt it will offer to install it from the windows store)
- [Strawberry Perl](https://strawberryperl.com/)
- [Rustup](https://rustup.rs/)
- [NASM](https://www.nasm.us/)
- [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
- On the Individual components tab:
- MSVC VS 2019 C++ build tools
- Windows 10 SDK (latest version available)
- C++ CMake tools for Windows
- [Git for Windows](https://git-scm.com/download/win)
- [Node 16](https://nodejs.org)
- [Python 3](https://www.python.org/downloads/) (if you type 'python' into command prompt it will offer to install it from the windows store)
- [Strawberry Perl](https://strawberryperl.com/)
- [Rustup](https://rustup.rs/)
- [NASM](https://www.nasm.us/)
- [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
- On the Individual components tab:
- MSVC VS 2019 C++ build tools
- Windows 10 SDK (latest version available)
- C++ CMake tools for Windows
Once installed make sure all those utilities are accessible in your `PATH`.
If you want to be able to build x86 targets from an x64 host install the right toolchain:
```cmd
rustup toolchain install stable-i686-pc-windows-msvc
rustup target add i686-pc-windows-msvc

View File

@@ -0,0 +1,7 @@
Package: element-io-archive-keyring
Architecture: all
Section: contrib/meta
Maintainer: support@element.io
Priority: optional
Version: 1.1
Description: The packages.element.io repository keyring

View File

@@ -11,16 +11,11 @@
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"uisi_autorageshake_app": "element-auto-uisi",
"showLabsSettings": true,
"roomDirectory": {
"servers": [
"matrix.org",
"gitter.im",
"libera.chat"
]
"servers": ["matrix.org", "gitter.im", "libera.chat"]
},
"enable_presence_by_hs_url": {
"https://matrix.org": false,

View File

@@ -4,7 +4,7 @@ Vendor: support@element.io
Architecture: amd64
Maintainer: support@element.io
Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libsecret-1-0, libasound2, libgbm1
Recommends: libappindicator3-1, libsqlcipher0
Recommends: libsqlcipher0, element-io-archive-keyring
Section: net
Priority: extra
Homepage: https://element.io/

View File

@@ -11,15 +11,10 @@
"https://scalar-staging.vector.im/api",
"https://scalar-staging.riot.im/scalar/api"
],
"hosting_signup_link": "https://element.io/matrix-services?utm_source=element-web&utm_medium=web",
"bug_report_endpoint_url": "https://element.io/bugreports/submit",
"uisi_autorageshake_app": "element-auto-uisi",
"roomDirectory": {
"servers": [
"matrix.org",
"gitter.im",
"libera.chat"
]
"servers": ["matrix.org", "gitter.im", "libera.chat"]
},
"showLabsSettings": false,
"enable_presence_by_hs_url": {

View File

@@ -4,7 +4,7 @@ Vendor: support@element.io
Architecture: amd64
Maintainer: support@element.io
Depends: libgtk-3-0, libnotify4, libnss3, libxss1, libxtst6, xdg-utils, libatspi2.0-0, libuuid1, libsecret-1-0, libasound2, libgbm1
Recommends: libappindicator3-1, libsqlcipher0
Recommends: libsqlcipher0, element-io-archive-keyring
Replaces: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)
Breaks: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)
Section: net

View File

@@ -14,11 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import path from 'path';
import childProcess from 'child_process';
import path from "path";
import childProcess from "child_process";
import HakEnv from '../../scripts/hak/hakEnv';
import { DependencyInfo } from '../../scripts/hak/dep';
import HakEnv from "../../scripts/hak/hakEnv";
import { DependencyInfo } from "../../scripts/hak/dep";
export default async function buildKeytar(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const env = hakEnv.makeGypEnv();
@@ -26,15 +26,15 @@ export default async function buildKeytar(hakEnv: HakEnv, moduleInfo: Dependency
console.log("Running yarn with env", env);
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
path.join(moduleInfo.nodeModuleBinDir, 'node-gyp' + (hakEnv.isWin() ? '.cmd' : '')),
['rebuild'],
path.join(moduleInfo.nodeModuleBinDir, "node-gyp" + (hakEnv.isWin() ? ".cmd" : "")),
["rebuild"],
{
cwd: moduleInfo.moduleBuildDir,
env,
stdio: 'inherit',
stdio: "inherit",
},
);
proc.on('exit', (code) => {
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});

View File

@@ -14,20 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import childProcess from 'child_process';
import childProcess from "child_process";
import HakEnv from '../../scripts/hak/hakEnv';
import { DependencyInfo } from '../../scripts/hak/dep';
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
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<void>((resolve, reject) => {
const proc = childProcess.spawn(tool[0], tool.slice(1), {
stdio: ['ignore'],
stdio: ["ignore"],
});
proc.on('exit', (code) => {
proc.on("exit", (code) => {
if (code !== 0) {
reject("Can't find " + tool);
} else {

View File

@@ -14,15 +14,24 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import path from 'path';
import childProcess from 'child_process';
import mkdirp from 'mkdirp';
import fsExtra from 'fs-extra';
import path from "path";
import childProcess from "child_process";
import mkdirp from "mkdirp";
import fsExtra from "fs-extra";
import HakEnv from '../../scripts/hak/hakEnv';
import { DependencyInfo } from '../../scripts/hak/dep';
import HakEnv from "../../scripts/hak/hakEnv";
import { DependencyInfo } from "../../scripts/hak/dep";
export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
type WinConfiguration =
| "VC-WIN32"
| "VC-WIN64A"
| "VC-WIN64-ARM"
| "VC-WIN64-CLANGASM-ARM"
| "VC-CLANG-WIN64-CLANGASM-ARM"
| "VC-WIN32-HYBRIDCRT"
| "VC-WIN64A-HYBRIDCRT";
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (hakEnv.isWin()) {
await buildOpenSslWin(hakEnv, moduleInfo);
await buildSqlCipherWin(hakEnv, moduleInfo);
@@ -32,165 +41,158 @@ export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promi
await buildMatrixSeshat(hakEnv, moduleInfo);
}
async function buildOpenSslWin(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
async function buildOpenSslWin(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const version = moduleInfo.cfg.dependencies.openssl;
const openSslDir = path.join(moduleInfo.moduleTargetDotHakDir, `openssl-${version}`);
const openSslArch = hakEnv.getTargetArch() === 'x64' ? 'VC-WIN64A' : 'VC-WIN32';
let openSslArch: WinConfiguration;
switch (hakEnv.getTargetArch()) {
case "x64":
openSslArch = "VC-WIN64A";
break;
case "ia32":
openSslArch = "VC-WIN32";
break;
case "arm64":
openSslArch = "VC-WIN64-ARM";
break;
}
console.log("Building openssl in " + openSslDir);
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
'perl',
"perl",
[
'Configure',
'--prefix=' + moduleInfo.depPrefix,
"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.
'no-afalgeng',
'no-capieng',
'no-cms',
'no-ct',
'no-deprecated',
'no-dgram',
'no-dso',
'no-ec',
'no-ec2m',
'no-gost',
'no-nextprotoneg',
'no-ocsp',
'no-sock',
'no-srp',
'no-srtp',
'no-tests',
'no-ssl',
'no-tls',
'no-dtls',
'no-shared',
'no-aria',
'no-camellia',
'no-cast',
'no-chacha',
'no-cmac',
'no-des',
'no-dh',
'no-dsa',
'no-ecdh',
'no-ecdsa',
'no-idea',
'no-md4',
'no-mdc2',
'no-ocb',
'no-poly1305',
'no-rc2',
'no-rc4',
'no-rmd160',
'no-scrypt',
'no-seed',
'no-siphash',
'no-sm2',
'no-sm3',
'no-sm4',
'no-whirlpool',
"no-afalgeng",
"no-capieng",
"no-cms",
"no-ct",
"no-deprecated",
"no-dgram",
"no-dso",
"no-ec",
"no-ec2m",
"no-gost",
"no-nextprotoneg",
"no-ocsp",
"no-sock",
"no-srp",
"no-srtp",
"no-tests",
"no-ssl",
"no-tls",
"no-dtls",
"no-shared",
"no-aria",
"no-camellia",
"no-cast",
"no-chacha",
"no-cmac",
"no-des",
"no-dh",
"no-dsa",
"no-ecdh",
"no-ecdsa",
"no-idea",
"no-md4",
"no-mdc2",
"no-ocb",
"no-poly1305",
"no-rc2",
"no-rc4",
"no-rmd160",
"no-scrypt",
"no-seed",
"no-siphash",
"no-sm2",
"no-sm3",
"no-sm4",
"no-whirlpool",
openSslArch,
],
{
cwd: openSslDir,
stdio: 'inherit',
stdio: "inherit",
},
);
proc.on('exit', (code) => {
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
'nmake',
['build_libs'],
{
cwd: openSslDir,
stdio: 'inherit',
},
);
proc.on('exit', (code) => {
const proc = childProcess.spawn("nmake", ["build_libs"], {
cwd: openSslDir,
stdio: "inherit",
});
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
'nmake',
['install_dev'],
{
cwd: openSslDir,
stdio: 'inherit',
},
);
proc.on('exit', (code) => {
const proc = childProcess.spawn("nmake", ["install_dev"], {
cwd: openSslDir,
stdio: "inherit",
});
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
}
async function buildSqlCipherWin(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
async function buildSqlCipherWin(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const version = moduleInfo.cfg.dependencies.sqlcipher;
const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`);
const buildDir = path.join(sqlCipherDir, 'bld');
const buildDir = path.join(sqlCipherDir, "bld");
await mkdirp(buildDir);
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
'nmake',
['/f', path.join('..', 'Makefile.msc'), 'libsqlite3.lib', 'TOP=..'],
{
cwd: buildDir,
stdio: 'inherit',
env: Object.assign({}, process.env, {
CCOPTS: "-DSQLITE_HAS_CODEC -I" + path.join(moduleInfo.depPrefix, 'include'),
LTLIBPATHS: "/LIBPATH:" + path.join(moduleInfo.depPrefix, 'lib'),
LTLIBS: "libcrypto.lib",
}),
},
);
proc.on('exit', (code) => {
const proc = childProcess.spawn("nmake", ["/f", path.join("..", "Makefile.msc"), "libsqlite3.lib", "TOP=.."], {
cwd: buildDir,
stdio: "inherit",
env: Object.assign({}, process.env, {
CCOPTS: "-DSQLITE_HAS_CODEC -I" + path.join(moduleInfo.depPrefix, "include"),
LTLIBPATHS: "/LIBPATH:" + path.join(moduleInfo.depPrefix, "lib"),
LTLIBS: "libcrypto.lib",
}),
});
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
await fsExtra.copy(
path.join(buildDir, 'libsqlite3.lib'),
path.join(moduleInfo.depPrefix, 'lib', 'sqlcipher.lib'),
);
await fsExtra.copy(path.join(buildDir, "libsqlite3.lib"), path.join(moduleInfo.depPrefix, "lib", "sqlcipher.lib"));
await fsExtra.copy(
path.join(buildDir, 'sqlite3.h'),
path.join(moduleInfo.depPrefix, 'include', 'sqlcipher.h'),
);
await fsExtra.copy(path.join(buildDir, "sqlite3.h"), path.join(moduleInfo.depPrefix, "include", "sqlcipher.h"));
}
async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
const version = moduleInfo.cfg.dependencies.sqlcipher;
const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`);
const args = [
'--prefix=' + moduleInfo.depPrefix + '',
'--enable-tempstore=yes',
'--enable-shared=no',
'--enable-tcl=no',
"--prefix=" + moduleInfo.depPrefix + "",
"--enable-tempstore=yes",
"--enable-shared=no",
"--enable-tcl=no",
];
if (hakEnv.isMac()) {
args.push('--with-crypto-lib=commoncrypto');
args.push("--with-crypto-lib=commoncrypto");
}
if (hakEnv.wantsStaticSqlCipherUnix()) {
args.push('--enable-tcl=no');
args.push("--enable-tcl=no");
if (hakEnv.isLinux()) {
args.push('--with-pic=yes');
args.push("--with-pic=yes");
}
}
@@ -201,9 +203,7 @@ async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
args.push(`--host=${hakEnv.getTargetId()}`);
}
const cflags = [
'-DSQLITE_HAS_CODEC',
];
const cflags = ["-DSQLITE_HAS_CODEC"];
if (!hakEnv.isHost()) {
// `clang` uses more logical option naming.
@@ -211,64 +211,52 @@ async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
}
if (cflags.length) {
args.push(`CFLAGS=${cflags.join(' ')}`);
args.push(`CFLAGS=${cflags.join(" ")}`);
}
const ldflags: string[] = [];
if (hakEnv.isMac()) {
ldflags.push('-framework Security');
ldflags.push('-framework Foundation');
ldflags.push("-framework Security");
ldflags.push("-framework Foundation");
}
if (ldflags.length) {
args.push(`LDFLAGS=${ldflags.join(' ')}`);
args.push(`LDFLAGS=${ldflags.join(" ")}`);
}
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
path.join(sqlCipherDir, 'configure'),
args,
{
cwd: sqlCipherDir,
stdio: 'inherit',
},
);
proc.on('exit', (code) => {
const proc = childProcess.spawn(path.join(sqlCipherDir, "configure"), args, {
cwd: sqlCipherDir,
stdio: "inherit",
});
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
'make',
[],
{
cwd: sqlCipherDir,
stdio: 'inherit',
},
);
proc.on('exit', (code) => {
const proc = childProcess.spawn("make", [], {
cwd: sqlCipherDir,
stdio: "inherit",
});
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
'make',
['install'],
{
cwd: sqlCipherDir,
stdio: 'inherit',
},
);
proc.on('exit', (code) => {
const proc = childProcess.spawn("make", ["install"], {
cwd: sqlCipherDir,
stdio: "inherit",
});
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
}
async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
// 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.
@@ -277,8 +265,8 @@ async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
if (!hakEnv.isLinux() || hakEnv.wantsStaticSqlCipherUnix()) {
Object.assign(env, {
SQLCIPHER_STATIC: 1,
SQLCIPHER_LIB_DIR: path.join(moduleInfo.depPrefix, 'lib'),
SQLCIPHER_INCLUDE_DIR: path.join(moduleInfo.depPrefix, 'include'),
SQLCIPHER_LIB_DIR: path.join(moduleInfo.depPrefix, "lib"),
SQLCIPHER_INCLUDE_DIR: path.join(moduleInfo.depPrefix, "include"),
});
}
@@ -298,11 +286,11 @@ async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
// --exclude-libs ALL
// Prevent symbols from being exported by any archive libraries.
// Reduces output filesize and prevents being dynamically linked against.
env.RUSTFLAGS = '-Clink-arg=-Wl,-Bsymbolic -Clink-arg=-Wl,--exclude-libs,ALL';
env.RUSTFLAGS = "-Clink-arg=-Wl,-Bsymbolic -Clink-arg=-Wl,--exclude-libs,ALL";
}
if (hakEnv.isWin()) {
env.RUSTFLAGS = '-Ctarget-feature=+crt-static -Clink-args=libcrypto.lib';
env.RUSTFLAGS = "-Ctarget-feature=+crt-static -Clink-args=libcrypto.lib";
// Note that in general, you can specify targets in Rust without having to have
// the matching toolchain, however for this, cargo gets confused when building
// the build scripts since they run on the host, but vcvarsall.bat sets the c
@@ -318,15 +306,15 @@ async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
console.log("Running neon with env", env);
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(
path.join(moduleInfo.nodeModuleBinDir, 'neon' + (hakEnv.isWin() ? '.cmd' : '')),
['build', '--release'],
path.join(moduleInfo.nodeModuleBinDir, "neon" + (hakEnv.isWin() ? ".cmd" : "")),
["build", "--release"],
{
cwd: moduleInfo.moduleBuildDir,
env,
stdio: 'inherit',
stdio: "inherit",
},
);
proc.on('exit', (code) => {
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});

View File

@@ -14,20 +14,20 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import childProcess from 'child_process';
import fsProm from 'fs/promises';
import childProcess from "child_process";
import fsProm from "fs/promises";
import HakEnv from '../../scripts/hak/hakEnv';
import { DependencyInfo } from '../../scripts/hak/dep';
import HakEnv from "../../scripts/hak/hakEnv";
import { DependencyInfo } from "../../scripts/hak/dep";
export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (hakEnv.wantsStaticSqlCipher()) {
// of course tcl doesn't have a --version
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn('tclsh', [], {
stdio: ['pipe', 'ignore', 'ignore'],
const proc = childProcess.spawn("tclsh", [], {
stdio: ["pipe", "ignore", "ignore"],
});
proc.on('exit', (code) => {
proc.on("exit", (code) => {
if (code !== 0) {
reject("Can't find tclsh - have you installed TCL?");
} else {
@@ -39,24 +39,24 @@ export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promi
}
const tools = [
['rustc', '--version'],
['python', '--version'], // node-gyp uses python for reasons beyond comprehension
["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', '/?']);
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']);
tools.push(["make", "--version"]);
}
for (const tool of tools) {
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(tool[0], tool.slice(1), {
stdio: ['ignore'],
stdio: ["ignore"],
});
proc.on('exit', (code) => {
proc.on("exit", (code) => {
if (code !== 0) {
reject("Can't find " + tool);
} else {
@@ -68,19 +68,24 @@ export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promi
// Ensure Rust target exists (nb. we avoid depending on rustup)
await new Promise((resolve, reject) => {
const rustc = childProcess.execFile('rustc', [
'--target', hakEnv.getTargetId(), '-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.stdin.end();
const rustc = childProcess.execFile(
"rustc",
["--target", hakEnv.getTargetId(), "-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.stdin!.end();
});
}

View File

@@ -14,17 +14,25 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
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';
import path from "path";
import childProcess from "child_process";
import fs from "fs";
import fsProm from "fs/promises";
import tar from "tar";
import fetch from "node-fetch";
import { promises as stream } from "stream";
import HakEnv from '../../scripts/hak/hakEnv';
import { DependencyInfo } from '../../scripts/hak/dep';
import HakEnv from "../../scripts/hak/hakEnv";
import { DependencyInfo } from "../../scripts/hak/dep";
export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
async function download(url: string, filename: string): Promise<void> {
const resp = await fetch(url);
if (!resp.ok) throw new Error(`unexpected response ${resp.statusText}`);
if (!resp.body) throw new Error(`unexpected response has no body ${resp.statusText}`);
await stream.pipeline(resp.body, fs.createWriteStream(filename));
}
export default async function (hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (hakEnv.wantsStaticSqlCipher()) {
await getSqlCipher(hakEnv, moduleInfo);
}
@@ -57,11 +65,7 @@ async function getSqlCipher(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise
haveSqlcipherTar = false;
}
if (!haveSqlcipherTar) {
const bob = needle('get', `https://github.com/sqlcipher/sqlcipher/archive/v${version}.tar.gz`, {
follow: 10,
output: sqlCipherTarball,
});
await bob;
await download(`https://github.com/sqlcipher/sqlcipher/archive/v${version}.tar.gz`, sqlCipherTarball);
}
// Extract the tarball to per-target directories, then we avoid cross-contaiminating archs
@@ -79,15 +83,11 @@ async function getSqlCipher(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise
await new Promise<void>((resolve, reject) => {
const readStream = fs.createReadStream(patchFile);
const proc = childProcess.spawn(
'patch',
['-p1'],
{
cwd: sqlCipherDir,
stdio: ['pipe', 'inherit', 'inherit'],
},
);
proc.on('exit', (code) => {
const proc = childProcess.spawn("patch", ["-p1"], {
cwd: sqlCipherDir,
stdio: ["pipe", "inherit", "inherit"],
});
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
readStream.pipe(proc.stdin);
@@ -118,10 +118,7 @@ async function getOpenSsl(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<v
haveOpenSslTar = false;
}
if (!haveOpenSslTar) {
await needle('get', `https://www.openssl.org/source/openssl-${version}.tar.gz`, {
follow: 10,
output: openSslTarball,
});
await download(`https://www.openssl.org/source/openssl-${version}.tar.gz`, openSslTarball);
}
console.log("extracting " + openSslTarball + " in " + moduleInfo.moduleTargetDotHakDir);

View File

@@ -1,17 +1,14 @@
{
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"target": "es2016",
"sourceMap": false,
"lib": [
"es2019",
]
},
"include": [
"./**/*.ts"
],
"ts-node": {
"transpileOnly": true
}
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"target": "es2016",
"sourceMap": false,
"strict": true,
"lib": ["es2019"]
},
"include": ["../scripts/@types/*.d.ts", "./**/*.ts"],
"ts-node": {
"transpileOnly": true
}
}

View File

@@ -2,7 +2,7 @@
"name": "element-desktop",
"productName": "Element",
"main": "lib/electron-main.js",
"version": "1.11.15",
"version": "1.11.29",
"description": "A feature-rich client for Matrix.org",
"author": "Element",
"repository": {
@@ -11,18 +11,33 @@
},
"license": "Apache-2.0",
"files": [],
"engines": {
"node": ">=16.0.0"
},
"scripts": {
"i18n": "matrix-gen-i18n",
"prunei18n": "matrix-prune-i18n",
"diff-i18n": "cp src/i18n/strings/en_EN.json src/i18n/strings/en_EN_orig.json && matrix-gen-i18n && matrix-compare-i18n-files src/i18n/strings/en_EN_orig.json src/i18n/strings/en_EN.json",
"mkdirs": "mkdirp packages deploys",
"fetch": "yarn run mkdirs && node scripts/fetch-package.js",
"fetch": "yarn run mkdirs && ts-node scripts/fetch-package.ts",
"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 --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",
"lint:js": "yarn lint:js:src && yarn lint:js:test && yarn lint:js:scripts && yarn lint:js:hak",
"lint:js:src": "eslint --max-warnings 0 src",
"lint:js:test": "eslint --max-warnings 0 --config .eslintrc-test.js test",
"lint:js:scripts": "eslint --max-warnings 0 --config .eslintrc-scripts.js scripts",
"lint:js:hak": "eslint --max-warnings 0 --config .eslintrc-hak.js hak",
"lint:js-fix": "yarn lint:js-fix:src &&yarn lint:js-fix:test && yarn lint:js-fix:scripts && yarn lint:js-fix:hak",
"lint:js-fix:src": "eslint --fix --max-warnings 0 src",
"lint:js-fix:test": "eslint --fix --max-warnings 0 --config .eslintrc-test.js test",
"lint:js-fix:scripts": "eslint --fix --max-warnings 0 --config .eslintrc-scripts.js scripts",
"lint:js-fix:hak": "eslint --fix --max-warnings 0 --config .eslintrc-hak.js hak",
"lint:types": "yarn lint:types:src && yarn lint:types:test && yarn lint:types:scripts && yarn lint:types:hak",
"lint:types:src": "tsc --noEmit",
"lint:types:test": "tsc --noEmit -p test/tsconfig.json",
"lint:types:scripts": "tsc --noEmit -p scripts/tsconfig.json",
"lint:types:hak": "tsc --noEmit -p hak/tsconfig.json",
"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",
@@ -30,19 +45,20 @@
"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",
"build:res": "ts-node scripts/copy-res.ts",
"docker:setup": "docker build -t element-desktop-dockerbuild dockerbuild",
"docker:build:native": "scripts/in-docker.sh yarn run hak",
"docker:build": "scripts/in-docker.sh yarn run build",
"docker:install": "scripts/in-docker.sh yarn install",
"debrepo": "scripts/mkrepo.sh",
"clean": "rimraf webapp.asar dist packages deploys lib",
"hak": "ts-node scripts/hak/index.ts",
"test": "jest"
},
"dependencies": {
"@sentry/electron": "^4.3.0",
"auto-launch": "^5.0.5",
"counterpart": "^0.18.6",
"electron-clear-data": "^1.0.5",
"electron-store": "^8.0.2",
"electron-window-state": "^5.0.3",
"minimist": "^1.2.6",
@@ -54,6 +70,7 @@
"@babel/core": "^7.18.10",
"@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6",
"@electron/asar": "^3.2.3",
"@electron/notarize": "^1.2.3",
"@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1",
@@ -61,48 +78,49 @@
"@types/jest": "^29.0.0",
"@types/minimist": "^1.2.1",
"@types/mkdirp": "^1.0.2",
"@types/node": "16.18.23",
"@types/pacote": "^11.1.1",
"@types/rimraf": "^3.0.2",
"@types/tar": "^6.1.3",
"@typescript-eslint/eslint-plugin": "^5.42.0",
"@typescript-eslint/parser": "^5.42.0",
"allchange": "^1.0.6",
"app-builder-lib": "^22.14.10",
"asar": "^2.0.1",
"app-builder-lib": "24.0.0",
"babel-jest": "^29.0.0",
"chokidar": "^3.5.2",
"detect-libc": "^1.0.3",
"electron": "^21",
"electron-builder": "^23.6.0",
"electron-builder-squirrel-windows": "^23.6.0",
"electron-devtools-installer": "^3.1.1",
"electron": "^24.0.0",
"electron-builder": "24.0.0",
"electron-builder-squirrel-windows": "24.1.2",
"electron-devtools-installer": "^3.2.0",
"eslint": "^8.26.0",
"eslint-config-google": "^0.14.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-matrix-org": "^0.7.0",
"eslint-plugin-unicorn": "^45.0.0",
"eslint-plugin-matrix-org": "^1.0.0",
"eslint-plugin-unicorn": "^46.0.0",
"expect-playwright": "^0.8.0",
"find-npm-prefix": "^1.0.2",
"fs-extra": "^10.0.0",
"glob": "^7.1.6",
"fs-extra": "^11.0.0",
"glob": "^9.0.0",
"jest": "^29.0.0",
"matrix-web-i18n": "^1.3.0",
"mkdirp": "^1.0.3",
"needle": "^2.5.0",
"node-pre-gyp": "^0.15.0",
"pacote": "^11.3.5",
"mkdirp": "^2.0.0",
"node-pre-gyp": "^0.17.0",
"pacote": "^15.0.0",
"playwright": "^1.25.0",
"rimraf": "^3.0.2",
"prettier": "^2.8.1",
"rimraf": "^4.4.1",
"tar": "^6.1.2",
"ts-jest": "^29.0.0",
"ts-node": "^10.9.1",
"typescript": "4.5.5"
"typescript": "5.0.3"
},
"hakDependencies": {
"matrix-seshat": "^2.3.3",
"keytar": "^7.9.0"
},
"resolutions": {
"@types/node": "16.11.38"
"@types/node": "16.18.23"
},
"build": {
"appId": "im.riot.app",
@@ -128,26 +146,22 @@
"deb"
],
"category": "Network;InstantMessaging;Chat",
"maintainer": "support@element.io",
"desktop": {
"StartupWMClass": "element"
}
"maintainer": "support@element.io"
},
"mac": {
"category": "public.app-category.social-networking",
"darkModeSupport": true
"darkModeSupport": true,
"gatekeeperAssess": true
},
"win": {
"target": [
"squirrel"
],
"sign": "scripts/electron_winSign"
]
},
"directories": {
"output": "dist"
},
"afterPack": "scripts/electron_afterPack",
"afterSign": "scripts/electron_afterSign",
"protocols": [
{
"name": "element",

View File

@@ -24,35 +24,69 @@ zj97Y0WRPkAagJzeesIx/M4pjYg9zDIZ22NWT9d7KAZemLVtREwWM4zKYEI0Hpid
GxR8jQ1rCc9RMVdO6xuhnVwUD/JyNEgtRKbBJX9qIH2Z30rvIg7ev9MJG6g52cDy
+inNdxh4u4vpqQjjLTBraRalUe/4S4I8EaUFya91RWDLrEcmgdYfrqXbLMAEcPWS
cYQdjW3ADEy47rGQ2SeaZweLuHGVx68hCcJx5E0X7eE32R8uaRjmEzgvU+wZKo0y
HFbLsQok8v7NqoqtuQGNBFy1FtQBDADPalE7/hP0kt7afhFoY/sGyO/464BA4Ozo
MaQC28d4JJCd07upnyj1aLGHfYyO6TXC1cqOQ2tThENyTfJOhVDQ9YCjqDzm4S5V
R91tNzvYNZOEIwRRPND2jpnmsCzwrnIRHNIiojHBZRnPdC01zcx4oC1m13qDiFSU
NOi/uDlAXtOf8p0zVnPypaGTG7MUBU8RmkyygvG+Z6AqNDOsDL/nIC5mf2zmLJqK
VkEeXnWhWBEVgIdr840vi/ejblmVRxanlyGVFY/5CWgylmGxxB0Oh5vz7SjpK5H5
pONBo43K2tEjnU1jmWTX7tkHYo8wyQS04uO33qh01FLnYl1I0qebfwBys88i/yhr
9afxcXae5xTLUPzPp+6WYICxRdJ41/3zwlyKbNLvyNQzv43kiRYNR3Yc44F1tHMq
1Ty3kca7Qe0zGXXeISY3fUA4zKjg0S8bi3yfO5Z/FxpMhjJ+tAcDoiVrXZwsXCsd
MnQR0KVjzIAmCuJI7OUnujuAB9aMYSEAEQEAAYkD8gQYAQoAJgIbAhYhBBLUzWAM
IkCp9KggcdewtmlB0BU4BQJgd9oUBQkHhSpAAcDA9CAEGQEKAB0WIQR1dBiQBj5e
mkYTXQHChQsmWsCFvQUCXLUW1AAKCRDChQsmWsCFvaDYDADPVBNm75uZtEPOM2Ct
oxASarbPDLz8Ucy6FCtOoSpNdgAZFTISFASWfBO6h/9w5czT3owQD431V950QBHG
t763VFILckZ0Ul4roGGesmncRUIZLrc+UABigirHmCdnvo9s5UszTxid0muMbDeL
b1RmI0tkRDzlk/TrkHDf7rIUrcqhPqhtR0b75MfosEaowVN+kS9PqyFtXsrKB/iM
/gjvVnEEfIVDaK+lc6EBbqfJLMCa5z63CSEqMUhWP0qXGoA7ZM6AzaplzCTr5aB9
dQBNU53SUo35OzblQSqR0gyuCYrvOHtisjTdrrUNsIbyjkUOc5Umpxzs9XmY94D5
FfdxeALvYcs2hMEQWPoINVx87p1tWjwnmPzXGm2q095gL+ysOS5OeKOaPEPWfUe7
NUd/WJ3GqvtPiF++PMEDBiPBm5gwrfg8Nd9xNoRntRZoOKJDcJ2/hhH5+4zPW54O
8Z4xBaOGjbWYTMxKw/M9sRmHIvXVcQmWdPhCOIP1XQndJoAJENewtmlB0BU4lpQQ
AK4hX6My0ehfuXoEl9BZE0T+HCFvwgH6xUoAjocZEw7l3ud6M4OouIaoODE/Fqgm
g/kFXjwyl/VQRDalMzi6ajPM6T3AOhv+d2oeNNJCSoilQUsJwAzMHDncbt7rGAb5
SoeFEKdwu07lXRIVPhjmC+CgWT24Osv8dmOCj60jBaGdKEnmmdQ8Kq+h2k21oI2I
TYhjQBPcpxj0RSIJQHVHBYF3hgIZSWOeEg6ocx+3BLR2InEFwEK/GM9iXkwTadr5
3AyaPAcOTaOeSQYKya3onQDI1LFhU5XnLg6YX1PKpKQMtouyM77RxqXk7QMsY0S9
y8rveH5AK5Iou5IFcpXslVNyw63UFGiUQWKnYUMEm14Kzz/4EOVCDPjMY4Uj9rkh
rNR2Oc1fqtFNDMfbQKpxP6JlIHnTFRRYkbW98/oHAvVekysYq29CVg5MjVqPw6ek
//nOPuiFXa1dR3sMntsP+atG5imBINmRRzQ0Ha5CnX4a0PE4ZnTwLPPDDz0Hp2Rf
+X5AgKbCRA6s+O0juqKBcwdp/lWaMfm2KSBjLKalf654NeoKCHh1x5896NM5xVpl
UeI+G/FygG4XwKBuw408ZLlSgF7Dd02BMKptjLkIrnAEG8abvcRIgf2q+QwX3H8E
jxIwng3BGYCBP1LW3ulIrcfJ96/PkZG8MYuSCCIHzNkB
=JVma
HFbLsQok8v7NqoqtiQJUBBMBCgA+AhsDBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA
FiEEEtTNYAwiQKn0qCBx17C2aUHQFTgFAmQTZtMFCRoqUzwACgkQ17C2aUHQFTje
kRAAl0NkH0roj3qvjvAdZUU3vN+5ju68MddDaThuMEhrIO4OZKEVoD0iEiQT1p5n
PS06NkISzXOXRJ4TSlZ/r0U8o5HSfGwYmczyVpwiQYdbGdjMYPt0E/WTnPV59iKv
BmYeN/cUyo3WuPGRP0suA86XkMO73buHEx8/srQE1EFeDsBGruyIqRTGq9lLCi0P
ozyal+vjwrWd7D8MwQRu4YGnk7eCaHek+pSI3DZDxoRs2NqPPx8wT5O3manTBLjQ
HX24+VjOof6EhsOr6uGXIRpK7gK6olJj8gyEWpuz3R3Y2usWPK+n/nHFc+/YBS7w
y6uy+2aur4sjSqgCzNnI+o2GlDX+a1cB+urz1apQAOCRSZycGKuVXRYDFbIGi71V
sTq2x7qM0cbCu4bAU/rWxJaYrVo2xtBywiM2bjTrYty8Dyi59WqnsWuWxCbN5mB7
6sGuomL13yZF3eHhzKQjJiK7xpPJXHu2iizFems9JlH0e5MtyXp9vcPBEJyyuYR5
Q3HatbnkGccRe+W08CR3k3nzdStCXIxDb47Eo62I3D/q/SgXlFEDaiLtR+PAkNvX
i4NXnGGE/+yH9ISGYax/jRTjRVpMUfSbgUbAP/5X2X54qShVtz0hDOIiCWX+DXMV
d9LYXoBs0isS7bKvZ0qu775knyaLGZKkxHcYFtseF4SmAvC5AY0EXLUW1AEMAM9q
UTv+E/SS3tp+EWhj+wbI7/jrgEDg7OgxpALbx3gkkJ3Tu6mfKPVosYd9jI7pNcLV
yo5Da1OEQ3JN8k6FUND1gKOoPObhLlVH3W03O9g1k4QjBFE80PaOmeawLPCuchEc
0iKiMcFlGc90LTXNzHigLWbXeoOIVJQ06L+4OUBe05/ynTNWc/KloZMbsxQFTxGa
TLKC8b5noCo0M6wMv+cgLmZ/bOYsmopWQR5edaFYERWAh2vzjS+L96NuWZVHFqeX
IZUVj/kJaDKWYbHEHQ6Hm/PtKOkrkfmk40Gjjcra0SOdTWOZZNfu2QdijzDJBLTi
47feqHTUUudiXUjSp5t/AHKzzyL/KGv1p/Fxdp7nFMtQ/M+n7pZggLFF0njX/fPC
XIps0u/I1DO/jeSJFg1HdhzjgXW0cyrVPLeRxrtB7TMZdd4hJjd9QDjMqODRLxuL
fJ87ln8XGkyGMn60BwOiJWtdnCxcKx0ydBHQpWPMgCYK4kjs5Se6O4AH1oxhIQAR
AQABiQPyBBgBCgAmAhsCFiEEEtTNYAwiQKn0qCBx17C2aUHQFTgFAmB32hQFCQeF
KkABwMD0IAQZAQoAHRYhBHV0GJAGPl6aRhNdAcKFCyZawIW9BQJctRbUAAoJEMKF
CyZawIW9oNgMAM9UE2bvm5m0Q84zYK2jEBJqts8MvPxRzLoUK06hKk12ABkVMhIU
BJZ8E7qH/3DlzNPejBAPjfVX3nRAEca3vrdUUgtyRnRSXiugYZ6yadxFQhkutz5Q
AGKCKseYJ2e+j2zlSzNPGJ3Sa4xsN4tvVGYjS2REPOWT9OuQcN/ushStyqE+qG1H
Rvvkx+iwRqjBU36RL0+rIW1eysoH+Iz+CO9WcQR8hUNor6VzoQFup8kswJrnPrcJ
ISoxSFY/SpcagDtkzoDNqmXMJOvloH11AE1TndJSjfk7NuVBKpHSDK4Jiu84e2Ky
NN2utQ2whvKORQ5zlSanHOz1eZj3gPkV93F4Au9hyzaEwRBY+gg1XHzunW1aPCeY
/NcabarT3mAv7Kw5Lk54o5o8Q9Z9R7s1R39Yncaq+0+IX748wQMGI8GbmDCt+Dw1
33E2hGe1Fmg4okNwnb+GEfn7jM9bng7xnjEFo4aNtZhMzErD8z2xGYci9dVxCZZ0
+EI4g/VdCd0mgAkQ17C2aUHQFTiWlBAAriFfozLR6F+5egSX0FkTRP4cIW/CAfrF
SgCOhxkTDuXe53ozg6i4hqg4MT8WqCaD+QVePDKX9VBENqUzOLpqM8zpPcA6G/53
ah400kJKiKVBSwnADMwcOdxu3usYBvlKh4UQp3C7TuVdEhU+GOYL4KBZPbg6y/x2
Y4KPrSMFoZ0oSeaZ1Dwqr6HaTbWgjYhNiGNAE9ynGPRFIglAdUcFgXeGAhlJY54S
DqhzH7cEtHYicQXAQr8Yz2JeTBNp2vncDJo8Bw5No55JBgrJreidAMjUsWFTlecu
DphfU8qkpAy2i7IzvtHGpeTtAyxjRL3Lyu94fkArkii7kgVyleyVU3LDrdQUaJRB
YqdhQwSbXgrPP/gQ5UIM+MxjhSP2uSGs1HY5zV+q0U0Mx9tAqnE/omUgedMVFFiR
tb3z+gcC9V6TKxirb0JWDkyNWo/Dp6T/+c4+6IVdrV1Hewye2w/5q0bmKYEg2ZFH
NDQdrkKdfhrQ8ThmdPAs88MPPQenZF/5fkCApsJEDqz47SO6ooFzB2n+VZox+bYp
IGMspqV/rng16goIeHXHnz3o0znFWmVR4j4b8XKAbhfAoG7DjTxkuVKAXsN3TYEw
qm2MuQiucAQbxpu9xEiB/ar5DBfcfwSPEjCeDcEZgIE/Utbe6Uitx8n3r8+Rkbwx
i5IIIgfM2QGJA/IEGAEKACYCGwIWIQQS1M1gDCJAqfSoIHHXsLZpQdAVOAUCZBNm
+gUJCyC3JgHAwPQgBBkBCgAdFiEEdXQYkAY+XppGE10BwoULJlrAhb0FAly1FtQA
CgkQwoULJlrAhb2g2AwAz1QTZu+bmbRDzjNgraMQEmq2zwy8/FHMuhQrTqEqTXYA
GRUyEhQElnwTuof/cOXM096MEA+N9VfedEARxre+t1RSC3JGdFJeK6BhnrJp3EVC
GS63PlAAYoIqx5gnZ76PbOVLM08YndJrjGw3i29UZiNLZEQ85ZP065Bw3+6yFK3K
oT6obUdG++TH6LBGqMFTfpEvT6shbV7Kygf4jP4I71ZxBHyFQ2ivpXOhAW6nySzA
muc+twkhKjFIVj9KlxqAO2TOgM2qZcwk6+WgfXUATVOd0lKN+Ts25UEqkdIMrgmK
7zh7YrI03a61DbCG8o5FDnOVJqcc7PV5mPeA+RX3cXgC72HLNoTBEFj6CDVcfO6d
bVo8J5j81xptqtPeYC/srDkuTnijmjxD1n1HuzVHf1idxqr7T4hfvjzBAwYjwZuY
MK34PDXfcTaEZ7UWaDiiQ3Cdv4YR+fuMz1ueDvGeMQWjho21mEzMSsPzPbEZhyL1
1XEJlnT4QjiD9V0J3SaACRDXsLZpQdAVOLR+EACQWO84JbUqSVkInAPJ+dsWXq9Z
cm1GwwipsoaDkZSDWZMX2Yj2TKVbeqEDNuBC5/KFSwyBKB3edBUy8onrYqRdLx0q
qQj2PFRFo4Iz3si+6iBEGQtK5OZXjBkuDuzxcNRlp9Sooquf5n9dLaXQWj6IfH5u
Vlpkf/EoCKEuWqRHpn/NpN4Goc+m4ZPU6eJiJr5RMnv4lHgJyn03IZRbltqEL0gB
OEOxUEhVJvkknw5aTTZrr8OHnh614Duq1asrrU5jaowGWMnfeOPyT0oDgmnUzg0k
PrNkhro/SbSWxzVpC+dapVIg4udGyU03XgXP6C1psKfdBMoZoMzSX1E5aItS5yr9
KGyUUwQh0m0kzzUD1tVJU0QmLpTow/O2IaV+c1iPOB5AZ4fXyBq8X/NuWDmN42Jh
zgtjQyb97wy9/ABqQn5fy1KNAjN4yOIHri/UY+y0OuU27g4mSfJCBEA+H9mt8Cgv
CB0xdYaDfjc1uq9UoEAteuY4bso9KpB84UtJetEOxQWYJe7LVRiha037wTOpxgD2
JhHPU8f//FocQXkZNxOeNSWQLM/U5d2X9ISjOZGRyctk3VHKWv45v0bOs6NnT4tU
SaV+98JeB1eVCmOrKvgmxoNGK+n9kdtbrGb9kLfMarAvx1/GTHC6b9oQ50bQ6Igk
KOQ1/miIFEhO+ksiqQ==
=OOgy
-----END PGP PUBLIC KEY BLOCK-----

View File

Binary file not shown.

View File

@@ -1,65 +0,0 @@
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBFy1FpcBEADemFRfa16qbsgvnEq5TPhFOssXfSLG4eGBrU0O6adDwv6QyE53
fivsepaZ21xLXP8KdfJBe40XmsYDLk6I+1cQIoKLCDhN/omaCivJ0QwsHKFqdhsD
0mmGpRzN1nNXOV856tcWsj25T4V2ttPumvCV/ArITta0X2GPbF2oYKbKjE93uZWR
xogqHrD7QVzjlDvU6+gQ/TzIA/k0cG/LlOqhHTrR/VMvSzE9LDn2YoWaC2Hk2NZE
Uby788vombTgPhTrCUmQwDsaXYUfILLhaiAdCqNc3aMcNjc3VX1YjJG0pArx9V2N
RPMR2UZQzSLgthEz/om9k7x9A9RG85Jo2AAmjrpIl4NRawpKP+uXtIdr4huCzWT4
r8e1DiMORKRvRPzua/kf+i8vjKWy16KRD5N6rNOTjfoSQxkQTgh9fvLgJUAJ+UnL
gLKXaijyyIisQ6O2zaI5jJMuSzBG129xpdCeNB0Vmfuy8fBGttTg+OoP1mhnQtDA
mh7k5EefFKDoKKgt2m+C6nlLr7pG9EA5qMHbQikmZo33phi/yIIU0w8RahueC7A1
rCvDla+lr9Y2o0Y+2VGTqkc37WadiCcF6DZ/rKMoajgafbJV3QsVBdD0rraqLfvK
/+UfbbJuZdxb7LtBMGL35ENrVfFNZDiEFJs0eumDCk/KLGBVlL25PH6kIwARAQAB
tCNyaW90LmltIHBhY2thZ2VzIDxwYWNrYWdlc0ByaW90LmltPokCVAQTAQoAPhYh
BBLUzWAMIkCp9KggcdewtmlB0BU4BQJctRaXAhsDBQkJZgGABQsJCAcCBhUKCQgL
AgQWAgMBAh4BAheAAAoJENewtmlB0BU49RsP/2wqPjk4VDhAf10oP2HWyE98nfGm
SriZFQgewbvgwWzXMdIkGpKGxOsl6SFIgVALPGNE/NBbCjn899l207UMqJt0ylZ1
9YZgoKwJwZBNDAGPxWgqCUnxZJwZ2iBOPq4jYyn/why91H55T0fICyF0ZDUJUj0C
b5P5lASeNJaAxweQ6rqAhVQFSD64t1yR/3sMISRHXl6j12ko6wQmZgZf8VR0NrrP
4EF8892/bpSbM9SsZdCSRvyiRFuPATz6z8+jQIUnVmlHILPH/efuwkbPh4MAsQRg
xpVzSwCIurp2zc7R3s03DB2K4Ox8xlawsvYQUVPcEg4EOUK4MC0Zly+dOVUmVzm3
zj97Y0WRPkAagJzeesIx/M4pjYg9zDIZ22NWT9d7KAZemLVtREwWM4zKYEI0Hpid
5y4uaKaOh7hCNswnorOovNQ/wnDG0X7wiI9+iSR/mfo84OyYYzGnz3aPEjrKuOtM
GxR8jQ1rCc9RMVdO6xuhnVwUD/JyNEgtRKbBJX9qIH2Z30rvIg7ev9MJG6g52cDy
+inNdxh4u4vpqQjjLTBraRalUe/4S4I8EaUFya91RWDLrEcmgdYfrqXbLMAEcPWS
cYQdjW3ADEy47rGQ2SeaZweLuHGVx68hCcJx5E0X7eE32R8uaRjmEzgvU+wZKo0y
HFbLsQok8v7NqoqtiQEzBBABCgAdFiEEQlNDQm4FMsm53u1sih+T1XW16NUFAly1
FzMACgkQih+T1XW16NUl8AgAnuMyOfLRynXceH/kF8atQZ8nty8+1CgQhHNRreFu
Q2hm2VkM0xn0QvISkLX5yPwXVNeRyW0xIwwOwgP4Gu91fYujgUv/P2bPIuQlAqrZ
XMvR8IZ9xLUiS1xCktlZYzyg/36ZFd6bcYkxfplJ86yLHya8vy7oyAKr7Po13K1l
qxPANte/Ak4DfoejfjnzwnMza0dfKh7XjqHRzkVXeQhGsgVoWPssGKsEyI3HDI4J
zvpPajSMSWHcbjKQSk2QqwEwjg5ITEBs3PCmKLkKR7qq7+tKU/iIrPJ72BqMluCK
UE+9s5RvcXkDHmEgnE2NBOLGJ4ZcsajGxs7DjGNYlnMG9bkBjQRctRbUAQwAz2pR
O/4T9JLe2n4RaGP7Bsjv+OuAQODs6DGkAtvHeCSQndO7qZ8o9Wixh32Mjuk1wtXK
jkNrU4RDck3yToVQ0PWAo6g85uEuVUfdbTc72DWThCMEUTzQ9o6Z5rAs8K5yERzS
IqIxwWUZz3QtNc3MeKAtZtd6g4hUlDTov7g5QF7Tn/KdM1Zz8qWhkxuzFAVPEZpM
soLxvmegKjQzrAy/5yAuZn9s5iyailZBHl51oVgRFYCHa/ONL4v3o25ZlUcWp5ch
lRWP+QloMpZhscQdDoeb8+0o6SuR+aTjQaONytrRI51NY5lk1+7ZB2KPMMkEtOLj
t96odNRS52JdSNKnm38AcrPPIv8oa/Wn8XF2nucUy1D8z6fulmCAsUXSeNf988Jc
imzS78jUM7+N5IkWDUd2HOOBdbRzKtU8t5HGu0HtMxl13iEmN31AOMyo4NEvG4t8
nzuWfxcaTIYyfrQHA6Ila12cLFwrHTJ0EdClY8yAJgriSOzlJ7o7gAfWjGEhABEB
AAGJA/IEGAEKACYWIQQS1M1gDCJAqfSoIHHXsLZpQdAVOAUCXLUW1AIbAgUJA8Jn
AAHACRDXsLZpQdAVOMD0IAQZAQoAHRYhBHV0GJAGPl6aRhNdAcKFCyZawIW9BQJc
tRbUAAoJEMKFCyZawIW9oNgMAM9UE2bvm5m0Q84zYK2jEBJqts8MvPxRzLoUK06h
Kk12ABkVMhIUBJZ8E7qH/3DlzNPejBAPjfVX3nRAEca3vrdUUgtyRnRSXiugYZ6y
adxFQhkutz5QAGKCKseYJ2e+j2zlSzNPGJ3Sa4xsN4tvVGYjS2REPOWT9OuQcN/u
shStyqE+qG1HRvvkx+iwRqjBU36RL0+rIW1eysoH+Iz+CO9WcQR8hUNor6VzoQFu
p8kswJrnPrcJISoxSFY/SpcagDtkzoDNqmXMJOvloH11AE1TndJSjfk7NuVBKpHS
DK4Jiu84e2KyNN2utQ2whvKORQ5zlSanHOz1eZj3gPkV93F4Au9hyzaEwRBY+gg1
XHzunW1aPCeY/NcabarT3mAv7Kw5Lk54o5o8Q9Z9R7s1R39Yncaq+0+IX748wQMG
I8GbmDCt+Dw133E2hGe1Fmg4okNwnb+GEfn7jM9bng7xnjEFo4aNtZhMzErD8z2x
GYci9dVxCZZ0+EI4g/VdCd0mgExeEACPH4USF03wP8EcSSKs6DXtCHPv+PqEMD6w
0AckI2scEKQ0b45xY4ASEytQlHDpZ+HQLJ22JJ2WT9z+ZL6KC2mAafW5GTpyL6Vl
WbikiN4V2ueIV3Z1sW9m5342RmqM7OKum2F2phrWfauQxRxwp+bCU7TfbF+PNedb
dqsyXNLUdgM01GnjTL5sWNp3GJPC22RBjC1Ssc9+e+sde2/HkoBbpCd0xc7wN6cP
O+SpGJSkWnvOfEnBLGwk8fLZz3wfwVZe8A8tmPMrQNievnPvoz2urkkFYaZ8bOLt
YRK/3RtALnz4fpuwqOwNdPOGbXVhXPQZ7euJ7pCuIbCbcYxYJJd1UdFMnFB/YkXB
s/O7TOQzoIEGlNBLzg8d6rnm+Hg8o/PrKwLqYTgvrjSm2DbbP0T38tlgxM2JNP9+
AELqcgvafnaq0H+jGvM2gCu70Jv0qfzuK9BYiR4kOAq9vT2D8doWDOF4yX71KT81
ntz4qHNRyf7foTIDpxQ1QgYGtpJ3yjp4tcoElFbHBDIZ6TcPh4xP8Yw8AkvvsnYG
ARxZDEF+FfH6mikEJSoa6++byxdkmVuQzTj0ZSNev4Z68MF1NhV3vZP2GjQte14v
v+o35cEMLqEybxi6EPBLbl1B841zDty55Jp6QjK9uAxcCLHZiN5ffK6lKvdRBhT0
l91/+ZrRJQ==
=kDqh
-----END PGP PUBLIC KEY BLOCK-----

View File

@@ -1,154 +1,139 @@
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 100;
font-display: swap;
src: url("Inter-Thin.woff2?v=3.19") format("woff2"),
url("Inter-Thin.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 100;
font-display: swap;
src: url("Inter-Thin.woff2?v=3.19") format("woff2"), url("Inter-Thin.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 100;
font-display: swap;
src: url("Inter-ThinItalic.woff2?v=3.19") format("woff2"),
url("Inter-ThinItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 100;
font-display: swap;
src: url("Inter-ThinItalic.woff2?v=3.19") format("woff2"), url("Inter-ThinItalic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 200;
font-display: swap;
src: url("Inter-ExtraLight.woff2?v=3.19") format("woff2"),
url("Inter-ExtraLight.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 200;
font-display: swap;
src: url("Inter-ExtraLight.woff2?v=3.19") format("woff2"), url("Inter-ExtraLight.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 200;
font-display: swap;
src: url("Inter-ExtraLightItalic.woff2?v=3.19") format("woff2"),
url("Inter-ExtraLightItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 200;
font-display: swap;
src: url("Inter-ExtraLightItalic.woff2?v=3.19") format("woff2"),
url("Inter-ExtraLightItalic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 300;
font-display: swap;
src: url("Inter-Light.woff2?v=3.19") format("woff2"),
url("Inter-Light.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 300;
font-display: swap;
src: url("Inter-Light.woff2?v=3.19") format("woff2"), url("Inter-Light.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 300;
font-display: swap;
src: url("Inter-LightItalic.woff2?v=3.19") format("woff2"),
url("Inter-LightItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 300;
font-display: swap;
src: url("Inter-LightItalic.woff2?v=3.19") format("woff2"), url("Inter-LightItalic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("Inter-Regular.woff2?v=3.19") format("woff2"),
url("Inter-Regular.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 400;
font-display: swap;
src: url("Inter-Regular.woff2?v=3.19") format("woff2"), url("Inter-Regular.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 400;
font-display: swap;
src: url("Inter-Italic.woff2?v=3.19") format("woff2"),
url("Inter-Italic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 400;
font-display: swap;
src: url("Inter-Italic.woff2?v=3.19") format("woff2"), url("Inter-Italic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("Inter-Medium.woff2?v=3.19") format("woff2"),
url("Inter-Medium.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 500;
font-display: swap;
src: url("Inter-Medium.woff2?v=3.19") format("woff2"), url("Inter-Medium.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 500;
font-display: swap;
src: url("Inter-MediumItalic.woff2?v=3.19") format("woff2"),
url("Inter-MediumItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 500;
font-display: swap;
src: url("Inter-MediumItalic.woff2?v=3.19") format("woff2"), url("Inter-MediumItalic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("Inter-SemiBold.woff2?v=3.19") format("woff2"),
url("Inter-SemiBold.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 600;
font-display: swap;
src: url("Inter-SemiBold.woff2?v=3.19") format("woff2"), url("Inter-SemiBold.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 600;
font-display: swap;
src: url("Inter-SemiBoldItalic.woff2?v=3.19") format("woff2"),
url("Inter-SemiBoldItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 600;
font-display: swap;
src: url("Inter-SemiBoldItalic.woff2?v=3.19") format("woff2"),
url("Inter-SemiBoldItalic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("Inter-Bold.woff2?v=3.19") format("woff2"),
url("Inter-Bold.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 700;
font-display: swap;
src: url("Inter-Bold.woff2?v=3.19") format("woff2"), url("Inter-Bold.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 700;
font-display: swap;
src: url("Inter-BoldItalic.woff2?v=3.19") format("woff2"),
url("Inter-BoldItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 700;
font-display: swap;
src: url("Inter-BoldItalic.woff2?v=3.19") format("woff2"), url("Inter-BoldItalic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 800;
font-display: swap;
src: url("Inter-ExtraBold.woff2?v=3.19") format("woff2"),
url("Inter-ExtraBold.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 800;
font-display: swap;
src: url("Inter-ExtraBold.woff2?v=3.19") format("woff2"), url("Inter-ExtraBold.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 800;
font-display: swap;
src: url("Inter-ExtraBoldItalic.woff2?v=3.19") format("woff2"),
url("Inter-ExtraBoldItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 800;
font-display: swap;
src: url("Inter-ExtraBoldItalic.woff2?v=3.19") format("woff2"),
url("Inter-ExtraBoldItalic.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: normal;
font-weight: 900;
font-display: swap;
src: url("Inter-Black.woff2?v=3.19") format("woff2"),
url("Inter-Black.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: normal;
font-weight: 900;
font-display: swap;
src: url("Inter-Black.woff2?v=3.19") format("woff2"), url("Inter-Black.woff?v=3.19") format("woff");
}
@font-face {
font-family: 'Inter';
font-style: italic;
font-weight: 900;
font-display: swap;
src: url("Inter-BlackItalic.woff2?v=3.19") format("woff2"),
url("Inter-BlackItalic.woff?v=3.19") format("woff");
font-family: "Inter";
font-style: italic;
font-weight: 900;
font-display: swap;
src: url("Inter-BlackItalic.woff2?v=3.19") format("woff2"), url("Inter-BlackItalic.woff?v=3.19") format("woff");
}
/* -------------------------------------------------------
@@ -161,21 +146,20 @@ Usage:
}
*/
@font-face {
font-family: 'Inter var';
font-weight: 100 900;
font-display: swap;
font-style: normal;
src: url("Inter-roman.var.woff2?v=3.19") format("woff2");
font-family: "Inter var";
font-weight: 100 900;
font-display: swap;
font-style: normal;
src: url("Inter-roman.var.woff2?v=3.19") format("woff2");
}
@font-face {
font-family: 'Inter var';
font-weight: 100 900;
font-display: swap;
font-style: italic;
src: url("Inter-italic.var.woff2?v=3.19") format("woff2");
font-family: "Inter var";
font-weight: 100 900;
font-display: swap;
font-style: italic;
src: url("Inter-italic.var.woff2?v=3.19") format("woff2");
}
/* --------------------------------------------------------------------------
[EXPERIMENTAL] Multi-axis, single variable font.
@@ -190,9 +174,9 @@ explicitly, e.g.
*/
@font-face {
font-family: 'Inter var experimental';
font-weight: 100 900;
font-display: swap;
font-style: oblique 0deg 10deg;
src: url("Inter.var.woff2?v=3.19") format("woff2");
font-family: "Inter var experimental";
font-weight: 100 900;
font-display: swap;
font-style: oblique 0deg 10deg;
src: url("Inter.var.woff2?v=3.19") format("woff2");
}

View File

@@ -5,13 +5,16 @@
* hosted on GitHub, https://GitHub.com/Naereen/Nginx-Fancyindex-Theme
*/
@import url('./fonts/inter.css');
@import url("./fonts/inter.css");
* { font-family: 'Inter', sans-serif; }
@supports (font-variation-settings: normal) {
* { font-family: 'Inter var', sans-serif; }
* {
font-family: "Inter", sans-serif;
}
@supports (font-variation-settings: normal) {
* {
font-family: "Inter var", sans-serif;
}
}
* {
margin: 0;
@@ -22,14 +25,14 @@
}
html {
color: #17191C;
color: #17191c;
font-weight: 400;
font-size: 1em;
line-height: 1.6em;
}
body {
background-color: #F4F6FA;
background-color: #f4f6fa;
margin: 0 auto;
padding: 100px 20px 20px;
max-width: 800px;
@@ -52,9 +55,11 @@ a {
text-decoration: underline;
}
a:hover {
color: #0DBD8B;
color: #0dbd8b;
}
a.clear, a.clear:link, a.clear:visited {
a.clear,
a.clear:link,
a.clear:visited {
color: #666;
padding: 2px 0;
font-weight: 400;
@@ -74,7 +79,7 @@ a.clear, a.clear:link, a.clear:visited {
input {
vertical-align: middle;
*overflow: visible;
font-family: 'Open Sans', sans-serif;
font-family: "Open Sans", sans-serif;
font-weight: 300;
display: inline-block;
height: 20px;
@@ -89,20 +94,20 @@ input {
width: 196px;
background-color: #fff;
border: 1px solid #ccc;
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075);
-webkit-transition: border linear .2s,box-shadow linear .2s;
-moz-transition: border linear .2s,box-shadow linear .2s;
-o-transition: border linear .2s,box-shadow linear .2s;
transition: border linear .2s,box-shadow linear .2s;
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
-webkit-transition: border linear 0.2s, box-shadow linear 0.2s;
-moz-transition: border linear 0.2s, box-shadow linear 0.2s;
-o-transition: border linear 0.2s, box-shadow linear 0.2s;
transition: border linear 0.2s, box-shadow linear 0.2s;
}
input:focus {
outline: 0;
border-color: rgba(0,0,0,0.8);
-webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(0,0,0,0.6);
-moz-box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(0,0,0,0.6);
box-shadow: inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(0,0,0,0.6);
border-color: rgba(0, 0, 0, 0.8);
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(0, 0, 0, 0.6);
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(0, 0, 0, 0.6);
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(0, 0, 0, 0.6);
}
input::-moz-focus-inner {
padding: 0;
@@ -128,13 +133,12 @@ tr td:first-of-type {
padding-right: 10px;
}
tr.parent a {
color: #9099A3;
color: #9099a3;
}
th {
text-align: left;
font-size: .75em;
font-size: 0.75em;
padding-right: 20px;
}
th + th {
@@ -157,7 +161,8 @@ td {
-o-transition: background 300ms ease-in;
transition: background 300ms ease-in;
}
td:last-child,th:last-child {
td:last-child,
th:last-child {
text-align: right;
padding-right: 0;
}
@@ -187,11 +192,11 @@ td a {
padding: 0;
list-style: none;
overflow: hidden;
background-color: #FFF;
background-color: #fff;
}
.nav li a {
color: #17191C;
color: #17191c;
display: block;
padding: 20px 20px;
text-decoration: none;
@@ -199,7 +204,7 @@ td a {
.nav li a:hover,
.nav .menu-btn:hover {
color: #0DBD8B;
color: #0dbd8b;
}
.nav .logo {
@@ -216,7 +221,7 @@ td a {
.nav .menu {
clear: both;
max-height: 0;
transition: max-height .2s ease-out;
transition: max-height 0.2s ease-out;
}
/* menu icon */
@@ -237,18 +242,18 @@ td a {
margin-top: 6px;
margin-bottom: 4px;
position: relative;
transition: background .2s ease-out;
transition: background 0.2s ease-out;
width: 18px;
}
.nav .menu-icon .navicon:before,
.nav .menu-icon .navicon:after {
background: #17191C;
content: '';
background: #17191c;
content: "";
display: block;
height: 100%;
position: absolute;
transition: all .2s ease-out;
transition: all 0.2s ease-out;
width: 100%;
}
@@ -303,13 +308,13 @@ td a {
margin-left: 20px;
padding: 12px 20px;
border-radius: 100px;
background-color: #0DBD8B;
color:#FFF;
background-color: #0dbd8b;
color: #fff;
}
.nav .primary:hover {
background-color: #099970;
color:#FFF;
color: #fff;
}
.nav .menu {
@@ -324,10 +329,10 @@ td a {
footer {
margin-top: 40px;
font-size:0.8em;
text-align:center;
font-size: 0.8em;
text-align: center;
}
footer a {
color:#03b381;
color: #03b381;
}

19
scripts/@types/find-npm-prefix.d.ts vendored Normal file
View File

@@ -0,0 +1,19 @@
/*
Copyright 2022 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
declare module "find-npm-prefix" {
export default function findPrefix(dir: string): Promise<string>;
}

20
scripts/@types/node-pre-gyp.d.ts vendored Normal file
View File

@@ -0,0 +1,20 @@
/*
Copyright 2022 New Vector Ltd
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
declare module "node-pre-gyp/lib/util/versioning" {
// eslint-disable-next-line @typescript-eslint/naming-convention
export function get_runtime_abi(runtime: string, version: string): string;
}

View File

@@ -1,18 +1,18 @@
#!/usr/bin/env node
#!/usr/bin/env -S npx ts-node
// copies resources into the lib directory.
const parseArgs = require('minimist');
const chokidar = require('chokidar');
const path = require('path');
const fs = require('fs');
import parseArgs from "minimist";
import * as chokidar from "chokidar";
import * as path from "path";
import * as fs from "fs";
const argv = parseArgs(process.argv.slice(2), {});
const watch = argv.w;
const verbose = argv.v;
function errCheck(err) {
function errCheck(err?: Error): void {
if (err) {
console.error(err.message);
process.exit(1);
@@ -20,20 +20,19 @@ function errCheck(err) {
}
const I18N_BASE_PATH = "src/i18n/strings/";
const INCLUDE_LANGS = fs.readdirSync(I18N_BASE_PATH).filter(fn => fn.endsWith(".json"));
const INCLUDE_LANGS = fs.readdirSync(I18N_BASE_PATH).filter((fn) => fn.endsWith(".json"));
// Ensure lib, lib/i18n and lib/i18n/strings all exist
fs.mkdirSync('lib/i18n/strings', { recursive: true });
fs.mkdirSync("lib/i18n/strings", { recursive: true });
function genLangFile(file, dest) {
let translations = {};
[file].forEach(function(f) {
type Translations = Record<string, Record<string, string> | string>;
function genLangFile(file: string, dest: string): void {
const inTrs: Record<string, string> = {};
[file].forEach(function (f) {
if (fs.existsSync(f)) {
try {
Object.assign(
translations,
JSON.parse(fs.readFileSync(f).toString()),
);
Object.assign(inTrs, JSON.parse(fs.readFileSync(f).toString()));
} catch (e) {
console.error("Failed: " + f, e);
throw e;
@@ -41,8 +40,7 @@ function genLangFile(file, dest) {
}
});
translations = weblateToCounterpart(translations);
const translations = weblateToCounterpart(inTrs);
const json = JSON.stringify(translations, null, 4);
const filename = path.basename(file);
@@ -66,11 +64,11 @@ function genLangFile(file, dest) {
* "other": "%(count)s badgers"
* }
*/
function weblateToCounterpart(inTrs) {
const outTrs = {};
function weblateToCounterpart(inTrs: Record<string, string>): Translations {
const outTrs: Translations = {};
for (const key of Object.keys(inTrs)) {
const keyParts = key.split('|', 2);
const keyParts = key.split("|", 2);
if (keyParts.length === 2) {
let obj = outTrs[keyParts[0]];
if (obj === undefined) {
@@ -79,7 +77,7 @@ function weblateToCounterpart(inTrs) {
// This is a transitional edge case if a string went from singular to pluralised and both still remain
// in the translation json file. Use the singular translation as `other` and merge pluralisation atop.
obj = outTrs[keyParts[0]] = {
"other": inTrs[key],
other: inTrs[key],
};
console.warn("Found entry in i18n file in both singular and pluralised form", keyParts[0]);
}
@@ -96,12 +94,12 @@ function weblateToCounterpart(inTrs) {
watch the input files for a given language,
regenerate the file, and regenerating languages.json with the new filename
*/
function watchLanguage(file, dest) {
function watchLanguage(file: string, dest: string): void {
// XXX: Use a debounce because for some reason if we read the language
// file immediately after the FS event is received, the file contents
// appears empty. Possibly https://github.com/nodejs/node/issues/6112
let makeLangDebouncer;
const makeLang = () => {
let makeLangDebouncer: NodeJS.Timeout | undefined;
const makeLang = (): void => {
if (makeLangDebouncer) {
clearTimeout(makeLangDebouncer);
}
@@ -110,18 +108,15 @@ function watchLanguage(file, dest) {
}, 500);
};
chokidar.watch(file)
.on('add', makeLang)
.on('change', makeLang)
.on('error', errCheck);
chokidar.watch(file).on("add", makeLang).on("change", makeLang).on("error", errCheck);
}
// language resources
const I18N_DEST = "lib/i18n/strings/";
INCLUDE_LANGS.forEach((file) => {
INCLUDE_LANGS.forEach((file): void => {
genLangFile(I18N_BASE_PATH + file, I18N_DEST);
}, {});
if (watch) {
INCLUDE_LANGS.forEach(file => watchLanguage(I18N_BASE_PATH + file, I18N_DEST));
INCLUDE_LANGS.forEach((file) => watchLanguage(I18N_BASE_PATH + file, I18N_DEST));
}

View File

@@ -1,7 +1,7 @@
const fsProm = require('fs').promises;
const path = require('path');
const fsProm = require("fs").promises;
const path = require("path");
exports.default = async function(context) {
exports.default = async function (context) {
const { electronPlatformName, appOutDir } = context;
// Squirrel windows will try to relaunch the app using an executable of the same name as
@@ -9,7 +9,7 @@ exports.default = async function(context) {
// We add a fake Riot.exe that it can run which runs the real one.
// This also gets signed automatically, presumably because electron-build just looks for all
// exe files and signs them all...
if (electronPlatformName === 'win32') {
await fsProm.copyFile('build/rebrand_stub/rebrand_stub.exe', path.join(appOutDir, "Riot.exe"));
if (electronPlatformName === "win32") {
await fsProm.copyFile("build/rebrand_stub/rebrand_stub.exe", path.join(appOutDir, "Riot.exe"));
}
};

View File

@@ -1,32 +0,0 @@
const { notarize } = require('@electron/notarize');
let warned = false;
exports.default = async function(context) {
const { electronPlatformName, appOutDir } = context;
const appId = context.packager.info.appInfo.id;
if (electronPlatformName === 'darwin') {
const appName = context.packager.appInfo.productFilename;
const keychainProfile = process.env.NOTARIZE_KEYCHAIN_PROFILE;
if (keychainProfile === undefined) {
if (!warned) {
console.log("*****************************************");
console.log("* NOTARIZE_KEYCHAIN_PROFILE is not set. *");
console.log("* This build will NOT be notarised. *");
console.log("*****************************************");
warned = true;
}
return;
}
console.log("Notarising macOS app. This may be some time.");
return await notarize({
tool: "notarytool",
appBundleId: appId,
appPath: `${appOutDir}/${appName}.app`,
keychainProfile,
keychain: process.env.NOTARIZE_KEYCHAIN,
});
}
};

View File

@@ -1,78 +0,0 @@
const { execFile } = require('child_process');
// Loosely based on computeSignToolArgs from app-builder-lib/src/codeSign/windowsCodeSign.ts
function computeSignToolArgs(options, keyContainer) {
const args = [];
if (process.env.ELECTRON_BUILDER_OFFLINE !== "true") {
const timestampingServiceUrl = options.options.timeStampServer || "http://timestamp.digicert.com";
args.push(
options.isNest || options.hash === "sha256" ? "/tr" : "/t",
options.isNest || options.hash === "sha256" ? (
options.options.rfc3161TimeStampServer || "http://timestamp.comodoca.com/rfc3161"
) : timestampingServiceUrl,
);
}
args.push('/kc', keyContainer);
// To use the hardware token (this should probably be less hardcoded)
args.push('/csp', 'eToken Base Cryptographic Provider');
// The certificate file. Somehow this appears to be the only way to specify
// the cert that works. If you specify the subject name or hash, it will
// say it can't associate the private key to the certificate.
// TODO: Find a way to pass this through from the electron-builder config
// so we don't have to hard-code this here
// fwiw https://stackoverflow.com/questions/17927895/automate-extended-validation-ev-code-signing
// is about the most useful resource on automating code signing...
args.push('/f', 'element.io\\New_Vector_Ltd.pem');
if (options.hash !== "sha1") {
args.push("/fd", options.hash);
if (process.env.ELECTRON_BUILDER_OFFLINE !== "true") {
args.push("/td", "sha256");
}
}
// msi does not support dual-signing
if (options.isNest) {
args.push("/as");
}
// https://github.com/electron-userland/electron-builder/issues/2875#issuecomment-387233610
args.push("/debug");
// must be last argument
args.push(options.path);
return args;
}
let warned = false;
exports.default = async function(options) {
const keyContainer = process.env.SIGNING_KEY_CONTAINER;
if (keyContainer === undefined) {
if (!warned) {
console.warn(
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n" +
"! Skipping Windows signing. !\n" +
"! SIGNING_KEY_CONTAINER not defined. !\n" +
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
);
warned = true;
}
return;
}
return new Promise((resolve, reject) => {
const args = ['sign'].concat(computeSignToolArgs(options, keyContainer));
execFile('signtool', args, {}, (error, stdout) => {
if (error) {
console.error("signtool failed with code " + error);
reject("signtool failed with code " + error);
console.log(stdout);
} else {
resolve();
}
});
});
};

View File

@@ -1,43 +1,41 @@
#!/usr/bin/env node
#!/usr/bin/env -S npx ts-node --resolveJsonModule
const process = require('process');
const path = require('path');
const fs = require('fs');
const fsPromises = require('fs').promises;
const childProcess = require('child_process');
const tar = require('tar');
const asar = require('asar');
const needle = require('needle');
import * as path from "path";
import { createWriteStream, promises as fs } from "fs";
import * as childProcess from "child_process";
import tar from "tar";
import * as asar from "@electron/asar";
import fetch from "node-fetch";
import { promises as stream } from "stream";
const riotDesktopPackageJson = require('../package.json');
const { setPackageVersion } = require('./set-version.js');
import riotDesktopPackageJson from "../package.json";
import { setPackageVersion } from "./set-version";
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 DEVELOP_TGZ_URL = "https://develop.element.io/develop.tar.gz";
const ASAR_PATH = 'webapp.asar';
const ASAR_PATH = "webapp.asar";
async function downloadToFile(url, filename) {
async function downloadToFile(url: string, filename: string): Promise<void> {
console.log("Downloading " + url + "...");
try {
await needle('get', url, null,
{
follow_max: 5,
output: filename,
},
);
const resp = await fetch(url);
if (!resp.ok) throw new Error(`unexpected response ${resp.statusText}`);
if (!resp.body) throw new Error(`unexpected response has no body ${resp.statusText}`);
await stream.pipeline(resp.body, createWriteStream(filename));
} catch (e) {
console.error(e);
try {
await fsPromises.unlink(filename);
await fs.unlink(filename);
} catch (_) {}
throw e;
}
}
async function verifyFile(filename) {
return new Promise((resolve, reject) => {
childProcess.execFile('gpg', ['--verify', filename + '.asc', filename], (error) => {
async function verifyFile(filename: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
childProcess.execFile("gpg", ["--verify", filename + ".asc", filename], (error) => {
if (error) {
reject(error);
} else {
@@ -47,35 +45,35 @@ async function verifyFile(filename) {
});
}
async function main() {
async function main(): Promise<number | undefined> {
let verify = true;
let importkey = false;
let pkgDir = 'packages';
let deployDir = 'deploys';
let cfgDir;
let targetVersion;
let filename;
let url;
let pkgDir = "packages";
let deployDir = "deploys";
let cfgDir: string | undefined;
let targetVersion: string | undefined;
let filename: string | undefined;
let url: string | undefined;
let setVersion = false;
while (process.argv.length > 2) {
switch (process.argv[2]) {
case '--noverify':
case "--noverify":
verify = false;
break;
case '--importkey':
case "--importkey":
importkey = true;
break;
case '--packages':
case "--packages":
process.argv.shift();
pkgDir = process.argv[2];
break;
case '--deploys':
case "--deploys":
process.argv.shift();
deployDir = process.argv[2];
break;
case '--cfgdir':
case '-d':
case "--cfgdir":
case "-d":
process.argv.shift();
cfgDir = process.argv[2];
break;
@@ -86,13 +84,13 @@ async function main() {
}
if (targetVersion === undefined) {
targetVersion = 'v' + riotDesktopPackageJson.version;
} else if (targetVersion !== 'develop') {
targetVersion = "v" + riotDesktopPackageJson.version;
} else if (targetVersion !== "develop") {
setVersion = true; // version was specified
}
if (targetVersion === 'develop') {
filename = 'develop.tar.gz';
if (targetVersion === "develop") {
filename = "develop.tar.gz";
url = DEVELOP_TGZ_URL;
verify = false; // develop builds aren't signed
} else if (targetVersion.includes("://")) {
@@ -101,11 +99,11 @@ async function main() {
verify = false; // manually verified
} else {
filename = `element-${targetVersion}.tar.gz`;
url = PACKAGE_URL_PREFIX + targetVersion + '/' + filename;
url = PACKAGE_URL_PREFIX + targetVersion + "/" + filename;
}
const haveGpg = await new Promise((resolve) => {
childProcess.execFile('gpg', ['--version'], (error) => {
const haveGpg = await new Promise<boolean>((resolve) => {
childProcess.execFile("gpg", ["--version"], (error) => {
resolve(!error);
});
});
@@ -116,8 +114,8 @@ async function main() {
return 1;
}
await new Promise((resolve) => {
const gpgProc = childProcess.execFile('gpg', ['--import'], (error) => {
await new Promise<boolean>((resolve) => {
const gpgProc = childProcess.execFile("gpg", ["--import"], (error) => {
if (error) {
console.log("Failed to import key", error);
} else {
@@ -125,7 +123,9 @@ async function main() {
}
resolve(!error);
});
needle.get(PUB_KEY_URL).pipe(gpgProc.stdin);
fetch(PUB_KEY_URL).then((resp) => {
stream.pipeline(resp.body, gpgProc.stdin!);
});
});
return 0;
}
@@ -143,18 +143,17 @@ async function main() {
}
let haveDeploy = false;
let expectedDeployDir = path.join(deployDir, path.basename(filename).replace(/\.tar\.gz/, ''));
let expectedDeployDir = path.join(deployDir, path.basename(filename).replace(/\.tar\.gz/, ""));
try {
await fs.opendir(expectedDeployDir);
console.log(expectedDeployDir + "already exists");
haveDeploy = true;
} catch (e) {
}
} catch (e) {}
if (!haveDeploy) {
const outPath = path.join(pkgDir, filename);
try {
await fsPromises.stat(outPath);
await fs.stat(outPath);
console.log("Already have " + filename + ": not redownloading");
} catch (e) {
try {
@@ -167,11 +166,11 @@ async function main() {
if (verify) {
try {
await fsPromises.stat(outPath+'.asc');
await fs.stat(outPath + ".asc");
console.log("Already have " + filename + ".asc: not redownloading");
} catch (e) {
try {
await downloadToFile(url + '.asc', outPath + '.asc');
await downloadToFile(url + ".asc", outPath + ".asc");
} catch (e) {
console.log("Failed to download " + url, e);
return 1;
@@ -192,7 +191,7 @@ async function main() {
await tar.x({
file: outPath,
cwd: deployDir,
onentry: entry => {
onentry: (entry) => {
// Find the appropriate extraction path, only needed for `develop` where the dir name is unknown
if (entry.type === "Directory" && !path.join(deployDir, entry.path).startsWith(expectedDeployDir)) {
expectedDeployDir = path.join(deployDir, entry.path);
@@ -202,17 +201,16 @@ async function main() {
}
try {
await fsPromises.stat(ASAR_PATH);
await fs.stat(ASAR_PATH);
console.log(ASAR_PATH + " already present: removing");
await fsPromises.unlink(ASAR_PATH);
} catch (e) {
}
await fs.unlink(ASAR_PATH);
} catch (e) {}
if (cfgDir.length) {
const configJsonSource = path.join(cfgDir, 'config.json');
const configJsonDest = path.join(expectedDeployDir, 'config.json');
console.log(configJsonSource + ' -> ' + configJsonDest);
await fsPromises.copyFile(configJsonSource, configJsonDest);
const configJsonSource = path.join(cfgDir, "config.json");
const configJsonDest = path.join(expectedDeployDir, "config.json");
console.log(configJsonSource + " -> " + configJsonDest);
await fs.copyFile(configJsonSource, configJsonDest);
} else {
console.log("Skipping config file");
}
@@ -221,7 +219,7 @@ async function main() {
await asar.createPackage(expectedDeployDir, ASAR_PATH);
if (setVersion) {
const semVer = fs.readFileSync(path.join(expectedDeployDir, "version"), "utf-8").trim();
const semVer = (await fs.readFile(path.join(expectedDeployDir, "version"), "utf-8")).trim();
console.log("Updating version to " + semVer);
await setPackageVersion(semVer);
}
@@ -229,9 +227,11 @@ async function main() {
console.log("Done!");
}
main().then((ret) => {
process.exit(ret);
}).catch(e => {
console.error(e);
process.exit(1);
});
main()
.then((ret) => {
process.exit(ret);
})
.catch((e) => {
console.error(e);
process.exit(1);
});

View File

@@ -0,0 +1,128 @@
#!/usr/bin/env -S npx ts-node
/**
* Script to generate electron-builder.json config files for builds which don't match package.json, e.g. nightlies
* This script has different outputs depending on your os platform.
*
* On Windows:
* Prefixes the nightly version with `0.0.1-nightly.` as it breaks if it is not semver
*
* On macOS:
* Passes --notarytool-team-id to build.mac.notarize.notarize if specified
*
* On Linux:
* Replaces spaces in the product name with dashes as spaces in paths can cause issues
* Passes --deb-custom-control to build.deb.fpm if specified
*/
import parseArgs from "minimist";
import fsProm from "fs/promises";
import * as os from "os";
import { Configuration } from "app-builder-lib";
const ELECTRON_BUILDER_CFG_FILE = "electron-builder.json";
const NIGHTLY_APP_ID = "im.riot.nightly";
const NIGHTLY_APP_NAME = "element-desktop-nightly";
const argv = parseArgs<{
"nightly"?: string;
"signtool-thumbprint"?: string;
"signtool-subject-name"?: string;
"notarytool-team-id"?: string;
"deb-custom-control"?: string;
"deb-changelog"?: string;
}>(process.argv.slice(2), {
string: [
"nightly",
"deb-custom-control",
"deb-changelog",
"signtool-thumbprint",
"signtool-subject-name",
"notarytool-team-id",
],
});
type DeepWriteable<T> = { -readonly [P in keyof T]: DeepWriteable<T[P]> };
interface PackageBuild extends DeepWriteable<Omit<Configuration, "extraMetadata">> {
extraMetadata?: {
productName?: string;
name?: string;
version?: string;
};
}
interface Package {
build: PackageBuild;
productName: string;
}
async function main(): Promise<number | void> {
// Electron builder doesn't overlay with the config in package.json, so load it here
const pkg: Package = JSON.parse(await fsProm.readFile("package.json", "utf8"));
const cfg: PackageBuild = {
...pkg.build,
extraMetadata: {
productName: pkg.productName,
},
};
if (argv.nightly) {
cfg.appId = NIGHTLY_APP_ID;
cfg.extraMetadata!.productName += " Nightly";
cfg.extraMetadata!.name = NIGHTLY_APP_NAME;
let version = argv.nightly;
if (os.platform() === "win32") {
// The windows packager relies on parsing this as semver, so we have to make it look like one.
// This will give our update packages really stupid names, but we probably can't change that either
// because squirrel windows parses them for the version too. We don't really care: nobody sees them.
// We just give the installer a static name, so you'll just see this in the 'about' dialog.
// Turns out if you use 0.0.0 here it makes Squirrel windows crash, so we use 0.0.1.
version = "0.0.1-nightly." + version;
}
cfg.extraMetadata!.version = version;
}
if (argv["signtool-thumbprint"] && argv["signtool-subject-name"]) {
cfg.win!.signingHashAlgorithms = ["sha256"];
cfg.win!.certificateSubjectName = argv["signtool-subject-name"];
cfg.win!.certificateSha1 = argv["signtool-thumbprint"];
}
if (argv["notarytool-team-id"]) {
cfg.mac!.notarize = {
teamId: argv["notarytool-team-id"],
};
}
if (os.platform() === "linux") {
// Electron crashes on debian if there's a space in the path.
// https://github.com/vector-im/element-web/issues/13171
cfg.extraMetadata!.productName = cfg.extraMetadata!.productName!.replace(/ /g, "-");
cfg.deb = {
fpm: [],
};
if (argv["deb-custom-control"]) {
cfg.deb.fpm!.push(`--deb-custom-control=${argv["deb-custom-control"]}`);
}
if (argv["deb-changelog"]) {
cfg.deb.fpm!.push(`--deb-changelog=${argv["deb-changelog"]}`);
}
}
await fsProm.writeFile(ELECTRON_BUILDER_CFG_FILE, JSON.stringify(cfg, null, 4));
}
main()
.then((ret) => {
process.exit(ret!);
})
.catch((e) => {
console.error(e);
process.exit(1);
});

View File

@@ -0,0 +1,41 @@
#!/usr/bin/env -S npx ts-node
/**
* Script to generate incremental Nightly build versions, based on the latest Nightly build version of that kind.
* The version format is YYYYMMDDNN where NN is in case we need to do multiple versions in a day.
*
* NB. on windows, squirrel will try to parse the version number parts, including this string, into 32-bit integers,
* which is fine as long as we only add two digits to the end...
*/
import parseArgs from "minimist";
const argv = parseArgs<{
latest?: string;
}>(process.argv.slice(2), {
string: ["latest"],
});
function parseVersion(version: string): [Date, number] {
const year = parseInt(version.slice(0, 4), 10);
const month = parseInt(version.slice(4, 6), 10);
const day = parseInt(version.slice(6, 8), 10);
const num = parseInt(version.slice(8, 10), 10);
return [new Date(year, month - 1, day), num];
}
const [latestDate, latestNum] = argv.latest ? parseVersion(argv.latest) : [];
const now = new Date();
const month = (now.getMonth() + 1).toString().padStart(2, "0");
const date = now.getDate().toString().padStart(2, "0");
let buildNum = 1;
if (latestDate && new Date(latestDate).getDate().toString().padStart(2, "0") === date) {
buildNum = latestNum! + 1;
}
if (buildNum > 99) {
throw new Error("Maximum number of Nightlies exceeded on this day.");
}
console.log(now.getFullYear() + month + date + buildNum.toString().padStart(2, "0"));

View File

@@ -8,6 +8,7 @@ const HIDDEN_FILES = [
".DS_Store",
"index.html",
"/fonts/",
"/tools/",
"/nginx-theme/",
".~tmp~/",
"msi/",
@@ -29,7 +30,7 @@ const client = new S3Client({
},
});
const templateLayout = (content: string) => `
const templateLayout = (content: string): string => `
<!DOCTYPE html>
<html>
<head>
@@ -80,25 +81,25 @@ const templateLayout = (content: string) => `
*
* @return Formatted string.
*/
function humanFileSize(bytes: number, si = false, dp = 1) {
function humanFileSize(bytes: number, si = false, dp = 1): string {
const thresh = si ? 1000 : 1024;
if (Math.abs(bytes) < thresh) {
return bytes + ' B';
return bytes + " B";
}
const units = si
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
: ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
let u = -1;
const r = 10**dp;
const r = 10 ** dp;
do {
bytes /= thresh;
++u;
} while (Math.round(Math.abs(bytes) * r) / r >= thresh && u < units.length - 1);
return bytes.toFixed(dp) + ' ' + units[u];
return bytes.toFixed(dp) + " " + units[u];
}
const dateTimeOptions: Intl.DateTimeFormatOptions = {
@@ -122,7 +123,8 @@ function indexLayout(prefix: string, files: _Object[], dirs: string[]): string {
}
for (const file of files) {
if (!file.Key ||
if (
!file.Key ||
HIDDEN_FILES.includes(`/${file.Key}`) ||
HIDDEN_FILES.includes(file.Key.slice(file.Key.lastIndexOf("/") + 1))
) {
@@ -143,11 +145,15 @@ function indexLayout(prefix: string, files: _Object[], dirs: string[]): string {
</tr>
</thead>
<tbody>
${rows.map(([link, name, size, date]) => `<tr>
${rows
.map(
([link, name, size, date]) => `<tr>
<td class="link"><a href="${link}">${name}</a></td>
<td class="size">${size ? humanFileSize(size) : "-"}</td>
<td class="date">${date?.toLocaleString("en-GB", dateTimeOptions) ?? "-"}</td>
</tr>`).join("")}
</tr>`,
)
.join("")}
</tbody>
</table>
`);
@@ -166,17 +172,20 @@ async function generateIndex(Prefix: string): Promise<{
const listResponse = await client.send(command);
const files = listResponse.Contents ?? [];
const dirs = listResponse.CommonPrefixes
?.map(p => p.Prefix?.slice(Prefix.length).split("/", 2)[0])
.filter(Boolean) as string[] ?? [];
const dirs =
(listResponse.CommonPrefixes?.map((p) => p.Prefix?.slice(Prefix.length).split("/", 2)[0]).filter(
Boolean,
) as string[]) ?? [];
const Body = indexLayout(Prefix, files, dirs);
await client.send(new PutObjectCommand({
Body,
Bucket,
ContentType: "text/html",
Key: Prefix + "index.html",
}));
await client.send(
new PutObjectCommand({
Body,
Bucket,
ContentType: "text/html",
Key: Prefix + "index.html",
}),
);
return { files, dirs };
}

View File

@@ -1,40 +1,40 @@
hak
===
# 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).
- 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
=======
# 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
=====
# 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.
- 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
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
@@ -49,33 +49,34 @@ This also means that the dependencies cannot be listed in `dependencies` or
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
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
* fetchDeps - Fetch & extract any native dependencies required to build the module.
* 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.
# 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
- fetchDeps - Fetch & extract any native dependencies required to build the module.
- 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
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
============
# 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
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

@@ -14,40 +14,14 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import path from 'path';
import rimraf from 'rimraf';
import path from "path";
import rimraf from "rimraf";
import { DependencyInfo } from './dep';
import HakEnv from './hakEnv';
import { DependencyInfo } from "./dep";
import HakEnv from "./hakEnv";
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 {
resolve();
}
});
});
await new Promise<void>((resolve, reject) => {
rimraf(path.join(hakEnv.dotHakDir, 'links', moduleInfo.name), (err: Error) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
await new Promise<void>((resolve, reject) => {
rimraf(path.join(hakEnv.projectRoot, 'node_modules', moduleInfo.name), (err: Error) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
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

@@ -14,15 +14,15 @@ 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 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';
import HakEnv from "./hakEnv";
import { DependencyInfo } from "./dep";
export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
if (moduleInfo.cfg.prune) {
@@ -33,11 +33,7 @@ export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo):
try {
await mkdirp(moduleInfo.moduleOutDir);
process.chdir(moduleInfo.moduleOutDir);
await new Promise<void>((resolve, reject) => {
rimraf(moduleInfo.cfg.prune, {}, err => {
err ? reject(err) : resolve();
});
});
await rimraf(moduleInfo.cfg.prune);
} finally {
process.chdir(oldCwd);
}
@@ -47,47 +43,35 @@ export default async function copy(hakEnv: HakEnv, moduleInfo: DependencyInfo):
// 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);
});
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.",
"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 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();
}
},
);
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,
);
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);

View File

@@ -28,5 +28,5 @@ export interface DependencyInfo {
moduleOutDir: string;
nodeModuleBinDir: string;
depPrefix: string;
scripts: Record<string, (hakEnv: HakEnv, moduleInfo: DependencyInfo) => Promise<void> >;
scripts: Record<string, (hakEnv: HakEnv, moduleInfo: DependencyInfo) => Promise<void>>;
}

View File

@@ -14,12 +14,12 @@ 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 fsProm from "fs/promises";
import childProcess from "child_process";
import pacote from "pacote";
import HakEnv from './hakEnv';
import { DependencyInfo } from './dep';
import HakEnv from "./hakEnv";
import { DependencyInfo } from "./dep";
export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
let haveModuleBuildDir;
@@ -41,15 +41,11 @@ export default async function fetch(hakEnv: HakEnv, moduleInfo: DependencyInfo):
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 => {
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();
});
});

View File

@@ -14,10 +14,10 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import mkdirp from 'mkdirp';
import mkdirp from "mkdirp";
import { DependencyInfo } from './dep';
import HakEnv from './hakEnv';
import { DependencyInfo } from "./dep";
import HakEnv from "./hakEnv";
export default async function fetchDeps(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
await mkdirp(moduleInfo.moduleDotHakDir);

View File

@@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import path from 'path';
import os from '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";
import { Arch, Target, TARGETS, getHost, isHostId, TargetId } from './target';
import { Arch, Target, TARGETS, getHost, isHostId, TargetId } from "./target";
async function getRuntime(projectRoot: string): Promise<string> {
const electronVersion = await getElectronVersion(projectRoot);
return electronVersion ? 'electron' : 'node-webkit';
return electronVersion ? "electron" : "node-webkit";
}
async function getRuntimeVersion(projectRoot: string): Promise<string> {
@@ -37,38 +37,32 @@ async function getRuntimeVersion(projectRoot: string): Promise<string> {
export default class HakEnv {
public readonly target: Target;
public runtime: string;
public runtimeVersion: string;
public runtime?: string;
public runtimeVersion?: string;
public dotHakDir: string;
constructor(public readonly projectRoot: string, targetId: TargetId | null) {
if (targetId) {
this.target = TARGETS[targetId];
} else {
this.target = getHost();
}
public constructor(public readonly projectRoot: string, targetId: TargetId | null) {
const target = targetId ? TARGETS[targetId] : getHost();
if (!this.target) {
if (!target) {
throw new Error(`Unknown target ${targetId}!`);
}
this.dotHakDir = path.join(this.projectRoot, '.hak');
this.target = target;
this.dotHakDir = path.join(this.projectRoot, ".hak");
}
public async init() {
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,
);
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;
return this.getRuntimeAbi() + "-" + this.target.platform + "-" + this.target.arch;
}
public getTargetId(): TargetId {
@@ -76,15 +70,15 @@ export default class HakEnv {
}
public isWin(): boolean {
return this.target.platform === 'win32';
return this.target.platform === "win32";
}
public isMac(): boolean {
return this.target.platform === 'darwin';
return this.target.platform === "darwin";
}
public isLinux(): boolean {
return this.target.platform === 'linux';
return this.target.platform === "linux";
}
public getTargetArch(): Arch {
@@ -95,11 +89,11 @@ export default class HakEnv {
return isHostId(this.target.id);
}
public makeGypEnv(): Record<string, string> {
public makeGypEnv(): Record<string, string | undefined> {
return Object.assign({}, process.env, {
npm_config_arch: this.target.arch,
npm_config_target_arch: this.target.arch,
npm_config_disturl: 'https://electronjs.org/headers',
npm_config_disturl: "https://electronjs.org/headers",
npm_config_runtime: this.runtime,
npm_config_target: this.runtimeVersion,
npm_config_build_from_source: true,
@@ -107,12 +101,8 @@ export default class HakEnv {
});
}
public getNodeModuleBin(name: string): string {
return path.join(this.projectRoot, 'node_modules', '.bin', name);
}
public wantsStaticSqlCipherUnix(): boolean {
return this.isMac() || process.env.SQLCIPHER_STATIC == '1';
return this.isMac() || process.env.SQLCIPHER_STATIC == "1";
}
public wantsStaticSqlCipher(): boolean {

View File

@@ -14,44 +14,29 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import path from 'path';
import findNpmPrefix from 'find-npm-prefix';
import path from "path";
import findNpmPrefix from "find-npm-prefix";
import HakEnv from './hakEnv';
import { TargetId } from './target';
import { DependencyInfo } from './dep';
import HakEnv from "./hakEnv";
import { TargetId } from "./target";
import { DependencyInfo } from "./dep";
const GENERALCOMMANDS = [
'target',
];
const GENERALCOMMANDS = ["target"];
// These can only be run on specific modules
const MODULECOMMANDS = [
'check',
'fetch',
'link',
'fetchDeps',
'build',
'copy',
'clean',
];
const MODULECOMMANDS = ["check", "fetch", "link", "fetchDeps", "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 = {
'fetchandbuild': ['check', 'fetch', 'fetchDeps', 'build'],
'copyandlink': ['copy', 'link'],
const METACOMMANDS: Record<string, string[]> = {
fetchandbuild: ["check", "fetch", "fetchDeps", "build"],
copyandlink: ["copy", "link"],
};
// Scripts valid in a hak.json 'scripts' section
const HAKSCRIPTS = [
'check',
'fetch',
'fetchDeps',
'build',
];
const HAKSCRIPTS = ["check", "fetch", "fetchDeps", "build"];
async function main() {
async function main(): Promise<void> {
const prefix = await findNpmPrefix(process.cwd());
let packageJson;
try {
@@ -65,11 +50,12 @@ async function main() {
// Apply `--target <target>` option if specified
// 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');
for (;;) {
// eslint-disable-line no-constant-condition
const targetIndex = process.argv.indexOf("--target");
if (targetIndex === -1) break;
if ((targetIndex + 1) >= process.argv.length) {
if (targetIndex + 1 >= process.argv.length) {
console.error("--target option specified without a target");
process.exit(1);
}
@@ -77,7 +63,7 @@ async function main() {
targetIds.push(process.argv.splice(targetIndex, 2)[1] as TargetId);
}
const hakEnvs = targetIds.map(tid => new HakEnv(prefix, tid));
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();
@@ -89,7 +75,7 @@ async function main() {
const hakDepsCfg = packageJson.hakDependencies || {};
for (const dep of Object.keys(hakDepsCfg)) {
const hakJsonPath = path.join(prefix, 'hak', dep, 'hak.json');
const hakJsonPath = path.join(prefix, "hak", dep, "hak.json");
let hakJson: Record<string, any>;
try {
hakJson = await require(hakJsonPath);
@@ -102,20 +88,20 @@ async function main() {
name: dep,
version: hakDepsCfg[dep],
cfg: hakJson,
moduleHakDir: path.join(prefix, 'hak', dep),
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'),
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 && hakJson.scripts[s]) {
const scriptModule = await import(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 {
@@ -127,14 +113,14 @@ async function main() {
let cmds: string[];
if (process.argv.length < 3) {
cmds = ['check', 'fetch', 'fetchDeps', 'build', 'copy', 'link'];
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))) {
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;
@@ -145,7 +131,7 @@ async function main() {
for (const cmd of cmds) {
if (GENERALCOMMANDS.includes(cmd)) {
if (cmd === 'target') {
if (cmd === "target") {
console.log(hakEnv.getNodeTriple());
}
return;
@@ -160,15 +146,12 @@ async function main() {
process.exit(1);
}
const cmdFunc = (await import('./' + cmd)).default;
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?",
);
console.log("Module " + mod + " not found - is it in hakDependencies " + "in your package.json?");
process.exit(1);
}
console.log("hak " + cmd + ": " + mod);
@@ -177,7 +160,7 @@ async function main() {
}
}
main().catch(err => {
main().catch((err) => {
console.error(err);
process.exit(1);
});

View File

@@ -14,16 +14,16 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import path from 'path';
import os from 'os';
import fsProm from 'fs/promises';
import childProcess from 'child_process';
import path from "path";
import os from "os";
import fsProm from "fs/promises";
import childProcess from "child_process";
import HakEnv from './hakEnv';
import { DependencyInfo } from './dep';
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');
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
@@ -43,28 +43,28 @@ export default async function link(hakEnv: HakEnv, moduleInfo: DependencyInfo):
// (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,
"--link-folder " + JSON.stringify(path.join(hakEnv.dotHakDir, "links")) + os.EOL,
);
}
const yarnCmd = 'yarn' + (hakEnv.isWin() ? '.cmd' : '');
const yarnCmd = "yarn" + (hakEnv.isWin() ? ".cmd" : "");
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(yarnCmd, ['link'], {
const proc = childProcess.spawn(yarnCmd, ["link"], {
cwd: moduleInfo.moduleOutDir,
stdio: 'inherit',
stdio: "inherit",
});
proc.on('exit', code => {
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});
await new Promise<void>((resolve, reject) => {
const proc = childProcess.spawn(yarnCmd, ['link', moduleInfo.name], {
const proc = childProcess.spawn(yarnCmd, ["link", moduleInfo.name], {
cwd: hakEnv.projectRoot,
stdio: 'inherit',
stdio: "inherit",
});
proc.on('exit', code => {
proc.on("exit", (code) => {
code ? reject(code) : resolve();
});
});

View File

@@ -20,29 +20,30 @@ import { GLIBC, MUSL, family as processLibC } from "detect-libc";
// 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' |
'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';
| "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-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' | 'linux' | 'win32';
export type Platform = "darwin" | "linux" | "win32";
// Values are expected to match those used in `process.arch`.
export type Arch = 'arm64' | 'ia32' | 'x64' | 'ppc64' | 'universal';
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 VcVarsArch = "amd64" | "arm64" | "x86";
export type Target = {
id: TargetId;
@@ -51,140 +52,143 @@ export type Target = {
};
export type WindowsTarget = Target & {
platform: 'win32';
platform: "win32";
vcVarsArch: VcVarsArch;
};
export type LinuxTarget = Target & {
platform: 'linux';
platform: "linux";
libC: typeof processLibC;
};
export type UniversalTarget = Target & {
arch: 'universal';
arch: "universal";
subtargets: Target[];
};
const aarch64AppleDarwin: Target = {
id: 'aarch64-apple-darwin',
platform: 'darwin',
arch: 'arm64',
id: "aarch64-apple-darwin",
platform: "darwin",
arch: "arm64",
};
const x8664AppleDarwin: Target = {
id: 'x86_64-apple-darwin',
platform: 'darwin',
arch: 'x64',
id: "x86_64-apple-darwin",
platform: "darwin",
arch: "x64",
};
const universalAppleDarwin: UniversalTarget = {
id: 'universal-apple-darwin',
platform: 'darwin',
arch: 'universal',
subtargets: [
aarch64AppleDarwin,
x8664AppleDarwin,
],
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',
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',
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 x8664UnknownLinuxGnu: LinuxTarget = {
id: 'x86_64-unknown-linux-gnu',
platform: 'linux',
arch: 'x64',
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',
id: "x86_64-unknown-linux-musl",
platform: "linux",
arch: "x64",
libC: MUSL,
};
const i686UnknownLinuxGnu: LinuxTarget = {
id: 'i686-unknown-linux-gnu',
platform: 'linux',
arch: 'ia32',
id: "i686-unknown-linux-gnu",
platform: "linux",
arch: "ia32",
libC: GLIBC,
};
const i686UnknownLinuxMusl: LinuxTarget = {
id: 'i686-unknown-linux-musl',
platform: 'linux',
arch: 'ia32',
id: "i686-unknown-linux-musl",
platform: "linux",
arch: "ia32",
libC: MUSL,
};
const aarch64UnknownLinuxGnu: LinuxTarget = {
id: 'aarch64-unknown-linux-gnu',
platform: 'linux',
arch: 'arm64',
id: "aarch64-unknown-linux-gnu",
platform: "linux",
arch: "arm64",
libC: GLIBC,
};
const aarch64UnknownLinuxMusl: LinuxTarget = {
id: 'aarch64-unknown-linux-musl',
platform: 'linux',
arch: 'arm64',
id: "aarch64-unknown-linux-musl",
platform: "linux",
arch: "arm64",
libC: MUSL,
};
const powerpc64leUnknownLinuxGnu: LinuxTarget = {
id: 'powerpc64le-unknown-linux-gnu',
platform: 'linux',
arch: 'ppc64',
id: "powerpc64le-unknown-linux-gnu",
platform: "linux",
arch: "ppc64",
libC: GLIBC,
};
const powerpc64leUnknownLinuxMusl: LinuxTarget = {
id: 'powerpc64le-unknown-linux-musl',
platform: 'linux',
arch: 'ppc64',
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,
"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,
"i686-pc-windows-msvc": i686PcWindowsMsvc,
"x86_64-pc-windows-msvc": x8664PcWindowsMsvc,
"aarch64-pc-windows-msvc": aarch64WindowsMsvc,
// 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,
"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
)
));
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 {

View File

@@ -1,18 +0,0 @@
{
"compilerOptions": {
"moduleResolution": "node",
"esModuleInterop": true,
"target": "es2017",
"module": "commonjs",
"sourceMap": false,
"lib": [
"es2019",
]
},
"include": [
"./**/*.ts"
],
"ts-node": {
"transpileOnly": true
}
}

View File

@@ -1,32 +0,0 @@
#!/bin/sh
# Take the deb and bundle it into a apt repository
if [[ $# -lt 1 ]]
then
echo "Usage $0 <config dir>"
exit
fi
confdir=$1
set -ex
ver=`jq -r .version package.json`
distdir=$PWD/dist
confdir=$PWD/$confdir
repodir=`mktemp -d -t repo`
mkdir $repodir/conf
cp $confdir/conf_distributions $repodir/conf/distributions
pushd $repodir
for i in `cat conf/distributions | grep Codename | cut -d ' ' -f 2`
do
reprepro includedeb $i $distdir/element-desktop_${ver}_amd64.deb
done
tar cvzf $distdir/element-desktop_repo_$ver.tar.gz .
popd
rm -r $repodir

View File

@@ -1,55 +0,0 @@
#!/usr/bin/env node
/*
* Checks for the presence of a webapp, inspects its version and sets the
* version metadata of the package to match.
*/
const fs = require('fs').promises;
const asar = require('asar');
const childProcess = require('child_process');
async function versionFromAsar() {
try {
await fs.stat('webapp.asar');
} catch (e) {
console.log("No 'webapp.asar' found. Run 'yarn run fetch'");
return 1;
}
return asar.extractFile('webapp.asar', 'version').toString().trim();
}
async function setPackageVersion(ver) {
// set version in package.json: electron-builder will use this to populate
// all the various version fields
await new Promise((resolve, reject) => {
childProcess.execFile(process.platform === 'win32' ? 'yarn.cmd' : 'yarn', [
'version',
'-s',
'--no-git-tag-version', // This also means "don't commit to git" as it turns out
'--new-version',
ver,
], (err) => {
if (err) {
reject(err);
} else {
resolve();
}
});
});
}
async function main(args) {
let version = args[0];
if (version === undefined) version = await versionFromAsar();
await setPackageVersion(version);
}
if (require.main === module) {
main(process.argv.slice(2)).then((ret) => process.exit(ret));
}
module.exports = { versionFromAsar, setPackageVersion };

64
scripts/set-version.ts Executable file
View File

@@ -0,0 +1,64 @@
#!/usr/bin/env -S npx ts-node
/*
* Checks for the presence of a webapp, inspects its version and sets the
* version metadata of the package to match.
*/
import { promises as fs } from "fs";
import * as asar from "@electron/asar";
import * as childProcess from "child_process";
export async function versionFromAsar(): Promise<string> {
try {
await fs.stat("webapp.asar");
} catch (e) {
throw new Error("No 'webapp.asar' found. Run 'yarn run fetch'");
}
return asar.extractFile("webapp.asar", "version").toString().trim();
}
export async function setPackageVersion(ver: string): Promise<void> {
// set version in package.json: electron-builder will use this to populate
// all the various version fields
await new Promise<void>((resolve, reject) => {
childProcess.execFile(
process.platform === "win32" ? "yarn.cmd" : "yarn",
[
"version",
"-s",
"--no-git-tag-version", // This also means "don't commit to git" as it turns out
"--new-version",
ver,
],
(err) => {
if (err) {
reject(err);
} else {
resolve();
}
},
);
});
}
async function main(args: string[]): Promise<number> {
let version = args[0];
if (version === undefined) version = await versionFromAsar();
await setPackageVersion(version);
return 0;
}
if (require.main === module) {
main(process.argv.slice(2))
.then((ret) => {
process.exit(ret);
})
.catch((e) => {
console.error(e);
process.exit(1);
});
}

16
scripts/tsconfig.json Normal file
View File

@@ -0,0 +1,16 @@
{
"compilerOptions": {
"resolveJsonModule": true,
"moduleResolution": "node",
"esModuleInterop": true,
"target": "es2017",
"module": "commonjs",
"sourceMap": false,
"strict": true,
"lib": ["es2019", "dom"]
},
"include": ["../src/@types", "./**/*.ts"],
"ts-node": {
"transpileOnly": true
}
}

6
src/@types/glob.d.ts vendored Normal file
View File

@@ -0,0 +1,6 @@
import { GlobOptions } from "glob";
declare module "glob" {
// Workaround for @electron/asar importing IOptions instead of GlobOptions
export type IOptions = GlobOptions;
}

View File

@@ -50,5 +50,5 @@ declare module "keytar" {
*
* @returns A promise for the array of found credentials.
*/
export function findCredentials(service: string): Promise<Array<{ account: string, password: string}>>;
export function findCredentials(service: string): Promise<Array<{ account: string; password: string }>>;
}

View File

@@ -86,7 +86,7 @@ declare module "matrix-seshat" {
}
export class Seshat {
constructor(path: string, config?: IConfig);
public constructor(path: string, config?: IConfig);
public addEvent(matrixEvent: IMatrixEvent, profile?: IMatrixProfile): void;
public deleteEvent(eventId: string): Promise<boolean>;
public commit(force?: boolean): Promise<number>;
@@ -132,7 +132,7 @@ declare module "matrix-seshat" {
}
export class SeshatRecovery {
constructor(path: string, config?: IConfig);
public constructor(path: string, config?: IConfig);
public info(): IRecoveryInfo;
public getUserVersion(): Promise<number>;
public shutdown(): Promise<void>;
@@ -140,6 +140,6 @@ declare module "matrix-seshat" {
}
export class ReindexError extends Error {
constructor(message?: string);
public constructor(message?: string);
}
}

View File

@@ -19,18 +19,12 @@ 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 "./squirrelhooks";
import {
app,
BrowserWindow,
Menu,
autoUpdater,
protocol,
dialog,
} from "electron";
import { app, BrowserWindow, Menu, autoUpdater, protocol, dialog, Input } from "electron";
import * as Sentry from "@sentry/electron/main";
import AutoLaunch from "auto-launch";
import path from "path";
import windowStateKeeper from 'electron-window-state';
import Store from 'electron-store';
import windowStateKeeper from "electron-window-state";
import Store from "electron-store";
import fs, { promises as afs } from "fs";
import { URL } from "url";
import minimist from "minimist";
@@ -40,23 +34,16 @@ import "./keytar";
import "./seshat";
import "./settings";
import * as tray from "./tray";
import { buildMenuTemplate } from './vectormenu';
import webContentsHandler from './webcontents-handler';
import * as updater from './updater';
import { getProfileFromDeeplink, protocolInit } from './protocol';
import { _t, AppLocalization } from './language-helper';
import Input = Electron.Input;
import { buildMenuTemplate } from "./vectormenu";
import webContentsHandler from "./webcontents-handler";
import * as updater from "./updater";
import { getProfileFromDeeplink, protocolInit } from "./protocol";
import { _t, AppLocalization } from "./language-helper";
const argv = minimist(process.argv, {
alias: { help: "h" },
});
// Things we need throughout the file but need to be created
// async to are initialised in setupGlobals()
let asarPath: string;
let resPath: string;
let iconPath: string;
if (argv["help"]) {
console.log("Options:");
console.log(" --profile-dir {path}: Path to where to store the profile.");
@@ -65,8 +52,7 @@ if (argv["help"]) {
console.log(" --no-update: Disable automatic updating.");
console.log(" --hidden: Start the application hidden in the system tray.");
console.log(" --help: Displays this help message.");
console.log("And more such as --proxy, see:" +
"https://electronjs.org/docs/api/command-line-switches");
console.log("And more such as --proxy, see:" + "https://electronjs.org/docs/api/command-line-switches");
app.exit();
}
@@ -74,7 +60,7 @@ if (argv["help"]) {
// as soon as the app path is set, so pick a random path in it that must exist if it's a
// real user data directory.
function isRealUserDataDir(d: string): boolean {
return fs.existsSync(path.join(d, 'IndexedDB'));
return fs.existsSync(path.join(d, "IndexedDB"));
}
// check if we are passed a profile in the SSO callback url
@@ -83,22 +69,22 @@ let userDataPath: string;
const userDataPathInProtocol = getProfileFromDeeplink(argv["_"]);
if (userDataPathInProtocol) {
userDataPath = userDataPathInProtocol;
} else if (argv['profile-dir']) {
userDataPath = argv['profile-dir'];
} else if (argv["profile-dir"]) {
userDataPath = argv["profile-dir"];
} else {
let newUserDataPath = app.getPath('userData');
if (argv['profile']) {
newUserDataPath += '-' + argv['profile'];
let newUserDataPath = app.getPath("userData");
if (argv["profile"]) {
newUserDataPath += "-" + argv["profile"];
}
const newUserDataPathExists = isRealUserDataDir(newUserDataPath);
let oldUserDataPath = path.join(app.getPath('appData'), app.getName().replace('Element', 'Riot'));
if (argv['profile']) {
oldUserDataPath += '-' + argv['profile'];
let oldUserDataPath = path.join(app.getPath("appData"), app.getName().replace("Element", "Riot"));
if (argv["profile"]) {
oldUserDataPath += "-" + argv["profile"];
}
const oldUserDataPathExists = isRealUserDataDir(oldUserDataPath);
console.log(newUserDataPath + " exists: " + (newUserDataPathExists ? 'yes' : 'no'));
console.log(oldUserDataPath + " exists: " + (oldUserDataPathExists ? 'yes' : 'no'));
console.log(newUserDataPath + " exists: " + (newUserDataPathExists ? "yes" : "no"));
console.log(oldUserDataPath + " exists: " + (oldUserDataPathExists ? "yes" : "no"));
if (!newUserDataPathExists && oldUserDataPathExists) {
console.log("Using legacy user data path: " + oldUserDataPath);
userDataPath = oldUserDataPath;
@@ -106,54 +92,57 @@ if (userDataPathInProtocol) {
userDataPath = newUserDataPath;
}
}
app.setPath('userData', userDataPath);
app.setPath("userData", userDataPath);
async function tryPaths(name: string, root: string, rawPaths: string[]): Promise<string> {
// Make everything relative to root
const paths = rawPaths.map(p => path.join(root, p));
const paths = rawPaths.map((p) => path.join(root, p));
for (const p of paths) {
try {
await afs.stat(p);
return p + '/';
} catch (e) {
}
return p + "/";
} catch (e) {}
}
console.log(`Couldn't find ${name} files in any of: `);
for (const p of paths) {
console.log("\t"+path.resolve(p));
console.log("\t" + path.resolve(p));
}
throw new Error(`Failed to find ${name} files`);
}
const homeserverProps = ['default_is_url', 'default_hs_url', 'default_server_name', 'default_server_config'] as const;
const homeserverProps = ["default_is_url", "default_hs_url", "default_server_name", "default_server_config"] as const;
// Find the webapp resources and set up things that require them
async function setupGlobals(): Promise<void> {
// find the webapp asar.
asarPath = await tryPaths("webapp", __dirname, [
// If run from the source checkout, this will be in the directory above
'../webapp.asar',
// but if run from a packaged application, electron-main.js will be in
// a different asar file so it will be two levels above
'../../webapp.asar',
// also try without the 'asar' suffix to allow symlinking in a directory
'../webapp',
// from a packaged application
'../../webapp',
]);
let asarPathPromise: Promise<string> | undefined;
// Get the webapp resource file path, memoizes result
function getAsarPath(): Promise<string> {
if (!asarPathPromise) {
asarPathPromise = tryPaths("webapp", __dirname, [
// If run from the source checkout, this will be in the directory above
"../webapp.asar",
// but if run from a packaged application, electron-main.js will be in
// a different asar file, so it will be two levels above
"../../webapp.asar",
// also try without the 'asar' suffix to allow symlinking in a directory
"../webapp",
// from a packaged application
"../../webapp",
]);
}
// we assume the resources path is in the same place as the asar
resPath = await tryPaths("res", path.dirname(asarPath), [
// If run from the source checkout
'res',
// if run from packaged application
'',
]);
return asarPathPromise;
}
// Loads the config from asar, and applies a config.json from userData atop if one exists
// Writes config to `global.vectorConfig`. Does nothing if `global.vectorConfig` is already set.
async function loadConfig(): Promise<void> {
if (global.vectorConfig) return;
const asarPath = await getAsarPath();
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
global.vectorConfig = require(asarPath + 'config.json');
global.vectorConfig = require(asarPath + "config.json");
} catch (e) {
// it would be nice to check the error code here and bail if the config
// is unparsable, but we get MODULE_NOT_FOUND in the case of a missing
@@ -165,19 +154,19 @@ async function setupGlobals(): Promise<void> {
try {
// Load local config and use it to override values from the one baked with the build
// eslint-disable-next-line @typescript-eslint/no-var-requires
const localConfig = require(path.join(app.getPath('userData'), 'config.json'));
const localConfig = require(path.join(app.getPath("userData"), "config.json"));
// If the local config has a homeserver defined, don't use the homeserver from the build
// config. This is to avoid a problem where Riot thinks there are multiple homeservers
// defined, and panics as a result.
if (Object.keys(localConfig).find(k => homeserverProps.includes(<any>k))) {
if (Object.keys(localConfig).find((k) => homeserverProps.includes(<any>k))) {
// Rip out all the homeserver options from the vector config
global.vectorConfig = Object.keys(global.vectorConfig)
.filter(k => !homeserverProps.includes(<any>k))
.filter((k) => !homeserverProps.includes(<any>k))
.reduce((obj, key) => {
obj[key] = global.vectorConfig[key];
return obj;
}, {} as Omit<Partial<typeof global["vectorConfig"]>, keyof typeof homeserverProps>);
}, {} as Omit<Partial<(typeof global)["vectorConfig"]>, keyof typeof homeserverProps>);
}
global.vectorConfig = Object.assign(global.vectorConfig, localConfig);
@@ -185,28 +174,57 @@ async function setupGlobals(): Promise<void> {
if (e instanceof SyntaxError) {
dialog.showMessageBox({
type: "error",
title: `Your ${global.vectorConfig.brand || 'Element'} is misconfigured`,
message: `Your custom ${global.vectorConfig.brand || 'Element'} configuration contains invalid JSON. ` +
`Please correct the problem and reopen ${global.vectorConfig.brand || 'Element'}.`,
title: `Your ${global.vectorConfig.brand || "Element"} is misconfigured`,
message:
`Your custom ${global.vectorConfig.brand || "Element"} configuration contains invalid JSON. ` +
`Please correct the problem and reopen ${global.vectorConfig.brand || "Element"}.`,
detail: e.message || "",
});
}
// Could not load local config, this is expected in most cases.
}
}
// Configure Electron Sentry and crashReporter using sentry.dsn in config.json if one is present.
async function configureSentry(): Promise<void> {
await loadConfig();
const { dsn, environment } = global.vectorConfig.sentry || {};
if (dsn) {
console.log(`Enabling Sentry with dsn=${dsn} environment=${environment}`);
Sentry.init({
dsn,
environment,
// We don't actually use this IPC, but we do not want Sentry injecting preloads
ipcMode: Sentry.IPCMode.Classic,
});
}
}
// Set up globals for Tray and AutoLaunch
async function setupGlobals(): Promise<void> {
const asarPath = await getAsarPath();
await loadConfig();
// we assume the resources path is in the same place as the asar
const resPath = await tryPaths("res", path.dirname(asarPath), [
// If run from the source checkout
"res",
// if run from packaged application
"",
]);
// The tray icon
// It's important to call `path.join` so we don't end up with the packaged asar in the final path.
const iconFile = `element.${process.platform === 'win32' ? 'ico' : 'png'}`;
iconPath = path.join(resPath, "img", iconFile);
const iconFile = `element.${process.platform === "win32" ? "ico" : "png"}`;
global.trayConfig = {
icon_path: iconPath,
brand: global.vectorConfig.brand || 'Element',
icon_path: path.join(resPath, "img", iconFile),
brand: global.vectorConfig.brand || "Element",
};
// launcher
global.launcher = new AutoLaunch({
name: global.vectorConfig.brand || 'Element',
name: global.vectorConfig.brand || "Element",
isHidden: true,
mac: {
useLaunchAgent: true,
@@ -214,12 +232,12 @@ async function setupGlobals(): Promise<void> {
});
}
// Look for an auto-launcher under 'Riot' and if we find one,
// port its enabled/disabled-ness over to the new 'Element' launcher
async function moveAutoLauncher(): Promise<void> {
// Look for an auto-launcher under 'Riot' and if we find one, port it's
// enabled/disabled-ness over to the new 'Element' launcher
if (!global.vectorConfig.brand || global.vectorConfig.brand === 'Element') {
if (!global.vectorConfig.brand || global.vectorConfig.brand === "Element") {
const oldLauncher = new AutoLaunch({
name: 'Riot',
name: "Riot",
isHidden: true,
mac: {
useLaunchAgent: true,
@@ -238,26 +256,30 @@ global.store = new Store({ name: "electron-config" });
global.appQuitting = false;
const exitShortcuts: Array<(input: Input, platform: string) => boolean> = [
(input, platform) => platform !== 'darwin' && input.alt && input.key.toUpperCase() === 'F4',
(input, platform) => platform !== 'darwin' && input.control && input.key.toUpperCase() === 'Q',
(input, platform) => platform === 'darwin' && input.meta && input.key.toUpperCase() === 'Q',
(input, platform): boolean => platform !== "darwin" && input.alt && input.key.toUpperCase() === "F4",
(input, platform): boolean => platform !== "darwin" && input.control && input.key.toUpperCase() === "Q",
(input, platform): boolean => platform === "darwin" && input.meta && input.key.toUpperCase() === "Q",
];
const warnBeforeExit = (event: Event, input: Input): void => {
const shouldWarnBeforeExit = global.store.get('warnBeforeExit', true);
const shouldWarnBeforeExit = global.store.get("warnBeforeExit", true);
const exitShortcutPressed =
input.type === 'keyDown' && exitShortcuts.some(shortcutFn => shortcutFn(input, process.platform));
input.type === "keyDown" && exitShortcuts.some((shortcutFn) => shortcutFn(input, process.platform));
if (shouldWarnBeforeExit && exitShortcutPressed && global.mainWindow) {
const shouldCancelCloseRequest = dialog.showMessageBoxSync(global.mainWindow, {
type: "question",
buttons: [_t("Cancel"), _t("Close %(brand)s", {
brand: global.vectorConfig.brand || 'Element',
})],
message: _t("Are you sure you want to quit?"),
defaultId: 1,
cancelId: 0,
}) === 0;
const shouldCancelCloseRequest =
dialog.showMessageBoxSync(global.mainWindow, {
type: "question",
buttons: [
_t("Cancel"),
_t("Close %(brand)s", {
brand: global.vectorConfig.brand || "Element",
}),
],
message: _t("Are you sure you want to quit?"),
defaultId: 1,
cancelId: 0,
}) === 0;
if (shouldCancelCloseRequest) {
event.preventDefault();
@@ -265,24 +287,26 @@ const warnBeforeExit = (event: Event, input: Input): void => {
}
};
configureSentry();
// handle uncaught errors otherwise it displays
// stack traces in popup dialogs, which is terrible (which
// it will do any time the auto update poke fails, and there's
// no other way to catch this error).
// Assuming we generally run from the console when developing,
// this is far preferable.
process.on('uncaughtException', function(error: Error): void {
console.log('Unhandled exception', error);
process.on("uncaughtException", function (error: Error): void {
console.log("Unhandled exception", error);
});
app.commandLine.appendSwitch('--enable-usermedia-screen-capturing');
if (!app.commandLine.hasSwitch('enable-features')) {
app.commandLine.appendSwitch('enable-features', 'WebRTCPipeWireCapturer');
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) {
console.log('Other instance detected: exiting');
console.log("Other instance detected: exiting");
app.exit();
}
@@ -294,14 +318,16 @@ protocolInit();
// work.
// Also mark it as secure (ie. accessing resources from this
// protocol and HTTPS won't trigger mixed content warnings).
protocol.registerSchemesAsPrivileged([{
scheme: 'vector',
privileges: {
standard: true,
secure: true,
supportFetchAPI: true,
protocol.registerSchemesAsPrivileged([
{
scheme: "vector",
privileges: {
standard: true,
secure: true,
supportFetchAPI: true,
},
},
}]);
]);
// Turn the sandbox on for *all* windows we might generate. Doing this means we don't
// have to specify a `sandbox: true` to each BrowserWindow.
@@ -315,16 +341,19 @@ protocol.registerSchemesAsPrivileged([{
app.enableSandbox();
// We disable media controls here. We do this because calls use audio and video elements and they sometimes capture the media keys. See https://github.com/vector-im/element-web/issues/15704
app.commandLine.appendSwitch('disable-features', 'HardwareMediaKeyHandling,MediaSessionService');
app.commandLine.appendSwitch("disable-features", "HardwareMediaKeyHandling,MediaSessionService");
// Disable hardware acceleration if the setting has been set.
if (global.store.get('disableHardwareAcceleration', false) === true) {
if (global.store.get("disableHardwareAcceleration", false) === true) {
console.log("Disabling hardware acceleration.");
app.disableHardwareAcceleration();
}
app.on('ready', async () => {
app.on("ready", async () => {
let asarPath: string;
try {
asarPath = await getAsarPath();
await setupGlobals();
await moveAutoLauncher();
} catch (e) {
@@ -337,51 +366,51 @@ app.on('ready', async () => {
return;
}
if (argv['devtools']) {
if (argv["devtools"]) {
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require('electron-devtools-installer');
const { default: installExt, REACT_DEVELOPER_TOOLS, REACT_PERF } = require("electron-devtools-installer");
installExt(REACT_DEVELOPER_TOOLS)
.then((name: string) => console.log(`Added Extension: ${name}`))
.catch((err: unknown) => console.log('An error occurred: ', err));
.catch((err: unknown) => console.log("An error occurred: ", err));
installExt(REACT_PERF)
.then((name: string) => console.log(`Added Extension: ${name}`))
.catch((err: unknown) => console.log('An error occurred: ', err));
.catch((err: unknown) => console.log("An error occurred: ", err));
} catch (e) {
console.log(e);
}
}
protocol.registerFileProtocol('vector', (request, callback) => {
if (request.method !== 'GET') {
protocol.registerFileProtocol("vector", (request, callback) => {
if (request.method !== "GET") {
callback({ error: -322 }); // METHOD_NOT_SUPPORTED from chromium/src/net/base/net_error_list.h
return null;
}
const parsedUrl = new URL(request.url);
if (parsedUrl.protocol !== 'vector:') {
if (parsedUrl.protocol !== "vector:") {
callback({ error: -302 }); // UNKNOWN_URL_SCHEME
return;
}
if (parsedUrl.host !== 'vector') {
if (parsedUrl.host !== "vector") {
callback({ error: -105 }); // NAME_NOT_RESOLVED
return;
}
const target = parsedUrl.pathname.split('/');
const target = parsedUrl.pathname.split("/");
// path starts with a '/'
if (target[0] !== '') {
if (target[0] !== "") {
callback({ error: -6 }); // FILE_NOT_FOUND
return;
}
if (target[target.length - 1] == '') {
target[target.length - 1] = 'index.html';
if (target[target.length - 1] == "") {
target[target.length - 1] = "index.html";
}
let baseDir: string;
if (target[1] === 'webapp') {
if (target[1] === "webapp") {
baseDir = asarPath;
} else {
callback({ error: -6 }); // FILE_NOT_FOUND
@@ -393,7 +422,7 @@ app.on('ready', async () => {
baseDir = path.normalize(baseDir);
const relTarget = path.normalize(path.join(...target.slice(2)));
if (relTarget.startsWith('..')) {
if (relTarget.startsWith("..")) {
callback({ error: -6 }); // FILE_NOT_FOUND
return;
}
@@ -404,13 +433,13 @@ app.on('ready', async () => {
});
});
if (argv['no-update']) {
if (argv["no-update"]) {
console.log('Auto update disabled via command line flag "--no-update"');
} else if (global.vectorConfig['update_base_url']) {
console.log(`Starting auto update with base URL: ${global.vectorConfig['update_base_url']}`);
updater.start(global.vectorConfig['update_base_url']);
} else if (global.vectorConfig["update_base_url"]) {
console.log(`Starting auto update with base URL: ${global.vectorConfig["update_base_url"]}`);
updater.start(global.vectorConfig["update_base_url"]);
} else {
console.log('No update_base_url is defined: auto update is disabled');
console.log("No update_base_url is defined: auto update is disabled");
}
// Load the previous window state with fallback to defaults
@@ -422,11 +451,11 @@ app.on('ready', async () => {
const preloadScript = path.normalize(`${__dirname}/preload.js`);
global.mainWindow = new BrowserWindow({
// https://www.electronjs.org/docs/faq#the-font-looks-blurry-what-is-this-and-what-can-i-do
backgroundColor: '#fff',
backgroundColor: "#fff",
icon: iconPath,
icon: global.trayConfig.icon_path,
show: false,
autoHideMenuBar: global.store.get('autoHideMenuBar', true),
autoHideMenuBar: global.store.get("autoHideMenuBar", true),
x: mainWindowState.x,
y: mainWindowState.y,
@@ -440,20 +469,20 @@ app.on('ready', async () => {
webgl: true,
},
});
global.mainWindow.loadURL('vector://vector/webapp/');
global.mainWindow.loadURL("vector://vector/webapp/");
// Handle spellchecker
// For some reason spellCheckerEnabled isn't persisted, so we have to use the store here
global.mainWindow.webContents.session.setSpellCheckerEnabled(global.store.get("spellCheckerEnabled", true));
// Create trayIcon icon
if (global.store.get('minimizeToTray', true)) tray.create(global.trayConfig);
if (global.store.get("minimizeToTray", true)) tray.create(global.trayConfig);
global.mainWindow.once('ready-to-show', () => {
global.mainWindow.once("ready-to-show", () => {
if (!global.mainWindow) return;
mainWindowState.manage(global.mainWindow);
if (!argv['hidden']) {
if (!argv["hidden"]) {
global.mainWindow.show();
} else {
// hide here explicitly because window manage above sometimes shows it
@@ -461,21 +490,21 @@ app.on('ready', async () => {
}
});
global.mainWindow.webContents.on('before-input-event', warnBeforeExit);
global.mainWindow.webContents.on("before-input-event", warnBeforeExit);
global.mainWindow.on('closed', () => {
global.mainWindow.on("closed", () => {
global.mainWindow = null;
});
global.mainWindow.on('close', async (e) => {
global.mainWindow.on("close", async (e) => {
// If we are not quitting and have a tray icon then minimize to tray
if (!global.appQuitting && (tray.hasTray() || process.platform === 'darwin')) {
if (!global.appQuitting && (tray.hasTray() || process.platform === "darwin")) {
// On Mac, closing the window just hides it
// (this is generally how single-window Mac apps
// behave, eg. Mail.app)
e.preventDefault();
if (global.mainWindow?.isFullScreen()) {
global.mainWindow.once('leave-full-screen', () => global.mainWindow?.hide());
global.mainWindow.once("leave-full-screen", () => global.mainWindow?.hide());
global.mainWindow.setFullScreen(false);
} else {
@@ -486,12 +515,12 @@ app.on('ready', async () => {
}
});
if (process.platform === 'win32') {
if (process.platform === "win32") {
// Handle forward/backward mouse buttons in Windows
global.mainWindow.on('app-command', (e, cmd) => {
if (cmd === 'browser-backward' && global.mainWindow?.webContents.canGoBack()) {
global.mainWindow.on("app-command", (e, cmd) => {
if (cmd === "browser-backward" && global.mainWindow?.webContents.canGoBack()) {
global.mainWindow.webContents.goBack();
} else if (cmd === 'browser-forward' && global.mainWindow?.webContents.canGoForward()) {
} else if (cmd === "browser-forward" && global.mainWindow?.webContents.canGoForward()) {
global.mainWindow.webContents.goForward();
}
});
@@ -501,32 +530,29 @@ app.on('ready', async () => {
global.appLocalization = new AppLocalization({
store: global.store,
components: [
() => tray.initApplicationMenu(),
() => Menu.setApplicationMenu(buildMenuTemplate()),
],
components: [(): void => tray.initApplicationMenu(), (): void => Menu.setApplicationMenu(buildMenuTemplate())],
});
});
app.on('window-all-closed', () => {
app.on("window-all-closed", () => {
app.quit();
});
app.on('activate', () => {
app.on("activate", () => {
global.mainWindow?.show();
});
function beforeQuit(): void {
global.appQuitting = true;
global.mainWindow?.webContents.send('before-quit');
global.mainWindow?.webContents.send("before-quit");
}
app.on('before-quit', beforeQuit);
autoUpdater.on('before-quit-for-update', beforeQuit);
app.on("before-quit", beforeQuit);
autoUpdater.on("before-quit-for-update", beforeQuit);
app.on('second-instance', (ev, commandLine, workingDirectory) => {
app.on("second-instance", (ev, commandLine, workingDirectory) => {
// If other instance launched with --hidden then skip showing window
if (commandLine.includes('--hidden')) return;
if (commandLine.includes("--hidden")) return;
// Someone tried to run a second instance, we should focus our window.
if (global.mainWindow) {
@@ -540,4 +566,4 @@ app.on('second-instance', (ev, commandLine, workingDirectory) => {
// installer uses for the shortcut icon.
// This makes notifications work on windows 8.1 (and is
// a noop on other platforms).
app.setAppUserModelId('com.squirrel.element-desktop.Element');
app.setAppUserModelId("com.squirrel.element-desktop.Element");

View File

@@ -41,5 +41,7 @@
"Undo": "تراجَع",
"Quit": "غادِر",
"Show/Hide": "اعرض/أخفِ",
"Are you sure you want to quit?": "أمتأكّد من الإغلاق؟"
"Are you sure you want to quit?": "أمتأكّد من الإغلاق؟",
"Copy image address": "انسخ عنوان (رابط) الصورة",
"Close %(brand)s": "اغلاق %(brand)s"
}

47
src/i18n/strings/cs.json Normal file
View File

@@ -0,0 +1,47 @@
{
"Add to dictionary": "Přidat do slovníku",
"Failed to save image": "Chyba při ukládání obrázku",
"The image failed to save": "Obrázek se nepodařilo uložit",
"Save image as...": "Uložit obrázek jako...",
"Copy link address": "Kopírovat adresu odkazu",
"Copy image address": "Kopírovat adresu obrázku",
"Copy email address": "Kopírovat e-mailovou adresu",
"Copy image": "Kopírovat obrázek",
"File": "Soubor",
"Bring All to Front": "Přenést vše do popředí",
"Zoom": "Lupa",
"Stop Speaking": "Zastavit nahrávání hlasu",
"Start Speaking": "Spustit nahrávání hlasu",
"Speech": "Řeč",
"Unhide": "Zrušit skrytí",
"Hide Others": "Skrýt ostatní",
"Hide": "Skrýt",
"Services": "Služby",
"About": "O aplikaci",
"Element Help": "Nápověda aplikace Element",
"Help": "Nápověda",
"Close": "Zavřít",
"Minimize": "Minimalizovat",
"Window": "Okno",
"Toggle Developer Tools": "Přepnout zobrazení nástrojů pro vývojáře",
"Toggle Full Screen": "Přepnout zobrazení celé obrazovky",
"Preferences": "Předvolby",
"Zoom Out": "Oddálit",
"Zoom In": "Přiblížit",
"Actual Size": "Aktuální velikost",
"View": "Zobrazit",
"Select All": "Vybrat vše",
"Delete": "Smazat",
"Paste and Match Style": "Vložit a přizpůsobit styl",
"Paste": "Vložit",
"Copy": "Kopírovat",
"Cut": "Vyjmout",
"Redo": "Znovu",
"Undo": "Zpět",
"Edit": "Úpravy",
"Quit": "Ukončit",
"Show/Hide": "Zobrazit/Skrýt",
"Are you sure you want to quit?": "Opravdu chcete ukončit aplikaci?",
"Close %(brand)s": "Zavřít %(brand)s",
"Cancel": "Zrušit"
}

View File

@@ -17,5 +17,18 @@
"Undo": "Malfari",
"Edit": "Redakti",
"Show/Hide": "Montri/Kaŝi",
"Cancel": "Nuligi"
"Cancel": "Nuligi",
"Copy link address": "Kopiu ligilon de la bildo",
"Copy image address": "Kopiu adreson de la bildo",
"Copy email address": "Kopiu retadreson",
"Copy image": "Kopiu bildon",
"File": "Dosiero",
"Minimize": "Minimumigi",
"Window": "Fenestro",
"Select All": "Elekti Ĉiujn",
"Paste": "Enmeti",
"Copy": "Kopiu",
"Cut": "Tranĉi",
"Are you sure you want to quit?": "Ĉu vi certas, ke vi volas ĉesi?",
"Close %(brand)s": "Fermu %(brand)s"
}

View File

@@ -42,5 +42,6 @@
"Stop Speaking": "Arrêter la dictée",
"Start Speaking": "Commencer la dictée",
"Copy image address": "Copier l'adresse de l'image",
"Redo": "Refaire"
"Redo": "Refaire",
"Close %(brand)s": "Fermer %(brand)s"
}

View File

@@ -42,5 +42,6 @@
"Show/Hide": "Sýna/Fela",
"Are you sure you want to quit?": "Ertu viss um að þú viljir hætta?",
"Cancel": "Hætta við",
"Copy image address": "Afrita slóð myndar"
"Copy image address": "Afrita slóð myndar",
"Close %(brand)s": "Loka %(brand)s"
}

View File

@@ -14,7 +14,7 @@
"Hide Others": "Nascondi gli altri",
"Hide": "Nascondi",
"Services": "Servizi",
"About": "Al riguardo",
"About": "Informazioni su",
"Element Help": "Aiuto di Element",
"Help": "Aiuto",
"Close": "Chiudi",
@@ -29,7 +29,7 @@
"View": "Vedi",
"Select All": "Seleziona tutto",
"Delete": "Elimina",
"Paste and Match Style": "Incolla e abbina lo stile",
"Paste and Match Style": "Incolla e adegua lo stile",
"Paste": "Incolla",
"Copy": "Copia",
"Cut": "Taglia",

47
src/i18n/strings/ja.json Normal file
View File

@@ -0,0 +1,47 @@
{
"Close %(brand)s": "%(brand)sを閉じる",
"Bring All to Front": "全てを前面に表示",
"The image failed to save": "画像の保存に失敗しました",
"Unhide": "再表示",
"Actual Size": "等倍",
"Paste and Match Style": "スタイルを保持して貼り付け",
"Add to dictionary": "辞書に追加",
"Failed to save image": "画像の保存に失敗",
"Save image as...": "画像を保存",
"Speech": "スピーチ",
"Stop Speaking": "録音を停止",
"Start Speaking": "録音を開始",
"Toggle Developer Tools": "開発者ツールを切り替える",
"Toggle Full Screen": "全画面表示を切り替える",
"Redo": "やり直す",
"Undo": "取り消す",
"Minimize": "最小化",
"Window": "ウィンドウ",
"Preferences": "環境設定",
"Zoom Out": "縮小",
"Zoom In": "拡大",
"Copy link address": "リンクのアドレスをコピー",
"Copy image address": "画像のアドレスをコピー",
"Copy email address": "メールアドレスをコピー",
"Copy image": "画像をコピー",
"File": "ファイル",
"Zoom": "ズーム",
"Hide Others": "他を非表示",
"Hide": "非表示",
"Services": "サービス",
"About": "概要",
"Element Help": "Element ヘルプ",
"Help": "ヘルプ",
"Close": "閉じる",
"View": "表示",
"Select All": "全て選択",
"Delete": "削除",
"Paste": "貼り付け",
"Copy": "コピー",
"Cut": "切り取り",
"Edit": "編集",
"Quit": "終了",
"Are you sure you want to quit?": "終了してよろしいですか?",
"Show/Hide": "表示/非表示",
"Cancel": "キャンセル"
}

12
src/i18n/strings/ko.json Normal file
View File

@@ -0,0 +1,12 @@
{
"File": "파일",
"Copy email address": "이메일 주소 복사",
"Paste": "붙여넣기",
"Hide": "숨기기",
"Preferences": "환경설정",
"Undo": "실행 취소",
"Edit": "수정",
"Quit": "종료",
"Delete": "삭제",
"Cancel": "취소"
}

View File

@@ -32,5 +32,7 @@
"Are you sure you want to quit?": "Er du sikker på at du vil slutte?",
"Cancel": "Avbryt",
"Services": "Tjenester",
"Hide Others": "Skjul Andre"
"Hide Others": "Skjul Andre",
"Bring All to Front": "Flytt Alt Frem",
"Toggle Full Screen": "Veksle Fullskjerm"
}

View File

@@ -1,13 +1,13 @@
{
"Add to dictionary": "Adăugați la dicționar",
"Failed to save image": "Eroare in salvarea imaginii",
"Failed to save image": "Eroare în 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",
"Zoom": "Zoom",
"Stop Speaking": "Oprire Voce",
"Start Speaking": "Pornire Voce",
"Speech": "Voce",
@@ -31,12 +31,14 @@
"Delete": "Șterge",
"Paste and Match Style": "Lipește si potrivește stilul",
"Paste": "Lipește",
"Copy": "Copiere",
"Copy": "Copiază",
"Redo": "Refă",
"Undo": "Anulare",
"Edit": "Editare",
"Quit": "Închid",
"Show/Hide": "Arată/Ascunde",
"Are you sure you want to quit?": "Sigur vrei să ieși din cont?",
"Cancel": "Anulare"
"Cancel": "Anulare",
"Close %(brand)s": "Închide %(brand)s",
"Cut": "Taie"
}

16
src/i18n/strings/tl.json Normal file
View File

@@ -0,0 +1,16 @@
{
"Hide": "Itago",
"Delete": "Alisin",
"Paste and Match Style": "I-paste at Tumugma ng Style",
"Paste": "I-paste",
"Copy": "I-copy",
"Cut": "I-cut",
"Redo": "Redo",
"Undo": "Undo",
"Edit": "I-edit",
"Quit": "Magsara",
"Show/Hide": "Ipakita/itago",
"Are you sure you want to quit?": "Sigurado ka ba na gusto mong magsara?",
"Close %(brand)s": "Isara ang %(brand)s",
"Cancel": "Kanselahin"
}

1
src/i18n/strings/uk.json Normal file
View File

@@ -0,0 +1 @@
{}

View File

@@ -42,5 +42,6 @@
"Show/Hide": "显示/隐藏",
"Are you sure you want to quit?": "你确定要退出吗?",
"Cancel": "取消",
"Copy image address": "复制图片地址"
"Copy image address": "复制图片地址",
"Close %(brand)s": "关闭 %(brand)s"
}

View File

@@ -1,6 +1,6 @@
{
"Bring All to Front": "全部移至最前",
"Add to dictionary": "加入至字典",
"Add to dictionary": "新增到字典",
"The image failed to save": "儲存圖片失敗",
"Failed to save image": "儲存圖片失敗",
"Save image as...": "另存圖片為...",
@@ -17,8 +17,8 @@
"Hide": "隱藏",
"Services": "服務",
"About": "關於",
"Element Help": "Element 協助",
"Help": "協助",
"Element Help": "Element 說明",
"Help": "說明",
"Close": "關閉",
"Minimize": "最小化",
"Window": "視窗",
@@ -38,9 +38,9 @@
"Redo": "取消復原",
"Undo": "復原",
"Edit": "編輯",
"Quit": "退出",
"Quit": "離開",
"Show/Hide": "顯示/隱藏",
"Are you sure you want to quit?": "您確定要退出嗎?",
"Are you sure you want to quit?": "您確定要離開嗎?",
"Cancel": "取消",
"Copy image address": "複製圖片地址",
"Close %(brand)s": "關閉 %(brand)s"

View File

@@ -14,7 +14,8 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker } from "electron";
import { app, autoUpdater, desktopCapturer, ipcMain, powerSaveBlocker, TouchBar, nativeImage } from "electron";
import { relaunchApp } from "electron-clear-data";
import IpcMainEvent = Electron.IpcMainEvent;
import { recordSSOSession } from "./protocol";
@@ -22,8 +23,8 @@ import { randomArray } from "./utils";
import { Settings } from "./settings";
import { keytar } from "./keytar";
ipcMain.on('setBadgeCount', function(_ev: IpcMainEvent, count: number): void {
if (process.platform !== 'win32') {
ipcMain.on("setBadgeCount", function (_ev: IpcMainEvent, count: number): void {
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
@@ -35,10 +36,10 @@ ipcMain.on('setBadgeCount', function(_ev: IpcMainEvent, count: number): void {
});
let focusHandlerAttached = false;
ipcMain.on('loudNotification', function(): void {
if (process.platform === 'win32' && global.mainWindow && !global.mainWindow.isFocused() && !focusHandlerAttached) {
ipcMain.on("loudNotification", function (): void {
if (process.platform === "win32" && global.mainWindow && !global.mainWindow.isFocused() && !focusHandlerAttached) {
global.mainWindow.flashFrame(true);
global.mainWindow.once('focus', () => {
global.mainWindow.once("focus", () => {
global.mainWindow?.flashFrame(false);
focusHandlerAttached = false;
});
@@ -47,17 +48,17 @@ ipcMain.on('loudNotification', function(): void {
});
let powerSaveBlockerId: number | null = null;
ipcMain.on('app_onAction', function(_ev: IpcMainEvent, payload) {
ipcMain.on("app_onAction", function (_ev: IpcMainEvent, payload) {
switch (payload.action) {
case 'call_state': {
case "call_state": {
if (powerSaveBlockerId !== null && powerSaveBlocker.isStarted(powerSaveBlockerId)) {
if (payload.state === 'ended') {
if (payload.state === "ended") {
powerSaveBlocker.stop(powerSaveBlockerId);
powerSaveBlockerId = null;
}
} else {
if (powerSaveBlockerId === null && payload.state === 'connected') {
powerSaveBlockerId = powerSaveBlocker.start('prevent-display-sleep');
if (powerSaveBlockerId === null && payload.state === "connected") {
powerSaveBlockerId = powerSaveBlocker.start("prevent-display-sleep");
}
}
break;
@@ -65,35 +66,35 @@ ipcMain.on('app_onAction', function(_ev: IpcMainEvent, payload) {
}
});
ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
ipcMain.on("ipcCall", async function (_ev: IpcMainEvent, payload) {
if (!global.mainWindow) return;
const args = payload.args || [];
let ret: any;
switch (payload.name) {
case 'getUpdateFeedUrl':
case "getUpdateFeedUrl":
ret = autoUpdater.getFeedURL();
break;
case 'getSettingValue': {
case "getSettingValue": {
const [settingName] = args;
const setting = Settings[settingName];
ret = await setting.read();
break;
}
case 'setSettingValue': {
case "setSettingValue": {
const [settingName, value] = args;
const setting = Settings[settingName];
await setting.write(value);
break;
}
case 'setLanguage':
case "setLanguage":
global.appLocalization.setAppLocale(args[0]);
break;
case 'getAppVersion':
case "getAppVersion":
ret = app.getVersion();
break;
case 'focusWindow':
case "focusWindow":
if (global.mainWindow.isMinimized()) {
global.mainWindow.restore();
} else if (!global.mainWindow.isVisible()) {
@@ -102,31 +103,31 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
global.mainWindow.focus();
}
break;
case 'getConfig':
case "getConfig":
ret = global.vectorConfig;
break;
case 'navigateBack':
case "navigateBack":
if (global.mainWindow.webContents.canGoBack()) {
global.mainWindow.webContents.goBack();
}
break;
case 'navigateForward':
case "navigateForward":
if (global.mainWindow.webContents.canGoForward()) {
global.mainWindow.webContents.goForward();
}
break;
case 'setSpellCheckEnabled':
if (typeof args[0] !== 'boolean') return;
case "setSpellCheckEnabled":
if (typeof args[0] !== "boolean") return;
global.mainWindow.webContents.session.setSpellCheckerEnabled(args[0]);
global.store.set("spellCheckerEnabled", args[0]);
break;
case 'getSpellCheckEnabled':
case "getSpellCheckEnabled":
ret = global.store.get("spellCheckerEnabled", true);
break;
case 'setSpellCheckLanguages':
case "setSpellCheckLanguages":
try {
global.mainWindow.webContents.session.setSpellCheckerLanguages(args[0]);
} catch (er) {
@@ -134,18 +135,18 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
}
break;
case 'getSpellCheckLanguages':
case "getSpellCheckLanguages":
ret = global.mainWindow.webContents.session.getSpellCheckerLanguages();
break;
case 'getAvailableSpellCheckLanguages':
case "getAvailableSpellCheckLanguages":
ret = global.mainWindow.webContents.session.availableSpellCheckerLanguages;
break;
case 'startSSOFlow':
case "startSSOFlow":
recordSSOSession(args[0]);
break;
case 'getPickleKey':
case "getPickleKey":
try {
ret = await keytar?.getPassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be
@@ -160,7 +161,7 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
}
break;
case 'createPickleKey':
case "createPickleKey":
try {
const pickleKey = await randomArray(32);
await keytar?.setPassword("element.io", `${args[0]}|${args[1]}`, pickleKey);
@@ -170,7 +171,7 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
}
break;
case 'destroyPickleKey':
case "destroyPickleKey":
try {
await keytar?.deletePassword("element.io", `${args[0]}|${args[1]}`);
// migrate from riot.im (remove once we think there will no longer be
@@ -178,7 +179,7 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
await keytar?.deletePassword("riot.im", `${args[0]}|${args[1]}`);
} catch (e) {}
break;
case 'getDesktopCapturerSources':
case "getDesktopCapturerSources":
ret = (await desktopCapturer.getSources(args[0])).map((source) => ({
id: source.id,
name: source.name,
@@ -186,17 +187,74 @@ ipcMain.on('ipcCall', async function(_ev: IpcMainEvent, payload) {
}));
break;
case "clearStorage":
global.store.clear();
global.mainWindow.webContents.session.flushStorageData();
await global.mainWindow.webContents.session.clearStorageData();
relaunchApp();
break;
case "breadcrumbs": {
if (process.platform === "darwin") {
const { TouchBarPopover, TouchBarButton } = TouchBar;
const recentsBar = new TouchBar({
items: args[0].map((r: { roomId: string; avatarUrl: string | null; initial: string }) => {
const defaultColors = ["#0DBD8B", "#368bd6", "#ac3ba8"];
let total = 0;
for (let i = 0; i < r.roomId.length; ++i) {
total += r.roomId.charCodeAt(i);
}
const button = new TouchBarButton({
label: r.initial,
backgroundColor: defaultColors[total % defaultColors.length],
click: (): void => {
global.mainWindow?.loadURL(`vector://vector/webapp/#/room/${r.roomId}`);
},
});
if (r.avatarUrl) {
fetch(r.avatarUrl)
.then((resp) => {
if (!resp.ok) return;
return resp.arrayBuffer();
})
.then((arrayBuffer) => {
if (!arrayBuffer) return;
const buffer = Buffer.from(arrayBuffer);
button.icon = nativeImage.createFromBuffer(buffer);
button.label = "";
button.backgroundColor = "";
});
}
return button;
}),
});
const touchBar = new TouchBar({
items: [
new TouchBarPopover({
label: "Recents",
showCloseButton: true,
items: recentsBar,
}),
],
});
global.mainWindow.setTouchBar(touchBar);
}
break;
}
default:
global.mainWindow.webContents.send('ipcReply', {
global.mainWindow.webContents.send("ipcReply", {
id: payload.id,
error: "Unknown IPC Call: " + payload.name,
});
return;
}
global.mainWindow.webContents.send('ipcReply', {
global.mainWindow.webContents.send("ipcReply", {
id: payload.id,
reply: ret,
});
});

View File

@@ -19,7 +19,7 @@ import type * as Keytar from "keytar"; // Hak dependency type
let keytar: typeof Keytar | undefined;
try {
// eslint-disable-next-line @typescript-eslint/no-var-requires
keytar = require('keytar');
keytar = require("keytar");
} catch (e) {
if ((<NodeJS.ErrnoException>e).code === "MODULE_NOT_FOUND") {
console.log("Keytar isn't installed; secure key storage is disabled.");

View File

@@ -16,9 +16,9 @@ limitations under the License.
import counterpart from "counterpart";
import type Store from 'electron-store';
import type Store from "electron-store";
const FALLBACK_LOCALE = 'en';
const FALLBACK_LOCALE = "en";
export function _td(text: string): string {
return text;
@@ -44,11 +44,11 @@ export function _t(text: string, variables: IVariables = {}): string {
Object.keys(variables).forEach((key) => {
if (variables[key] === undefined) {
console.warn("safeCounterpartTranslate called with undefined interpolation name: " + key);
variables[key] = 'undefined';
variables[key] = "undefined";
}
if (variables[key] === null) {
console.warn("safeCounterpartTranslate called with null interpolation name: " + key);
variables[key] = 'null';
variables[key] = "null";
}
});
let translated = counterpart.translate(text, variables);
@@ -71,10 +71,10 @@ export class AppLocalization {
private readonly store: TypedStore;
private readonly localizedComponents?: Set<Component>;
constructor({ store, components = [] }: { store: TypedStore, components: Component[] }) {
public constructor({ store, components = [] }: { store: TypedStore; components: Component[] }) {
counterpart.registerTranslations(FALLBACK_LOCALE, this.fetchTranslationJson("en_EN"));
counterpart.setFallbackLocale(FALLBACK_LOCALE);
counterpart.setSeparator('|');
counterpart.setSeparator("|");
if (Array.isArray(components)) {
this.localizedComponents = new Set(components);
@@ -119,7 +119,7 @@ export class AppLocalization {
locales = [locales];
}
const loadedLocales = locales.filter(locale => {
const loadedLocales = locales.filter((locale) => {
const translations = this.fetchTranslationJson(locale);
if (translations !== null) {
counterpart.registerTranslations(locale, translations);
@@ -135,7 +135,7 @@ export class AppLocalization {
public resetLocalizedUI(): void {
console.log("Resetting the UI components after locale change");
this.localizedComponents?.forEach(componentSetup => {
this.localizedComponents?.forEach((componentSetup) => {
if (typeof componentSetup === "function") {
componentSetup();
}

View File

@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
limitations under the License.
*/
import { ipcRenderer, contextBridge, IpcRendererEvent } 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.
@@ -36,22 +36,19 @@ const CHANNELS = [
"userDownloadAction",
];
contextBridge.exposeInMainWorld(
"electron",
{
on(channel: string, listener: (event: IpcRendererEvent, ...args: any[]) => void): void {
if (!CHANNELS.includes(channel)) {
console.error(`Unknown IPC channel ${channel} ignored`);
return;
}
ipcRenderer.on(channel, listener);
},
send(channel: string, ...args: any[]): void {
if (!CHANNELS.includes(channel)) {
console.error(`Unknown IPC channel ${channel} ignored`);
return;
}
ipcRenderer.send(channel, ...args);
},
contextBridge.exposeInMainWorld("electron", {
on(channel: string, listener: (event: IpcRendererEvent, ...args: any[]) => void): void {
if (!CHANNELS.includes(channel)) {
console.error(`Unknown IPC channel ${channel} ignored`);
return;
}
ipcRenderer.on(channel, listener);
},
);
send(channel: string, ...args: any[]): void {
if (!CHANNELS.includes(channel)) {
console.error(`Unknown IPC channel ${channel} ignored`);
return;
}
ipcRenderer.send(channel, ...args);
},
});

View File

@@ -67,7 +67,7 @@ function writeStore(data: Record<string, string>): void {
}
export function recordSSOSession(sessionID: string): void {
const userDataPath = app.getPath('userData');
const userDataPath = app.getPath("userData");
const store = readStore();
for (const key in store) {
// ensure each instance only has one (the latest) session ID to prevent the file growing unbounded
@@ -82,7 +82,7 @@ export function recordSSOSession(sessionID: string): void {
export function getProfileFromDeeplink(args: string[]): string | undefined {
// check if we are passed a profile in the SSO callback url
const deeplinkUrl = args.find(arg => arg.startsWith(PROTOCOL + '//'));
const deeplinkUrl = args.find((arg) => arg.startsWith(PROTOCOL + "//"));
if (deeplinkUrl?.includes(SEARCH_PARAM)) {
const parsedUrl = new URL(deeplinkUrl);
if (parsedUrl.protocol === PROTOCOL) {
@@ -98,25 +98,26 @@ export function protocolInit(): void {
// get all args except `hidden` as it'd mean the app would not get focused
// XXX: passing args to protocol handlers only works on Windows, so unpackaged deep-linking
// --profile/--profile-dir are passed via the SEARCH_PARAM var in the callback url
const args = process.argv.slice(1).filter(arg => arg !== "--hidden" && arg !== "-hidden");
const args = process.argv.slice(1).filter((arg) => arg !== "--hidden" && arg !== "-hidden");
if (app.isPackaged) {
app.setAsDefaultProtocolClient('element', process.execPath, args);
} else if (process.platform === 'win32') { // on Mac/Linux this would just cause the electron binary to open
app.setAsDefaultProtocolClient("element", process.execPath, args);
} else if (process.platform === "win32") {
// on Mac/Linux this would just cause the electron binary to open
// special handler for running without being packaged, e.g `electron .` by passing our app path to electron
app.setAsDefaultProtocolClient('element', process.execPath, [app.getAppPath(), ...args]);
app.setAsDefaultProtocolClient("element", process.execPath, [app.getAppPath(), ...args]);
}
if (process.platform === 'darwin') {
if (process.platform === "darwin") {
// Protocol handler for macos
app.on('open-url', function(ev, url) {
app.on("open-url", function (ev, url) {
ev.preventDefault();
processUrl(url);
});
} else {
// Protocol handler for win32/Linux
app.on('second-instance', (ev, commandLine) => {
app.on("second-instance", (ev, commandLine) => {
const url = commandLine[commandLine.length - 1];
if (!url.startsWith(PROTOCOL + '//')) return;
if (!url.startsWith(PROTOCOL + "//")) return;
processUrl(url);
});
}

Some files were not shown because too many files have changed in this diff Show More