mirror of
https://github.com/element-hq/element-desktop.git
synced 2026-02-23 17:57:58 -05:00
Compare commits
1 Commits
v1.11.17
...
dbkr/elect
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d577487cfe |
5
.github/CODEOWNERS
vendored
5
.github/CODEOWNERS
vendored
@@ -1,4 +1 @@
|
||||
* @vector-im/element-web
|
||||
/.github/workflows/** @vector-im/element-web-app-team
|
||||
/package.json @vector-im/element-web-app-team
|
||||
/yarn.lock @vector-im/element-web-app-team
|
||||
* @vector-im/element-web
|
||||
|
||||
10
.github/workflows/build_linux.yaml
vendored
10
.github/workflows/build_linux.yaml
vendored
@@ -1,6 +1,3 @@
|
||||
# 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:
|
||||
@@ -19,21 +16,19 @@ jobs:
|
||||
name: webapp
|
||||
|
||||
- name: Cache .hak
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ hashFiles('hakDependencies.json', 'electronVersion') }}
|
||||
key: ${{ hashFiles('./yarn.lock') }}
|
||||
path: |
|
||||
./.hak
|
||||
|
||||
- name: Install Rust
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
|
||||
- name: Install libsqlcipher-dev
|
||||
if: steps.cache.outputs.cache-hit != 'true' && inputs.sqlcipher == 'system'
|
||||
if: inputs.sqlcipher == 'system'
|
||||
run: sudo apt-get install -y libsqlcipher-dev
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
@@ -45,7 +40,6 @@ jobs:
|
||||
run: "yarn install --pure-lockfile"
|
||||
|
||||
- name: Build Natives
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: "yarn build:native"
|
||||
env:
|
||||
SQLCIPHER_STATIC: ${{ inputs.sqlcipher == 'static' && '1' || '' }}
|
||||
|
||||
8
.github/workflows/build_macos.yaml
vendored
8
.github/workflows/build_macos.yaml
vendored
@@ -1,6 +1,3 @@
|
||||
# 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:
|
||||
jobs:
|
||||
@@ -14,15 +11,13 @@ jobs:
|
||||
name: webapp
|
||||
|
||||
- name: Cache .hak
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ hashFiles('hakDependencies.json', 'electronVersion') }}
|
||||
key: ${{ hashFiles('./yarn.lock') }}
|
||||
path: |
|
||||
./.hak
|
||||
|
||||
- name: Install Rust
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
@@ -37,7 +32,6 @@ jobs:
|
||||
run: "yarn install --pure-lockfile"
|
||||
|
||||
- name: Build Natives
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: "yarn build:native:universal"
|
||||
|
||||
- name: Build App
|
||||
|
||||
8
.github/workflows/build_prepare.yaml
vendored
8
.github/workflows/build_prepare.yaml
vendored
@@ -26,12 +26,6 @@ jobs:
|
||||
- name: Fetch Element Web
|
||||
run: yarn run fetch --noverify -d ${{ inputs.config }} ${{ inputs.version }}
|
||||
|
||||
# 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
|
||||
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: webapp
|
||||
@@ -39,5 +33,3 @@ jobs:
|
||||
path: |
|
||||
webapp.asar
|
||||
package.json
|
||||
electronVersion
|
||||
hakDependencies.json
|
||||
|
||||
8
.github/workflows/build_windows.yaml
vendored
8
.github/workflows/build_windows.yaml
vendored
@@ -1,6 +1,3 @@
|
||||
# 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:
|
||||
@@ -35,10 +32,9 @@ jobs:
|
||||
name: webapp
|
||||
|
||||
- name: Cache .hak
|
||||
id: cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
key: ${{ runner.os }}-${{ hashFiles('hakDependencies.json', 'electronVersion') }}
|
||||
key: ${{ runner.os }}-${{ hashFiles('./yarn.lock') }}
|
||||
path: |
|
||||
./.hak
|
||||
|
||||
@@ -62,7 +58,6 @@ jobs:
|
||||
echo "C:/Program Files/NASM" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
|
||||
|
||||
- name: Install Rust
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: stable
|
||||
@@ -77,7 +72,6 @@ jobs:
|
||||
run: "yarn install --pure-lockfile"
|
||||
|
||||
- name: Build Natives
|
||||
if: steps.cache.outputs.cache-hit != 'true'
|
||||
run: |
|
||||
refreshenv
|
||||
yarn build:native --target ${{ steps.config.outputs.target }}
|
||||
|
||||
43
.github/workflows/packages_index.yaml
vendored
43
.github/workflows/packages_index.yaml
vendored
@@ -1,43 +0,0 @@
|
||||
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: { }
|
||||
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
|
||||
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 }}
|
||||
4
.github/workflows/static_analysis.yaml
vendored
4
.github/workflows/static_analysis.yaml
vendored
@@ -8,7 +8,7 @@ jobs:
|
||||
name: "Typescript Syntax Check"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
@@ -29,7 +29,7 @@ jobs:
|
||||
name: "ESLint"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v2
|
||||
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -4,7 +4,8 @@
|
||||
/webapp.asar
|
||||
/packages
|
||||
/deploys
|
||||
node_modules/
|
||||
/node_modules
|
||||
/docker_node_modules
|
||||
/pkg/control
|
||||
/.hak
|
||||
/.yarnrc
|
||||
@@ -14,4 +15,3 @@ node_modules/
|
||||
.vscode/
|
||||
/test_artifacts/
|
||||
/coverage/
|
||||
yarn-error.log
|
||||
|
||||
102
CHANGELOG.md
102
CHANGELOG.md
@@ -1,105 +1,3 @@
|
||||
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)
|
||||
=====================================================================================================
|
||||
|
||||
## ✨ Features
|
||||
* Switch to notarytool ([\#440](https://github.com/vector-im/element-desktop/pull/440)).
|
||||
* Make clear notifications work with threads ([\#9575](https://github.com/matrix-org/matrix-react-sdk/pull/9575)). Fixes vector-im/element-web#23751.
|
||||
* Change "None" to "Off" in notification options ([\#9539](https://github.com/matrix-org/matrix-react-sdk/pull/9539)). Contributed by @Arnei.
|
||||
* Advanced audio processing settings ([\#8759](https://github.com/matrix-org/matrix-react-sdk/pull/8759)). Fixes vector-im/element-web#6278. Contributed by @MrAnno.
|
||||
* Add way to create a user notice via config.json ([\#9559](https://github.com/matrix-org/matrix-react-sdk/pull/9559)).
|
||||
* Improve design of the rich text editor ([\#9533](https://github.com/matrix-org/matrix-react-sdk/pull/9533)).
|
||||
* Enable user to zoom beyond image size ([\#5949](https://github.com/matrix-org/matrix-react-sdk/pull/5949)). Contributed by @jaiwanth-v.
|
||||
* Fix: Move "Leave Space" option to the bottom of space context menu ([\#9535](https://github.com/matrix-org/matrix-react-sdk/pull/9535)). Contributed by @hanadi92.
|
||||
|
||||
## 🐛 Bug Fixes
|
||||
* Fix encrypted message search indexing for non-default `--profile` instances. ([\#433](https://github.com/vector-im/element-desktop/pull/433)).
|
||||
* Make build scripts work on NixOS ([\#23740](https://github.com/vector-im/element-web/pull/23740)).
|
||||
* Fix integration manager `get_open_id_token` action and add E2E tests ([\#9520](https://github.com/matrix-org/matrix-react-sdk/pull/9520)).
|
||||
* Fix links being mangled by markdown processing ([\#9570](https://github.com/matrix-org/matrix-react-sdk/pull/9570)). Fixes vector-im/element-web#23743.
|
||||
* Fix: inline links selecting radio button ([\#9543](https://github.com/matrix-org/matrix-react-sdk/pull/9543)). Contributed by @hanadi92.
|
||||
* fix wrong error message in registration when phone number threepid is in use. ([\#9571](https://github.com/matrix-org/matrix-react-sdk/pull/9571)). Contributed by @bagvand.
|
||||
* Fix missing avatar for show current profiles ([\#9563](https://github.com/matrix-org/matrix-react-sdk/pull/9563)). Fixes vector-im/element-web#23733.
|
||||
* fix read receipts trickling down correctly ([\#9567](https://github.com/matrix-org/matrix-react-sdk/pull/9567)). Fixes vector-im/element-web#23746.
|
||||
* Resilience fix for homeserver without thread notification support ([\#9565](https://github.com/matrix-org/matrix-react-sdk/pull/9565)).
|
||||
* Don't switch to the home page needlessly after leaving a room ([\#9477](https://github.com/matrix-org/matrix-react-sdk/pull/9477)).
|
||||
* Differentiate download and decryption errors when showing images ([\#9562](https://github.com/matrix-org/matrix-react-sdk/pull/9562)). Fixes vector-im/element-web#3892.
|
||||
* Close context menu when a modal is opened to prevent user getting stuck ([\#9560](https://github.com/matrix-org/matrix-react-sdk/pull/9560)). Fixes vector-im/element-web#15610 and vector-im/element-web#10781.
|
||||
* Fix TimelineReset handling when no room associated ([\#9553](https://github.com/matrix-org/matrix-react-sdk/pull/9553)).
|
||||
* Always use current profile on thread events ([\#9524](https://github.com/matrix-org/matrix-react-sdk/pull/9524)). Fixes vector-im/element-web#23648.
|
||||
* Fix `ThreadView` tests not using thread flag ([\#9547](https://github.com/matrix-org/matrix-react-sdk/pull/9547)).
|
||||
* Fix regressions around media uploads failing and causing soft crashes ([\#9549](https://github.com/matrix-org/matrix-react-sdk/pull/9549)). Fixes matrix-org/element-web-rageshakes#16831, matrix-org/element-web-rageshakes#16824 matrix-org/element-web-rageshakes#16810 and vector-im/element-web#23641.
|
||||
* Handle deletion of `m.call` events ([\#9540](https://github.com/matrix-org/matrix-react-sdk/pull/9540)). Fixes vector-im/element-web#23663.
|
||||
* Fix /myroomavatar slash command ([\#9536](https://github.com/matrix-org/matrix-react-sdk/pull/9536)). Fixes matrix-org/synapse#14321.
|
||||
* Fix incorrect notification count after leaving a room with notifications ([\#9518](https://github.com/matrix-org/matrix-react-sdk/pull/9518)). Contributed by @Arnei.
|
||||
|
||||
Changes in [1.11.14](https://github.com/vector-im/element-desktop/releases/tag/v1.11.14) (2022-11-08)
|
||||
=====================================================================================================
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
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 https://github.com/vector-im/element-builder/
|
||||
|
||||
# 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).
|
||||
|
||||
@@ -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: libsqlcipher0
|
||||
Recommends: libappindicator3-1, libsqlcipher0
|
||||
Section: net
|
||||
Priority: extra
|
||||
Homepage: https://element.io/
|
||||
|
||||
@@ -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: libsqlcipher0
|
||||
Recommends: libappindicator3-1, libsqlcipher0
|
||||
Replaces: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)
|
||||
Breaks: riot-desktop (<< 1.7.0), riot-web (<< 1.7.0)
|
||||
Section: net
|
||||
|
||||
@@ -32,7 +32,7 @@ export default async function(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promi
|
||||
await buildMatrixSeshat(hakEnv, moduleInfo);
|
||||
}
|
||||
|
||||
async function buildOpenSslWin(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
async function buildOpenSslWin(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
|
||||
const version = moduleInfo.cfg.dependencies.openssl;
|
||||
const openSslDir = path.join(moduleInfo.moduleTargetDotHakDir, `openssl-${version}`);
|
||||
|
||||
@@ -134,7 +134,7 @@ async function buildOpenSslWin(hakEnv: HakEnv, moduleInfo: DependencyInfo): Prom
|
||||
});
|
||||
}
|
||||
|
||||
async function buildSqlCipherWin(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
async function buildSqlCipherWin(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
|
||||
const version = moduleInfo.cfg.dependencies.sqlcipher;
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`);
|
||||
const buildDir = path.join(sqlCipherDir, 'bld');
|
||||
@@ -171,7 +171,7 @@ async function buildSqlCipherWin(hakEnv: HakEnv, moduleInfo: DependencyInfo): Pr
|
||||
);
|
||||
}
|
||||
|
||||
async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
|
||||
const version = moduleInfo.cfg.dependencies.sqlcipher;
|
||||
const sqlCipherDir = path.join(moduleInfo.moduleTargetDotHakDir, `sqlcipher-${version}`);
|
||||
|
||||
@@ -268,7 +268,7 @@ async function buildSqlCipherUnix(hakEnv: HakEnv, moduleInfo: DependencyInfo): P
|
||||
});
|
||||
}
|
||||
|
||||
async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<void> {
|
||||
async function buildMatrixSeshat(hakEnv: HakEnv, moduleInfo: DependencyInfo) {
|
||||
// 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.
|
||||
|
||||
@@ -18,20 +18,12 @@ 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 fetch from 'node-fetch';
|
||||
import { promises as stream } from "stream";
|
||||
|
||||
import HakEnv from '../../scripts/hak/hakEnv';
|
||||
import { DependencyInfo } from '../../scripts/hak/dep';
|
||||
|
||||
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);
|
||||
@@ -65,7 +57,11 @@ async function getSqlCipher(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise
|
||||
haveSqlcipherTar = false;
|
||||
}
|
||||
if (!haveSqlcipherTar) {
|
||||
await download(`https://github.com/sqlcipher/sqlcipher/archive/v${version}.tar.gz`, sqlCipherTarball);
|
||||
const bob = needle('get', `https://github.com/sqlcipher/sqlcipher/archive/v${version}.tar.gz`, {
|
||||
follow: 10,
|
||||
output: sqlCipherTarball,
|
||||
});
|
||||
await bob;
|
||||
}
|
||||
|
||||
// Extract the tarball to per-target directories, then we avoid cross-contaiminating archs
|
||||
@@ -122,7 +118,10 @@ async function getOpenSsl(hakEnv: HakEnv, moduleInfo: DependencyInfo): Promise<v
|
||||
haveOpenSslTar = false;
|
||||
}
|
||||
if (!haveOpenSslTar) {
|
||||
await download(`https://www.openssl.org/source/openssl-${version}.tar.gz`, openSslTarball);
|
||||
await needle('get', `https://www.openssl.org/source/openssl-${version}.tar.gz`, {
|
||||
follow: 10,
|
||||
output: openSslTarball,
|
||||
});
|
||||
}
|
||||
|
||||
console.log("extracting " + openSslTarball + " in " + moduleInfo.moduleTargetDotHakDir);
|
||||
|
||||
46
package.json
46
package.json
@@ -2,7 +2,7 @@
|
||||
"name": "element-desktop",
|
||||
"productName": "Element",
|
||||
"main": "lib/electron-main.js",
|
||||
"version": "1.11.17",
|
||||
"version": "1.11.14",
|
||||
"description": "A feature-rich client for Matrix.org",
|
||||
"author": "Element",
|
||||
"repository": {
|
||||
@@ -16,13 +16,13 @@
|
||||
"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 && ts-node scripts/fetch-package.ts",
|
||||
"fetch": "yarn run mkdirs && node scripts/fetch-package.js",
|
||||
"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/tsconfig.json --noEmit && tsc -p hak/tsconfig.json --noEmit",
|
||||
"lint:types": "tsc --noEmit && tsc -p scripts/hak/tsconfig.json --noEmit && tsc -p hak/tsconfig.json --noEmit",
|
||||
"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,7 +30,7 @@
|
||||
"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": "ts-node scripts/copy-res.ts",
|
||||
"build:res": "node scripts/copy-res.js",
|
||||
"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",
|
||||
@@ -46,64 +46,62 @@
|
||||
"electron-store": "^8.0.2",
|
||||
"electron-window-state": "^5.0.3",
|
||||
"minimist": "^1.2.6",
|
||||
"node-fetch": "^2",
|
||||
"png-to-ico": "^2.1.1"
|
||||
"png-to-ico": "^2.1.1",
|
||||
"request": "^2.88.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@aws-sdk/client-s3": "^3.213.0",
|
||||
"@babel/core": "^7.18.10",
|
||||
"@babel/preset-env": "^7.18.10",
|
||||
"@babel/preset-typescript": "^7.18.6",
|
||||
"@electron/asar": "^3.2.0",
|
||||
"@electron/notarize": "^1.2.3",
|
||||
"@types/auto-launch": "^5.0.1",
|
||||
"@types/counterpart": "^0.18.1",
|
||||
"@types/detect-libc": "^1.0.0",
|
||||
"@types/jest": "^29.0.0",
|
||||
"@types/jest": "^28",
|
||||
"@types/minimist": "^1.2.1",
|
||||
"@types/mkdirp": "^1.0.2",
|
||||
"@types/node": "16.18.4",
|
||||
"@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",
|
||||
"babel-jest": "^29.0.0",
|
||||
"asar": "^2.0.1",
|
||||
"babel-jest": "^28.1.3",
|
||||
"chokidar": "^3.5.2",
|
||||
"detect-libc": "^1.0.3",
|
||||
"electron": "^22.0.0",
|
||||
"electron": "^21",
|
||||
"electron-builder": "^23.6.0",
|
||||
"electron-builder-squirrel-windows": "^23.6.0",
|
||||
"electron-devtools-installer": "^3.1.1",
|
||||
"eslint": "^8.26.0",
|
||||
"eslint-config-google": "^0.14.0",
|
||||
"eslint-plugin-import": "^2.25.4",
|
||||
"eslint-plugin-matrix-org": "^0.8.0",
|
||||
"eslint-plugin-unicorn": "^45.0.0",
|
||||
"eslint-plugin-matrix-org": "^0.7.0",
|
||||
"eslint-plugin-unicorn": "^44.0.2",
|
||||
"expect-playwright": "^0.8.0",
|
||||
"find-npm-prefix": "^1.0.2",
|
||||
"fs-extra": "^11.0.0",
|
||||
"glob": "^8.0.0",
|
||||
"jest": "^29.0.0",
|
||||
"fs-extra": "^8.1.0",
|
||||
"glob": "^7.1.6",
|
||||
"jest": "^28",
|
||||
"matrix-web-i18n": "^1.3.0",
|
||||
"mkdirp": "^1.0.3",
|
||||
"node-pre-gyp": "^0.17.0",
|
||||
"pacote": "^15.0.0",
|
||||
"needle": "^2.5.0",
|
||||
"node-pre-gyp": "^0.15.0",
|
||||
"pacote": "^11.3.5",
|
||||
"playwright": "^1.25.0",
|
||||
"rimraf": "^3.0.2",
|
||||
"tar": "^6.1.2",
|
||||
"ts-jest": "^29.0.0",
|
||||
"ts-node": "^10.9.1",
|
||||
"typescript": "4.9.3"
|
||||
"ts-jest": "^28.0.8",
|
||||
"ts-node": "^10.4.0",
|
||||
"typescript": "4.5.5"
|
||||
},
|
||||
"hakDependencies": {
|
||||
"matrix-seshat": "^2.3.3",
|
||||
"keytar": "^7.9.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"@types/node": "16.18.4"
|
||||
"@types/node": "16.11.38"
|
||||
},
|
||||
"build": {
|
||||
"appId": "im.riot.app",
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=JVma
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
Binary file not shown.
@@ -1,58 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=JVma
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
@@ -1,65 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
l91/+ZrRJQ==
|
||||
=kDqh
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,58 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=LKM4
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
Binary file not shown.
@@ -1,63 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=DjWl
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,198 +0,0 @@
|
||||
@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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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-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");
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------
|
||||
Variable font.
|
||||
Usage:
|
||||
|
||||
html { font-family: 'Inter', sans-serif; }
|
||||
@supports (font-variation-settings: normal) {
|
||||
html { font-family: 'Inter var', sans-serif; }
|
||||
}
|
||||
*/
|
||||
@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-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");
|
||||
}
|
||||
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
[EXPERIMENTAL] Multi-axis, single variable font.
|
||||
|
||||
Slant axis is not yet widely supported (as of February 2019) and thus this
|
||||
multi-axis single variable font is opt-in rather than the default.
|
||||
|
||||
When using this, you will probably need to set font-variation-settings
|
||||
explicitly, e.g.
|
||||
|
||||
* { font-variation-settings: "slnt" 0deg }
|
||||
.italic { font-variation-settings: "slnt" 10deg }
|
||||
|
||||
*/
|
||||
@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");
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
<svg width="518" height="112" viewBox="0 0 518 112" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M56 112C86.9279 112 112 86.9279 112 56C112 25.0721 86.9279 0 56 0C25.0721 0 0 25.0721 0 56C0 86.9279 25.0721 112 56 112Z" fill="#0DBD8B"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M45.7615 26.093C45.7615 23.8325 47.5977 22.0001 49.8629 22.0001C65.2154 22.0001 77.6611 34.4199 77.6611 49.7406C77.6611 52.001 75.8248 53.8335 73.5597 53.8335C71.2945 53.8335 69.4583 52.001 69.4583 49.7406C69.4583 38.9408 60.6851 30.1859 49.8629 30.1859C47.5977 30.1859 45.7615 28.3534 45.7615 26.093Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M85.8986 45.6477C88.1637 45.6477 89.9999 47.4801 89.9999 49.7406C89.9999 65.0612 77.5543 77.4811 62.2017 77.4811C59.9366 77.4811 58.1003 75.6486 58.1003 73.3882C58.1003 71.1277 59.9366 69.2953 62.2017 69.2953C73.024 69.2953 81.7972 60.5403 81.7972 49.7406C81.7972 47.4801 83.6334 45.6477 85.8986 45.6477Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M66.3031 85.907C66.3031 88.1675 64.4668 89.9999 62.2017 89.9999C46.8492 89.9999 34.4035 77.58 34.4035 62.2594C34.4035 59.9989 36.2398 58.1665 38.5049 58.1665C40.77 58.1665 42.6063 59.9989 42.6063 62.2594C42.6063 73.0592 51.3795 81.8141 62.2017 81.8141C64.4668 81.8141 66.3031 83.6466 66.3031 85.907Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M26.1014 66.3523C23.8363 66.3523 22.0001 64.5199 22.0001 62.2594C22 46.9388 34.4457 34.5189 49.7983 34.5189C52.0634 34.5189 53.8997 36.3514 53.8997 38.6118C53.8997 40.8723 52.0634 42.7047 49.7983 42.7047C38.976 42.7047 30.2028 51.4597 30.2028 62.2594C30.2028 64.5199 28.3666 66.3523 26.1014 66.3523Z" fill="white"/>
|
||||
<path d="M197 63.5H157.5C157.967 67.6333 159.467 70.9333 162 73.4C164.533 75.8 167.867 77 172 77C174.733 77 177.2 76.3333 179.4 75C181.6 73.6667 183.167 71.8667 184.1 69.6H196.1C194.5 74.8667 191.5 79.1333 187.1 82.4C182.767 85.6 177.633 87.2 171.7 87.2C163.967 87.2 157.7 84.6333 152.9 79.5C148.167 74.3667 145.8 67.8667 145.8 60C145.8 52.3333 148.2 45.9 153 40.7C157.8 35.5 164 32.9 171.6 32.9C179.2 32.9 185.333 35.4667 190 40.6C194.733 45.6667 197.1 52.0667 197.1 59.8L197 63.5ZM171.6 42.6C167.867 42.6 164.767 43.7 162.3 45.9C159.833 48.1 158.3 51.0333 157.7 54.7H185.3C184.767 51.0333 183.3 48.1 180.9 45.9C178.5 43.7 175.4 42.6 171.6 42.6ZM205.289 70.5V11H217.189V70.7C217.189 73.3667 218.656 74.7 221.589 74.7L223.689 74.6V85.9C222.556 86.1 221.356 86.2 220.089 86.2C214.956 86.2 211.189 84.9 208.789 82.3C206.456 79.7 205.289 75.7667 205.289 70.5ZM279.109 63.5H239.609C240.076 67.6333 241.576 70.9333 244.109 73.4C246.643 75.8 249.976 77 254.109 77C256.843 77 259.309 76.3333 261.509 75C263.709 73.6667 265.276 71.8667 266.209 69.6H278.209C276.609 74.8667 273.609 79.1333 269.209 82.4C264.876 85.6 259.743 87.2 253.809 87.2C246.076 87.2 239.809 84.6333 235.009 79.5C230.276 74.3667 227.909 67.8667 227.909 60C227.909 52.3333 230.309 45.9 235.109 40.7C239.909 35.5 246.109 32.9 253.709 32.9C261.309 32.9 267.443 35.4667 272.109 40.6C276.843 45.6667 279.209 52.0667 279.209 59.8L279.109 63.5ZM253.709 42.6C249.976 42.6 246.876 43.7 244.409 45.9C241.943 48.1 240.409 51.0333 239.809 54.7H267.409C266.876 51.0333 265.409 48.1 263.009 45.9C260.609 43.7 257.509 42.6 253.709 42.6ZM332.798 56.2V86H320.898V54.9C320.898 47.0333 317.632 43.1 311.098 43.1C307.565 43.1 304.732 44.2333 302.598 46.5C300.532 48.7667 299.498 51.8667 299.498 55.8V86H287.598V34.1H298.598V41C299.865 38.6667 301.798 36.7333 304.398 35.2C306.998 33.6667 310.232 32.9 314.098 32.9C321.298 32.9 326.498 35.6333 329.698 41.1C334.098 35.6333 339.965 32.9 347.298 32.9C353.365 32.9 358.032 34.8 361.298 38.6C364.565 42.3333 366.198 47.2667 366.198 53.4V86H354.298V54.9C354.298 47.0333 351.032 43.1 344.498 43.1C340.898 43.1 338.032 44.2667 335.898 46.6C333.832 48.8667 332.798 52.0667 332.798 56.2ZM425.379 63.5H385.879C386.346 67.6333 387.846 70.9333 390.379 73.4C392.912 75.8 396.246 77 400.379 77C403.112 77 405.579 76.3333 407.779 75C409.979 73.6667 411.546 71.8667 412.479 69.6H424.479C422.879 74.8667 419.879 79.1333 415.479 82.4C411.146 85.6 406.012 87.2 400.079 87.2C392.346 87.2 386.079 84.6333 381.279 79.5C376.546 74.3667 374.179 67.8667 374.179 60C374.179 52.3333 376.579 45.9 381.379 40.7C386.179 35.5 392.379 32.9 399.979 32.9C407.579 32.9 413.712 35.4667 418.379 40.6C423.112 45.6667 425.479 52.0667 425.479 59.8L425.379 63.5ZM399.979 42.6C396.246 42.6 393.146 43.7 390.679 45.9C388.212 48.1 386.679 51.0333 386.079 54.7H413.679C413.146 51.0333 411.679 48.1 409.279 45.9C406.879 43.7 403.779 42.6 399.979 42.6ZM444.868 34.1V41C446.068 38.7333 448.035 36.8333 450.768 35.3C453.568 33.7 456.935 32.9 460.868 32.9C467.001 32.9 471.735 34.7667 475.068 38.5C478.468 42.2333 480.168 47.2 480.168 53.4V86H468.268V54.9C468.268 51.2333 467.401 48.3667 465.668 46.3C464.001 44.1667 461.435 43.1 457.968 43.1C454.168 43.1 451.168 44.2333 448.968 46.5C446.835 48.7667 445.768 51.9 445.768 55.9V86H433.868V34.1H444.868ZM514.922 75.4V85.7C513.455 86.1 511.389 86.3 508.722 86.3C498.589 86.3 493.522 81.2 493.522 71V43.6H485.622V34.1H493.522V20.6H505.422V34.1H515.122V43.6H505.422V69.8C505.422 73.8667 507.355 75.9 511.222 75.9L514.922 75.4Z" fill="black"/>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 5.2 KiB |
@@ -1,58 +0,0 @@
|
||||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=LKM4
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
||||
Binary file not shown.
@@ -1,333 +0,0 @@
|
||||
/* styles.css
|
||||
* Better styling for of Nginx FancyIndex page
|
||||
* © 2015-17, Lilian Besson (Naereen) and contributors,
|
||||
* open-sourced under the MIT License, https://lbesson.mit-license.org/
|
||||
* hosted on GitHub, https://GitHub.com/Naereen/Nginx-Fancyindex-Theme
|
||||
*/
|
||||
|
||||
@import url('./fonts/inter.css');
|
||||
|
||||
* { font-family: 'Inter', sans-serif; }
|
||||
@supports (font-variation-settings: normal) {
|
||||
* { font-family: 'Inter var', sans-serif; }
|
||||
}
|
||||
|
||||
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
color: #17191C;
|
||||
font-weight: 400;
|
||||
font-size: 1em;
|
||||
line-height: 1.6em;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: #F4F6FA;
|
||||
margin: 0 auto;
|
||||
padding: 100px 20px 20px;
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
thead {
|
||||
font-weight: 300;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
font-size: 1.6em;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #545454;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #0DBD8B;
|
||||
}
|
||||
a.clear, a.clear:link, a.clear:visited {
|
||||
color: #666;
|
||||
padding: 2px 0;
|
||||
font-weight: 400;
|
||||
font-size: 14px;
|
||||
margin: 0 0 0 20px;
|
||||
line-height: 14px;
|
||||
display: inline-block;
|
||||
border-bottom: transparent 1px solid;
|
||||
vertical-align: -10px;
|
||||
-webkit-transition: all 300ms ease-in;
|
||||
-moz-transition: all 300ms ease-in;
|
||||
-ms-transition: all 300ms ease-in;
|
||||
-o-transition: all 300ms ease-in;
|
||||
transition: all 300ms ease-in;
|
||||
}
|
||||
|
||||
input {
|
||||
vertical-align: middle;
|
||||
*overflow: visible;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-weight: 300;
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
padding: 4px 32px 4px 6px;
|
||||
margin: 0 auto 9px;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #555;
|
||||
-webkit-border-radius: 3px;
|
||||
-moz-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
input::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
font-size: 1em;
|
||||
max-width: 100%;
|
||||
margin: 20px auto 0;
|
||||
}
|
||||
|
||||
tr {
|
||||
outline: 0;
|
||||
border: 0;
|
||||
}
|
||||
tr:hover td {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
tr td:first-of-type {
|
||||
padding-left: 10px;
|
||||
padding-right: 10px;
|
||||
}
|
||||
tr.parent a {
|
||||
color: #9099A3;
|
||||
}
|
||||
|
||||
th {
|
||||
|
||||
text-align: left;
|
||||
font-size: .75em;
|
||||
padding-right: 20px;
|
||||
}
|
||||
th + th {
|
||||
width: 25%;
|
||||
}
|
||||
th + th + th + th {
|
||||
width: 5%;
|
||||
}
|
||||
|
||||
td {
|
||||
padding: 5px 0;
|
||||
outline: 0;
|
||||
border: 0;
|
||||
border-bottom: 1px solid #edf1f5;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
-webkit-transition: background 300ms ease-in;
|
||||
-moz-transition: background 300ms ease-in;
|
||||
-ms-transition: background 300ms ease-in;
|
||||
-o-transition: background 300ms ease-in;
|
||||
transition: background 300ms ease-in;
|
||||
}
|
||||
td:last-child,th:last-child {
|
||||
text-align: right;
|
||||
padding-right: 0;
|
||||
}
|
||||
td a {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.parent a:hover {
|
||||
color: #2a2a2a;
|
||||
}
|
||||
|
||||
/* nav */
|
||||
|
||||
.nav {
|
||||
background-color: #fff;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 3;
|
||||
padding-left: 0;
|
||||
padding-right: 0;
|
||||
}
|
||||
|
||||
.nav ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
overflow: hidden;
|
||||
background-color: #FFF;
|
||||
}
|
||||
|
||||
.nav li a {
|
||||
color: #17191C;
|
||||
display: block;
|
||||
padding: 20px 20px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.nav li a:hover,
|
||||
.nav .menu-btn:hover {
|
||||
color: #0DBD8B;
|
||||
}
|
||||
|
||||
.nav .logo {
|
||||
display: block;
|
||||
float: left;
|
||||
font-size: 2em;
|
||||
padding-top: 18px;
|
||||
padding-left: 20px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/* menu */
|
||||
|
||||
.nav .menu {
|
||||
clear: both;
|
||||
max-height: 0;
|
||||
transition: max-height .2s ease-out;
|
||||
}
|
||||
|
||||
/* menu icon */
|
||||
|
||||
.nav .menu-icon {
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
float: right;
|
||||
padding: 28px 20px;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.nav .menu-icon .navicon {
|
||||
background: #fff;
|
||||
display: block;
|
||||
height: 2px;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 4px;
|
||||
position: relative;
|
||||
transition: background .2s ease-out;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
.nav .menu-icon .navicon:before,
|
||||
.nav .menu-icon .navicon:after {
|
||||
background: #17191C;
|
||||
content: '';
|
||||
display: block;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
transition: all .2s ease-out;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.nav .menu-icon .navicon:before {
|
||||
top: 5px;
|
||||
}
|
||||
|
||||
.nav .menu-icon .navicon:after {
|
||||
top: -5px;
|
||||
}
|
||||
|
||||
/* menu btn */
|
||||
|
||||
.nav .menu-btn {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.nav .menu-btn:checked ~ .menu {
|
||||
max-height: 100%;
|
||||
}
|
||||
|
||||
.nav .menu-btn:checked ~ .menu-icon .navicon {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
.nav .menu-btn:checked ~ .menu-icon .navicon:before {
|
||||
transform: rotate(-45deg);
|
||||
}
|
||||
|
||||
.nav .menu-btn:checked ~ .menu-icon .navicon:after {
|
||||
transform: rotate(45deg);
|
||||
}
|
||||
|
||||
.nav .menu-btn:checked ~ .menu-icon:not(.steps) .navicon:before,
|
||||
.nav .menu-btn:checked ~ .menu-icon:not(.steps) .navicon:after {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
@media (min-width: 72em) {
|
||||
.nav {
|
||||
padding-left: 200px;
|
||||
padding-right: 200px;
|
||||
}
|
||||
.nav li {
|
||||
float: left;
|
||||
}
|
||||
.nav li a {
|
||||
padding: 20px 22px;
|
||||
}
|
||||
.nav .primary {
|
||||
margin-top: 8px;
|
||||
margin-left: 20px;
|
||||
padding: 12px 20px;
|
||||
border-radius: 100px;
|
||||
background-color: #0DBD8B;
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
.nav .primary:hover {
|
||||
background-color: #099970;
|
||||
color:#FFF;
|
||||
}
|
||||
|
||||
.nav .menu {
|
||||
clear: none;
|
||||
float: right;
|
||||
max-height: none;
|
||||
}
|
||||
.nav .menu-icon {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
footer {
|
||||
margin-top: 40px;
|
||||
font-size:0.8em;
|
||||
text-align:center;
|
||||
}
|
||||
|
||||
footer a {
|
||||
color:#03b381;
|
||||
}
|
||||
@@ -1,18 +1,18 @@
|
||||
#!/usr/bin/env -S npx ts-node
|
||||
#!/usr/bin/env node
|
||||
|
||||
// copies resources into the lib directory.
|
||||
|
||||
import parseArgs from "minimist";
|
||||
import * as chokidar from "chokidar";
|
||||
import * as path from "path";
|
||||
import * as fs from "fs";
|
||||
const parseArgs = require('minimist');
|
||||
const chokidar = require('chokidar');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
const argv = parseArgs(process.argv.slice(2), {});
|
||||
|
||||
const watch = argv.w;
|
||||
const verbose = argv.v;
|
||||
|
||||
function errCheck(err?: Error): void {
|
||||
function errCheck(err) {
|
||||
if (err) {
|
||||
console.error(err.message);
|
||||
process.exit(1);
|
||||
@@ -25,14 +25,15 @@ const INCLUDE_LANGS = fs.readdirSync(I18N_BASE_PATH).filter(fn => fn.endsWith(".
|
||||
// Ensure lib, lib/i18n and lib/i18n/strings all exist
|
||||
fs.mkdirSync('lib/i18n/strings', { recursive: true });
|
||||
|
||||
type Translations = Record<string, Record<string, string> | string>;
|
||||
|
||||
function genLangFile(file: string, dest: string): void {
|
||||
const inTrs: Record<string, string> = {};
|
||||
function genLangFile(file, dest) {
|
||||
let translations = {};
|
||||
[file].forEach(function(f) {
|
||||
if (fs.existsSync(f)) {
|
||||
try {
|
||||
Object.assign(inTrs, JSON.parse(fs.readFileSync(f).toString()));
|
||||
Object.assign(
|
||||
translations,
|
||||
JSON.parse(fs.readFileSync(f).toString()),
|
||||
);
|
||||
} catch (e) {
|
||||
console.error("Failed: " + f, e);
|
||||
throw e;
|
||||
@@ -40,7 +41,8 @@ function genLangFile(file: string, dest: string): void {
|
||||
}
|
||||
});
|
||||
|
||||
const translations = weblateToCounterpart(inTrs);
|
||||
translations = weblateToCounterpart(translations);
|
||||
|
||||
const json = JSON.stringify(translations, null, 4);
|
||||
const filename = path.basename(file);
|
||||
|
||||
@@ -64,8 +66,8 @@ function genLangFile(file: string, dest: string): void {
|
||||
* "other": "%(count)s badgers"
|
||||
* }
|
||||
*/
|
||||
function weblateToCounterpart(inTrs: Record<string, string>): Translations {
|
||||
const outTrs: Translations = {};
|
||||
function weblateToCounterpart(inTrs) {
|
||||
const outTrs = {};
|
||||
|
||||
for (const key of Object.keys(inTrs)) {
|
||||
const keyParts = key.split('|', 2);
|
||||
@@ -94,12 +96,12 @@ function weblateToCounterpart(inTrs: Record<string, string>): Translations {
|
||||
watch the input files for a given language,
|
||||
regenerate the file, and regenerating languages.json with the new filename
|
||||
*/
|
||||
function watchLanguage(file: string, dest: string): void {
|
||||
function watchLanguage(file, dest) {
|
||||
// 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: NodeJS.Timeout | undefined;
|
||||
const makeLang = (): void => {
|
||||
let makeLangDebouncer;
|
||||
const makeLang = () => {
|
||||
if (makeLangDebouncer) {
|
||||
clearTimeout(makeLangDebouncer);
|
||||
}
|
||||
@@ -116,7 +118,7 @@ function watchLanguage(file: string, dest: string): void {
|
||||
|
||||
// language resources
|
||||
const I18N_DEST = "lib/i18n/strings/";
|
||||
INCLUDE_LANGS.forEach((file): void => {
|
||||
INCLUDE_LANGS.forEach((file) => {
|
||||
genLangFile(I18N_BASE_PATH + file, I18N_DEST);
|
||||
}, {});
|
||||
|
||||
@@ -1,40 +1,42 @@
|
||||
#!/usr/bin/env -S npx ts-node --resolveJsonModule
|
||||
#!/usr/bin/env node
|
||||
|
||||
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 "asar";
|
||||
import fetch from "node-fetch";
|
||||
import { promises as stream } from "stream";
|
||||
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 riotDesktopPackageJson from "../package.json";
|
||||
import { setPackageVersion } from "./set-version";
|
||||
const riotDesktopPackageJson = require('../package.json');
|
||||
const { setPackageVersion } = require('./set-version.js');
|
||||
|
||||
const PUB_KEY_URL = "https://packages.riot.im/element-release-key.asc";
|
||||
const PACKAGE_URL_PREFIX = "https://github.com/vector-im/element-web/releases/download/";
|
||||
const DEVELOP_TGZ_URL = "https://develop.element.io/develop.tar.gz";
|
||||
const ASAR_PATH = 'webapp.asar';
|
||||
|
||||
async function downloadToFile(url: string, filename: string): Promise<void> {
|
||||
async function downloadToFile(url, filename) {
|
||||
console.log("Downloading " + url + "...");
|
||||
|
||||
try {
|
||||
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));
|
||||
await needle('get', url, null,
|
||||
{
|
||||
follow_max: 5,
|
||||
output: filename,
|
||||
},
|
||||
);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
try {
|
||||
await fs.unlink(filename);
|
||||
await fsPromises.unlink(filename);
|
||||
} catch (_) {}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
async function verifyFile(filename: string): Promise<void> {
|
||||
return new Promise<void>((resolve, reject) => {
|
||||
async function verifyFile(filename) {
|
||||
return new Promise((resolve, reject) => {
|
||||
childProcess.execFile('gpg', ['--verify', filename + '.asc', filename], (error) => {
|
||||
if (error) {
|
||||
reject(error);
|
||||
@@ -45,15 +47,15 @@ async function verifyFile(filename: string): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
async function main(): Promise<number | undefined> {
|
||||
async function main() {
|
||||
let verify = true;
|
||||
let importkey = false;
|
||||
let pkgDir = 'packages';
|
||||
let deployDir = 'deploys';
|
||||
let cfgDir: string | undefined;
|
||||
let targetVersion: string | undefined;
|
||||
let filename: string | undefined;
|
||||
let url: string | undefined;
|
||||
let cfgDir;
|
||||
let targetVersion;
|
||||
let filename;
|
||||
let url;
|
||||
let setVersion = false;
|
||||
|
||||
while (process.argv.length > 2) {
|
||||
@@ -102,7 +104,7 @@ async function main(): Promise<number | undefined> {
|
||||
url = PACKAGE_URL_PREFIX + targetVersion + '/' + filename;
|
||||
}
|
||||
|
||||
const haveGpg = await new Promise<boolean>((resolve) => {
|
||||
const haveGpg = await new Promise((resolve) => {
|
||||
childProcess.execFile('gpg', ['--version'], (error) => {
|
||||
resolve(!error);
|
||||
});
|
||||
@@ -114,7 +116,7 @@ async function main(): Promise<number | undefined> {
|
||||
return 1;
|
||||
}
|
||||
|
||||
await new Promise<boolean>((resolve) => {
|
||||
await new Promise((resolve) => {
|
||||
const gpgProc = childProcess.execFile('gpg', ['--import'], (error) => {
|
||||
if (error) {
|
||||
console.log("Failed to import key", error);
|
||||
@@ -123,9 +125,7 @@ async function main(): Promise<number | undefined> {
|
||||
}
|
||||
resolve(!error);
|
||||
});
|
||||
fetch(PUB_KEY_URL).then(resp => {
|
||||
stream.pipeline(resp.body, gpgProc.stdin!);
|
||||
});
|
||||
needle.get(PUB_KEY_URL).pipe(gpgProc.stdin);
|
||||
});
|
||||
return 0;
|
||||
}
|
||||
@@ -154,7 +154,7 @@ async function main(): Promise<number | undefined> {
|
||||
if (!haveDeploy) {
|
||||
const outPath = path.join(pkgDir, filename);
|
||||
try {
|
||||
await fs.stat(outPath);
|
||||
await fsPromises.stat(outPath);
|
||||
console.log("Already have " + filename + ": not redownloading");
|
||||
} catch (e) {
|
||||
try {
|
||||
@@ -167,7 +167,7 @@ async function main(): Promise<number | undefined> {
|
||||
|
||||
if (verify) {
|
||||
try {
|
||||
await fs.stat(outPath+'.asc');
|
||||
await fsPromises.stat(outPath+'.asc');
|
||||
console.log("Already have " + filename + ".asc: not redownloading");
|
||||
} catch (e) {
|
||||
try {
|
||||
@@ -202,9 +202,9 @@ async function main(): Promise<number | undefined> {
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.stat(ASAR_PATH);
|
||||
await fsPromises.stat(ASAR_PATH);
|
||||
console.log(ASAR_PATH + " already present: removing");
|
||||
await fs.unlink(ASAR_PATH);
|
||||
await fsPromises.unlink(ASAR_PATH);
|
||||
} catch (e) {
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ async function main(): Promise<number | undefined> {
|
||||
const configJsonSource = path.join(cfgDir, 'config.json');
|
||||
const configJsonDest = path.join(expectedDeployDir, 'config.json');
|
||||
console.log(configJsonSource + ' -> ' + configJsonDest);
|
||||
await fs.copyFile(configJsonSource, configJsonDest);
|
||||
await fsPromises.copyFile(configJsonSource, configJsonDest);
|
||||
} else {
|
||||
console.log("Skipping config file");
|
||||
}
|
||||
@@ -221,7 +221,7 @@ async function main(): Promise<number | undefined> {
|
||||
await asar.createPackage(expectedDeployDir, ASAR_PATH);
|
||||
|
||||
if (setVersion) {
|
||||
const semVer = (await fs.readFile(path.join(expectedDeployDir, "version"), "utf-8")).trim();
|
||||
const semVer = fs.readFileSync(path.join(expectedDeployDir, "version"), "utf-8").trim();
|
||||
console.log("Updating version to " + semVer);
|
||||
await setPackageVersion(semVer);
|
||||
}
|
||||
@@ -1,202 +0,0 @@
|
||||
#!/usr/bin/env -S npx ts-node
|
||||
|
||||
import { S3Client, ListObjectsV2Command, PutObjectCommand, _Object } from "@aws-sdk/client-s3";
|
||||
|
||||
const HIDDEN_FILES = [
|
||||
"/styles.css",
|
||||
"/logo.svg",
|
||||
".DS_Store",
|
||||
"index.html",
|
||||
"/fonts/",
|
||||
"/nginx-theme/",
|
||||
".~tmp~/",
|
||||
"msi/",
|
||||
];
|
||||
|
||||
const Bucket = "packages-element-io";
|
||||
|
||||
if (!process.env.CF_R2_ACCESS_KEY_ID || !process.env.CF_R2_TOKEN || !process.env.CF_R2_S3_API) {
|
||||
console.error("Missing environment variables `CF_R2_ACCESS_KEY_ID`, `CF_R2_TOKEN`, `CF_R2_S3_API`");
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const client = new S3Client({
|
||||
region: "auto",
|
||||
endpoint: process.env.CF_R2_S3_API,
|
||||
credentials: {
|
||||
accessKeyId: process.env.CF_R2_ACCESS_KEY_ID,
|
||||
secretAccessKey: process.env.CF_R2_TOKEN,
|
||||
},
|
||||
});
|
||||
|
||||
const templateLayout = (content: string): string => `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="x-ua-compatible" content="IE=edge">
|
||||
<title>packages.element.io</title>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link rel="stylesheet" href="/styles.css">
|
||||
</head>
|
||||
<body>
|
||||
<nav class="nav">
|
||||
<a href="https://element.io/" class="logo">
|
||||
<img src="/logo.svg" height="30" />
|
||||
</a>
|
||||
<input class="menu-btn" type="checkbox" id="menu-btn" />
|
||||
<label class="menu-icon" for="menu-btn"><span class="navicon"></span></label>
|
||||
<ul class="menu">
|
||||
<li><a href="https://element.io/about">About</a></li>
|
||||
<li><a href="https://element.io/enterprise/collaboration-features">Features</a></li>
|
||||
<li><a href="https://element.io/help">Help</a></li>
|
||||
<li><a href="https://element.io/open-source">Open Source</a></li>
|
||||
<li><a href="https://element.io/get-started" class="primary">Get Started</a></li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<h1>Browse files & directories<span style="color:#0DBD8B;">.</span></h1>
|
||||
|
||||
${content}
|
||||
|
||||
<div id="raw_include_README_md"></div>
|
||||
<footer>
|
||||
<p>© 2022 New Vector Ltd.</p>
|
||||
<p><a href="https://element.io/privacy">Privacy</a></p>
|
||||
<p><a href="https://element.io/legal">Legal</a></p>
|
||||
</footer>
|
||||
</body>
|
||||
</html>
|
||||
`;
|
||||
|
||||
/**
|
||||
* Format bytes as human-readable text.
|
||||
* https://stackoverflow.com/a/14919494
|
||||
*
|
||||
* @param bytes Number of bytes.
|
||||
* @param si True to use metric (SI) units, aka powers of 1000. False to use
|
||||
* binary (IEC), aka powers of 1024.
|
||||
* @param dp Number of decimal places to display.
|
||||
*
|
||||
* @return Formatted string.
|
||||
*/
|
||||
function humanFileSize(bytes: number, si = false, dp = 1): string {
|
||||
const thresh = si ? 1000 : 1024;
|
||||
|
||||
if (Math.abs(bytes) < thresh) {
|
||||
return bytes + ' B';
|
||||
}
|
||||
|
||||
const units = si
|
||||
? ['kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB']
|
||||
: ['KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
||||
let u = -1;
|
||||
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];
|
||||
}
|
||||
|
||||
const dateTimeOptions: Intl.DateTimeFormatOptions = {
|
||||
year: "numeric",
|
||||
month: "short",
|
||||
day: "2-digit",
|
||||
hour: "2-digit",
|
||||
minute: "numeric",
|
||||
};
|
||||
|
||||
function indexLayout(prefix: string, files: _Object[], dirs: string[]): string {
|
||||
const rows: [link: string, name: string, size?: number, date?: Date][] = [];
|
||||
|
||||
if (prefix) {
|
||||
rows.push(["../index.html", "Parent directory/"]);
|
||||
}
|
||||
|
||||
for (const dir of dirs) {
|
||||
if (HIDDEN_FILES.includes(`${prefix}/${dir}/`) || HIDDEN_FILES.includes(`${dir}/`)) continue;
|
||||
rows.push([`${dir}/index.html`, dir]);
|
||||
}
|
||||
|
||||
for (const file of files) {
|
||||
if (!file.Key ||
|
||||
HIDDEN_FILES.includes(`/${file.Key}`) ||
|
||||
HIDDEN_FILES.includes(file.Key.slice(file.Key.lastIndexOf("/") + 1))
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
const name = file.Key.slice(prefix.length);
|
||||
rows.push([name, name, file.Size, file.LastModified]);
|
||||
}
|
||||
|
||||
return templateLayout(`
|
||||
<div>/${prefix}</div>
|
||||
<table id="list">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width:55%">File Name</th>
|
||||
<th style="width:20%">File Size</th>
|
||||
<th style="width:25%">Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${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("")}
|
||||
</tbody>
|
||||
</table>
|
||||
`);
|
||||
}
|
||||
|
||||
async function generateIndex(Prefix: string): Promise<{
|
||||
files: _Object[];
|
||||
dirs: string[];
|
||||
}> {
|
||||
console.info(`Generating index for prefix '${Prefix}'`);
|
||||
const command = new ListObjectsV2Command({
|
||||
Bucket,
|
||||
Delimiter: "/",
|
||||
Prefix,
|
||||
});
|
||||
|
||||
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 Body = indexLayout(Prefix, files, dirs);
|
||||
|
||||
await client.send(new PutObjectCommand({
|
||||
Body,
|
||||
Bucket,
|
||||
ContentType: "text/html",
|
||||
Key: Prefix + "index.html",
|
||||
}));
|
||||
|
||||
return { files, dirs };
|
||||
}
|
||||
|
||||
async function generateIndexRecursive(Prefix = ""): Promise<void> {
|
||||
const { dirs } = await generateIndex(Prefix);
|
||||
for (const dir of dirs) {
|
||||
await generateIndexRecursive(Prefix + dir + "/");
|
||||
}
|
||||
}
|
||||
|
||||
async function generateIndexList(prefixes: string[]): Promise<void> {
|
||||
for (const prefix of prefixes) {
|
||||
await generateIndex(prefix);
|
||||
}
|
||||
}
|
||||
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length) {
|
||||
generateIndexList(args);
|
||||
} else {
|
||||
generateIndexRecursive();
|
||||
}
|
||||
@@ -22,7 +22,7 @@ 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 | null) => {
|
||||
rimraf(moduleInfo.moduleDotHakDir, (err: Error) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
@@ -32,7 +32,7 @@ export default async function clean(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
rimraf(path.join(hakEnv.dotHakDir, 'links', moduleInfo.name), (err?: Error | null) => {
|
||||
rimraf(path.join(hakEnv.dotHakDir, 'links', moduleInfo.name), (err: Error) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
@@ -42,7 +42,7 @@ export default async function clean(hakEnv: HakEnv, moduleInfo: DependencyInfo):
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
rimraf(path.join(hakEnv.projectRoot, 'node_modules', moduleInfo.name), (err?: Error | null) => {
|
||||
rimraf(path.join(hakEnv.projectRoot, 'node_modules', moduleInfo.name), (err: Error) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
|
||||
19
scripts/hak/find-npm-prefix.d.ts
vendored
19
scripts/hak/find-npm-prefix.d.ts
vendored
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
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>;
|
||||
}
|
||||
@@ -37,27 +37,33 @@ 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;
|
||||
|
||||
public constructor(public readonly projectRoot: string, targetId: TargetId | null) {
|
||||
const target = targetId ? TARGETS[targetId] : getHost();
|
||||
constructor(public readonly projectRoot: string, targetId: TargetId | null) {
|
||||
if (targetId) {
|
||||
this.target = TARGETS[targetId];
|
||||
} else {
|
||||
this.target = getHost();
|
||||
}
|
||||
|
||||
if (!target) {
|
||||
if (!this.target) {
|
||||
throw new Error(`Unknown target ${targetId}!`);
|
||||
}
|
||||
this.target = target;
|
||||
this.dotHakDir = path.join(this.projectRoot, '.hak');
|
||||
}
|
||||
|
||||
public async init(): Promise<void> {
|
||||
public async init() {
|
||||
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}
|
||||
@@ -89,7 +95,7 @@ export default class HakEnv {
|
||||
return isHostId(this.target.id);
|
||||
}
|
||||
|
||||
public makeGypEnv(): Record<string, string | undefined> {
|
||||
public makeGypEnv(): Record<string, string> {
|
||||
return Object.assign({}, process.env, {
|
||||
npm_config_arch: this.target.arch,
|
||||
npm_config_target_arch: this.target.arch,
|
||||
@@ -101,6 +107,10 @@ 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';
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ const MODULECOMMANDS = [
|
||||
|
||||
// Shortcuts for multiple commands at once (useful for building universal binaries
|
||||
// because you can run the fetch/fetchDeps/build for each arch and then copy/link once)
|
||||
const METACOMMANDS: Record<string, string[]> = {
|
||||
const METACOMMANDS = {
|
||||
'fetchandbuild': ['check', 'fetch', 'fetchDeps', 'build'],
|
||||
'copyandlink': ['copy', 'link'],
|
||||
};
|
||||
@@ -51,7 +51,7 @@ const HAKSCRIPTS = [
|
||||
'build',
|
||||
];
|
||||
|
||||
async function main(): Promise<void> {
|
||||
async function main() {
|
||||
const prefix = await findNpmPrefix(process.cwd());
|
||||
let packageJson;
|
||||
try {
|
||||
|
||||
20
scripts/hak/node-pre-gyp.d.ts
vendored
20
scripts/hak/node-pre-gyp.d.ts
vendored
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
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;
|
||||
}
|
||||
@@ -1,15 +1,12 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"resolveJsonModule": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"target": "es2017",
|
||||
"module": "commonjs",
|
||||
"sourceMap": false,
|
||||
"strict": true,
|
||||
"lib": [
|
||||
"es2019",
|
||||
"dom"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
@@ -1,28 +1,29 @@
|
||||
#!/usr/bin/env -S npx ts-node
|
||||
#!/usr/bin/env 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 "asar";
|
||||
import * as childProcess from "child_process";
|
||||
const fs = require('fs').promises;
|
||||
const asar = require('asar');
|
||||
const childProcess = require('child_process');
|
||||
|
||||
export async function versionFromAsar(): Promise<string> {
|
||||
async function versionFromAsar() {
|
||||
try {
|
||||
await fs.stat('webapp.asar');
|
||||
} catch (e) {
|
||||
throw new Error("No 'webapp.asar' found. Run 'yarn run fetch'");
|
||||
console.log("No 'webapp.asar' found. Run 'yarn run fetch'");
|
||||
return 1;
|
||||
}
|
||||
|
||||
return asar.extractFile('webapp.asar', 'version').toString().trim();
|
||||
}
|
||||
|
||||
export async function setPackageVersion(ver: string): Promise<void> {
|
||||
async function setPackageVersion(ver) {
|
||||
// set version in package.json: electron-builder will use this to populate
|
||||
// all the various version fields
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
await new Promise((resolve, reject) => {
|
||||
childProcess.execFile(process.platform === 'win32' ? 'yarn.cmd' : 'yarn', [
|
||||
'version',
|
||||
'-s',
|
||||
@@ -39,20 +40,16 @@ export async function setPackageVersion(ver: string): Promise<void> {
|
||||
});
|
||||
}
|
||||
|
||||
async function main(args: string[]): Promise<number> {
|
||||
async function main(args) {
|
||||
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);
|
||||
});
|
||||
main(process.argv.slice(2)).then((ret) => process.exit(ret));
|
||||
}
|
||||
|
||||
module.exports = { versionFromAsar, setPackageVersion };
|
||||
43
src/@types/global.d.ts
vendored
43
src/@types/global.d.ts
vendored
@@ -20,26 +20,27 @@ import AutoLaunch from "auto-launch";
|
||||
|
||||
import { AppLocalization } from "../language-helper";
|
||||
|
||||
// global type extensions need to use var for whatever reason
|
||||
/* eslint-disable no-var */
|
||||
declare global {
|
||||
var mainWindow: BrowserWindow | null;
|
||||
var appQuitting: boolean;
|
||||
var appLocalization: AppLocalization;
|
||||
var launcher: AutoLaunch;
|
||||
var vectorConfig: Record<string, any>;
|
||||
var trayConfig: {
|
||||
// eslint-disable-next-line camelcase
|
||||
icon_path: string;
|
||||
brand: string;
|
||||
};
|
||||
var store: Store<{
|
||||
warnBeforeExit?: boolean;
|
||||
minimizeToTray?: boolean;
|
||||
spellCheckerEnabled?: boolean;
|
||||
autoHideMenuBar?: boolean;
|
||||
locale?: string | string[];
|
||||
disableHardwareAcceleration?: boolean;
|
||||
}>;
|
||||
namespace NodeJS {
|
||||
interface Global {
|
||||
mainWindow: BrowserWindow;
|
||||
appQuitting: boolean;
|
||||
appLocalization: AppLocalization;
|
||||
launcher: AutoLaunch;
|
||||
vectorConfig: Record<string, any>;
|
||||
trayConfig: {
|
||||
// eslint-disable-next-line camelcase
|
||||
icon_path: string;
|
||||
brand: string;
|
||||
};
|
||||
store: Store<{
|
||||
warnBeforeExit?: boolean;
|
||||
minimizeToTray?: boolean;
|
||||
spellCheckerEnabled?: boolean;
|
||||
autoHideMenuBar?: boolean;
|
||||
locale?: string | string[];
|
||||
disableHardwareAcceleration?: boolean;
|
||||
}>;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* eslint-enable no-var */
|
||||
|
||||
6
src/@types/matrix-seshat.d.ts
vendored
6
src/@types/matrix-seshat.d.ts
vendored
@@ -86,7 +86,7 @@ declare module "matrix-seshat" {
|
||||
}
|
||||
|
||||
export class Seshat {
|
||||
public constructor(path: string, config?: IConfig);
|
||||
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 {
|
||||
public constructor(path: string, config?: IConfig);
|
||||
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 {
|
||||
public constructor(message?: string);
|
||||
constructor(message?: string);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,8 +126,6 @@ async function tryPaths(name: string, root: string, rawPaths: string[]): Promise
|
||||
throw new Error(`Failed to find ${name} files`);
|
||||
}
|
||||
|
||||
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.
|
||||
@@ -170,14 +168,12 @@ async function setupGlobals(): Promise<void> {
|
||||
// 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))) {
|
||||
const homeserverProps = ['default_is_url', 'default_hs_url', 'default_server_name', 'default_server_config'];
|
||||
if (Object.keys(localConfig).find(k => homeserverProps.includes(k))) {
|
||||
// Rip out all the homeserver options from the vector config
|
||||
global.vectorConfig = Object.keys(global.vectorConfig)
|
||||
.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>);
|
||||
.filter(k => !homeserverProps.includes(k))
|
||||
.reduce((obj, key) => {obj[key] = global.vectorConfig[key]; return obj;}, {});
|
||||
}
|
||||
|
||||
global.vectorConfig = Object.assign(global.vectorConfig, localConfig);
|
||||
@@ -238,9 +234,9 @@ global.store = new Store({ name: "electron-config" });
|
||||
global.appQuitting = false;
|
||||
|
||||
const exitShortcuts: Array<(input: Input, platform: string) => boolean> = [
|
||||
(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',
|
||||
(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',
|
||||
];
|
||||
|
||||
const warnBeforeExit = (event: Event, input: Input): void => {
|
||||
@@ -248,7 +244,7 @@ const warnBeforeExit = (event: Event, input: Input): void => {
|
||||
const exitShortcutPressed =
|
||||
input.type === 'keyDown' && exitShortcuts.some(shortcutFn => shortcutFn(input, process.platform));
|
||||
|
||||
if (shouldWarnBeforeExit && exitShortcutPressed && global.mainWindow) {
|
||||
if (shouldWarnBeforeExit && exitShortcutPressed) {
|
||||
const shouldCancelCloseRequest = dialog.showMessageBoxSync(global.mainWindow, {
|
||||
type: "question",
|
||||
buttons: [_t("Cancel"), _t("Close %(brand)s", {
|
||||
@@ -342,11 +338,11 @@ app.on('ready', async () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
||||
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));
|
||||
.then((name) => console.log(`Added Extension: ${name}`))
|
||||
.catch((err) => 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));
|
||||
.then((name) => console.log(`Added Extension: ${name}`))
|
||||
.catch((err) => console.log('An error occurred: ', err));
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
}
|
||||
@@ -450,7 +446,6 @@ app.on('ready', async () => {
|
||||
if (global.store.get('minimizeToTray', true)) tray.create(global.trayConfig);
|
||||
|
||||
global.mainWindow.once('ready-to-show', () => {
|
||||
if (!global.mainWindow) return;
|
||||
mainWindowState.manage(global.mainWindow);
|
||||
|
||||
if (!argv['hidden']) {
|
||||
@@ -474,12 +469,12 @@ app.on('ready', async () => {
|
||||
// behave, eg. Mail.app)
|
||||
e.preventDefault();
|
||||
|
||||
if (global.mainWindow?.isFullScreen()) {
|
||||
global.mainWindow.once('leave-full-screen', () => global.mainWindow?.hide());
|
||||
if (global.mainWindow.isFullScreen()) {
|
||||
global.mainWindow.once('leave-full-screen', () => global.mainWindow.hide());
|
||||
|
||||
global.mainWindow.setFullScreen(false);
|
||||
} else {
|
||||
global.mainWindow?.hide();
|
||||
global.mainWindow.hide();
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -489,9 +484,9 @@ app.on('ready', async () => {
|
||||
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()) {
|
||||
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();
|
||||
}
|
||||
});
|
||||
@@ -502,8 +497,8 @@ app.on('ready', async () => {
|
||||
global.appLocalization = new AppLocalization({
|
||||
store: global.store,
|
||||
components: [
|
||||
(): void => tray.initApplicationMenu(),
|
||||
(): void => Menu.setApplicationMenu(buildMenuTemplate()),
|
||||
() => tray.initApplicationMenu(),
|
||||
() => Menu.setApplicationMenu(buildMenuTemplate()),
|
||||
],
|
||||
});
|
||||
});
|
||||
@@ -513,7 +508,7 @@ app.on('window-all-closed', () => {
|
||||
});
|
||||
|
||||
app.on('activate', () => {
|
||||
global.mainWindow?.show();
|
||||
global.mainWindow.show();
|
||||
});
|
||||
|
||||
function beforeQuit(): void {
|
||||
|
||||
@@ -32,7 +32,5 @@
|
||||
"Are you sure you want to quit?": "Er du sikker på at du vil slutte?",
|
||||
"Cancel": "Avbryt",
|
||||
"Services": "Tjenester",
|
||||
"Hide Others": "Skjul Andre",
|
||||
"Bring All to Front": "Flytt Alt Frem",
|
||||
"Toggle Full Screen": "Veksle Fullskjerm"
|
||||
"Hide Others": "Skjul Andre"
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ 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?.flashFrame(false);
|
||||
global.mainWindow.flashFrame(false);
|
||||
focusHandlerAttached = false;
|
||||
});
|
||||
focusHandlerAttached = true;
|
||||
|
||||
@@ -63,7 +63,7 @@ export function _t(text: string, variables: IVariables = {}): string {
|
||||
|
||||
type Component = () => void;
|
||||
|
||||
type TypedStore = Store<{ locale?: string | string[] }>;
|
||||
type TypedStore = Store<{ locale?: string[] }>;
|
||||
|
||||
export class AppLocalization {
|
||||
private static readonly STORE_KEY = "locale";
|
||||
@@ -71,7 +71,7 @@ export class AppLocalization {
|
||||
private readonly store: TypedStore;
|
||||
private readonly localizedComponents?: Set<Component>;
|
||||
|
||||
public constructor({ store, components = [] }: { store: TypedStore, components: Component[] }) {
|
||||
constructor({ store, components = [] }: { store: TypedStore, components: Component[] }) {
|
||||
counterpart.registerTranslations(FALLBACK_LOCALE, this.fetchTranslationJson("en_EN"));
|
||||
counterpart.setFallbackLocale(FALLBACK_LOCALE);
|
||||
counterpart.setSeparator('|');
|
||||
|
||||
@@ -52,7 +52,7 @@ function processUrl(url: string): void {
|
||||
global.mainWindow.loadURL(urlToLoad.href);
|
||||
}
|
||||
|
||||
function readStore(): Record<string, string> {
|
||||
function readStore(): object {
|
||||
try {
|
||||
const s = fs.readFileSync(storePath, { encoding: "utf8" });
|
||||
const o = JSON.parse(s);
|
||||
@@ -62,7 +62,7 @@ function readStore(): Record<string, string> {
|
||||
}
|
||||
}
|
||||
|
||||
function writeStore(data: Record<string, string>): void {
|
||||
function writeStore(data: object): void {
|
||||
fs.writeFileSync(storePath, JSON.stringify(data));
|
||||
}
|
||||
|
||||
@@ -83,7 +83,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 + '//'));
|
||||
if (deeplinkUrl?.includes(SEARCH_PARAM)) {
|
||||
if (deeplinkUrl && deeplinkUrl.includes(SEARCH_PARAM)) {
|
||||
const parsedUrl = new URL(deeplinkUrl);
|
||||
if (parsedUrl.protocol === PROTOCOL) {
|
||||
const ssoID = parsedUrl.searchParams.get(SEARCH_PARAM)!;
|
||||
|
||||
@@ -81,12 +81,15 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
// We do this here to ensure we get the path after --profile has been resolved
|
||||
const eventStorePath = path.join(app.getPath('userData'), 'EventStore');
|
||||
|
||||
const sendError = (id: string, e: Error): void => {
|
||||
const sendError = (id, e) => {
|
||||
const error = {
|
||||
message: e.message,
|
||||
};
|
||||
|
||||
global.mainWindow?.webContents.send('seshatReply', { id, error });
|
||||
global.mainWindow.webContents.send('seshatReply', {
|
||||
id: id,
|
||||
error: error,
|
||||
});
|
||||
};
|
||||
|
||||
const args = payload.args || [];
|
||||
@@ -135,7 +138,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
|
||||
eventIndex = new Seshat(eventStorePath, { passphrase });
|
||||
} else {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -150,7 +153,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
await index.shutdown();
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -179,7 +182,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
eventIndex?.addEvent(args[0], args[1]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -188,7 +191,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex?.deleteEvent(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -197,7 +200,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex?.commit();
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -206,7 +209,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex?.search(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
break;
|
||||
@@ -218,7 +221,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
ret = await eventIndex.addHistoricEvents(
|
||||
args[0], args[1], args[2]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -230,7 +233,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.getStats();
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -242,7 +245,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.removeCrawlerCheckpoint(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -254,7 +257,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.addCrawlerCheckpoint(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -266,7 +269,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.loadFileEvents(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -289,7 +292,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
await eventIndex.setUserVersion(args[0]);
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -301,7 +304,7 @@ ipcMain.on('seshat', async function(_ev: IpcMainEvent, payload): Promise<void> {
|
||||
try {
|
||||
ret = await eventIndex.getUserVersion();
|
||||
} catch (e) {
|
||||
sendError(payload.id, <Error>e);
|
||||
sendError(payload.id, e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@ export const Settings: Record<string, Setting> = {
|
||||
},
|
||||
"Electron.alwaysShowMenuBar": { // not supported on macOS
|
||||
async read(): Promise<any> {
|
||||
return !global.mainWindow!.autoHideMenuBar;
|
||||
return !global.mainWindow.autoHideMenuBar;
|
||||
},
|
||||
async write(value: any): Promise<void> {
|
||||
global.store.set('autoHideMenuBar', !value);
|
||||
global.mainWindow!.autoHideMenuBar = !value;
|
||||
global.mainWindow!.setMenuBarVisibility(value);
|
||||
global.mainWindow.autoHideMenuBar = !value;
|
||||
global.mainWindow.setMenuBarVisibility(value);
|
||||
},
|
||||
},
|
||||
"Electron.showTrayIcon": { // not supported on macOS
|
||||
|
||||
20
src/tray.ts
20
src/tray.ts
@@ -36,12 +36,12 @@ export function destroy(): void {
|
||||
}
|
||||
|
||||
function toggleWin(): void {
|
||||
if (global.mainWindow?.isVisible() && !global.mainWindow.isMinimized() && global.mainWindow.isFocused()) {
|
||||
if (global.mainWindow.isVisible() && !global.mainWindow.isMinimized() && global.mainWindow.isFocused()) {
|
||||
global.mainWindow.hide();
|
||||
} else {
|
||||
if (global.mainWindow?.isMinimized()) global.mainWindow.restore();
|
||||
if (!global.mainWindow?.isVisible()) global.mainWindow?.show();
|
||||
global.mainWindow?.focus();
|
||||
if (global.mainWindow.isMinimized()) global.mainWindow.restore();
|
||||
if (!global.mainWindow.isVisible()) global.mainWindow.show();
|
||||
global.mainWindow.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,11 +60,11 @@ export function create(config: IConfig): void {
|
||||
initApplicationMenu();
|
||||
trayIcon.on('click', toggleWin);
|
||||
|
||||
let lastFavicon: string | null = null;
|
||||
global.mainWindow?.webContents.on('page-favicon-updated', async function(ev, favicons) {
|
||||
let lastFavicon = null;
|
||||
global.mainWindow.webContents.on('page-favicon-updated', async function(ev, favicons) {
|
||||
if (!favicons || favicons.length <= 0 || !favicons[0].startsWith('data:')) {
|
||||
if (lastFavicon !== null) {
|
||||
global.mainWindow?.setIcon(defaultIcon);
|
||||
global.mainWindow.setIcon(defaultIcon);
|
||||
trayIcon?.setImage(defaultIcon);
|
||||
lastFavicon = null;
|
||||
}
|
||||
@@ -89,10 +89,10 @@ export function create(config: IConfig): void {
|
||||
}
|
||||
|
||||
trayIcon?.setImage(newFavicon);
|
||||
global.mainWindow?.setIcon(newFavicon);
|
||||
global.mainWindow.setIcon(newFavicon);
|
||||
});
|
||||
|
||||
global.mainWindow?.webContents.on('page-title-updated', function(ev, title) {
|
||||
global.mainWindow.webContents.on('page-title-updated', function(ev, title) {
|
||||
trayIcon?.setToolTip(title);
|
||||
});
|
||||
}
|
||||
@@ -110,7 +110,7 @@ export function initApplicationMenu(): void {
|
||||
{ type: 'separator' },
|
||||
{
|
||||
label: _t('Quit'),
|
||||
click: function(): void {
|
||||
click: function() {
|
||||
app.quit();
|
||||
},
|
||||
},
|
||||
|
||||
@@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
import { autoUpdater, ipcMain } from "electron";
|
||||
import { app, autoUpdater, ipcMain } from "electron";
|
||||
|
||||
const UPDATE_POLL_INTERVAL_MS = 60 * 60 * 1000;
|
||||
const INITIAL_UPDATE_DELAY_MS = 30 * 1000;
|
||||
@@ -50,14 +50,20 @@ export function start(updateBaseUrl: string): void {
|
||||
}
|
||||
try {
|
||||
let url: string;
|
||||
let serverType: "json" | undefined;
|
||||
|
||||
// For reasons best known to Squirrel, the way it checks for updates
|
||||
// is completely different between macOS and windows. On macOS, it
|
||||
// hits a URL that either gives it a 200 with some json or
|
||||
// 204 No Content. On windows it takes a base path and looks for
|
||||
// files under that path.
|
||||
if (process.platform === 'darwin') {
|
||||
// On macOS it takes a JSON file with a map between versions and their URLs
|
||||
url = `${updateBaseUrl}macos/releases.json`;
|
||||
serverType = "json";
|
||||
// include the current version in the URL we hit. Electron doesn't add
|
||||
// it anywhere (apart from the User-Agent) so it's up to us. We could
|
||||
// (and previously did) just use the User-Agent, but this doesn't
|
||||
// rely on NSURLConnection setting the User-Agent to what we expect,
|
||||
// and also acts as a convenient cache-buster to ensure that when the
|
||||
// app updates it always gets a fresh value to avoid update-looping.
|
||||
url = `${updateBaseUrl}macos/?localVersion=${encodeURIComponent(app.getVersion())}`;
|
||||
} else if (process.platform === 'win32') {
|
||||
// On windows it takes a base path and looks for files under that path.
|
||||
url = `${updateBaseUrl}win32/${process.arch}/`;
|
||||
} else {
|
||||
// Squirrel / electron only supports auto-update on these two platforms.
|
||||
@@ -69,7 +75,7 @@ export function start(updateBaseUrl: string): void {
|
||||
|
||||
if (url) {
|
||||
console.log(`Update URL: ${url}`);
|
||||
autoUpdater.setFeedURL({ url, serverType });
|
||||
autoUpdater.setFeedURL({ url });
|
||||
// We check for updates ourselves rather than using 'updater' because we need to
|
||||
// do it in the main process (and we don't really need to check every 10 minutes:
|
||||
// every hour should be just fine for a desktop app)
|
||||
|
||||
@@ -98,7 +98,7 @@ export function buildMenuTemplate(): Menu {
|
||||
// in macOS the Preferences menu item goes in the first menu
|
||||
...(!isMac ? [{
|
||||
label: _t('Preferences'),
|
||||
click(): void { global.mainWindow?.webContents.send('preferences'); },
|
||||
click() { global.mainWindow.webContents.send('preferences'); },
|
||||
}] : []),
|
||||
{
|
||||
role: 'togglefullscreen',
|
||||
@@ -132,7 +132,7 @@ export function buildMenuTemplate(): Menu {
|
||||
submenu: [
|
||||
{
|
||||
label: _t('Element Help'),
|
||||
click(): void { shell.openExternal('https://element.io/help'); },
|
||||
click() { shell.openExternal('https://element.io/help'); },
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -153,7 +153,7 @@ export function buildMenuTemplate(): Menu {
|
||||
{
|
||||
label: _t('Preferences') + '…',
|
||||
accelerator: 'Command+,', // Mac-only accelerator
|
||||
click(): void { global.mainWindow?.webContents.send('preferences'); },
|
||||
click() { global.mainWindow.webContents.send('preferences'); },
|
||||
},
|
||||
{ type: 'separator' },
|
||||
{
|
||||
|
||||
@@ -31,8 +31,7 @@ import {
|
||||
} from 'electron';
|
||||
import url from 'url';
|
||||
import fs from 'fs';
|
||||
import fetch from 'node-fetch';
|
||||
import { pipeline } from 'stream';
|
||||
import request from 'request';
|
||||
import path from 'path';
|
||||
|
||||
import { _t } from './language-helper';
|
||||
@@ -97,7 +96,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
if (!url.startsWith('blob:')) {
|
||||
popupMenu.append(new MenuItem({
|
||||
label: url,
|
||||
click(): void {
|
||||
click() {
|
||||
safeOpenURL(url);
|
||||
},
|
||||
}));
|
||||
@@ -107,7 +106,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
popupMenu.append(new MenuItem({
|
||||
label: _t('Copy image'),
|
||||
accelerator: 'c',
|
||||
click(): void {
|
||||
click() {
|
||||
webContents.copyImageAt(params.x, params.y);
|
||||
},
|
||||
}));
|
||||
@@ -120,7 +119,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
popupMenu.append(new MenuItem({
|
||||
label: _t('Copy email address'),
|
||||
accelerator: 'a',
|
||||
click(): void {
|
||||
click() {
|
||||
clipboard.writeText(url.substr(MAILTO_PREFIX.length));
|
||||
},
|
||||
}));
|
||||
@@ -130,7 +129,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
? _t('Copy image address')
|
||||
: _t('Copy link address'),
|
||||
accelerator: 'a',
|
||||
click(): void {
|
||||
click() {
|
||||
clipboard.writeText(url);
|
||||
},
|
||||
}));
|
||||
@@ -143,7 +142,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
popupMenu.append(new MenuItem({
|
||||
label: _t('Save image as...'),
|
||||
accelerator: 's',
|
||||
async click(): Promise<void> {
|
||||
async click() {
|
||||
const targetFileName = params.suggestedFilename || params.altText || "image.png";
|
||||
const { filePath } = await dialog.showSaveDialog({
|
||||
defaultPath: targetFileName,
|
||||
@@ -155,10 +154,7 @@ function onLinkContextMenu(ev: Event, params: ContextMenuParams, webContents: We
|
||||
if (url.startsWith("data:")) {
|
||||
await writeNativeImage(filePath, nativeImage.createFromDataURL(url));
|
||||
} else {
|
||||
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}`);
|
||||
pipeline(resp.body, fs.createWriteStream(filePath));
|
||||
request.get(url).pipe(fs.createWriteStream(filePath));
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
@@ -228,7 +224,7 @@ function cutCopyPasteSelectContextMenus(params: ContextMenuParams): MenuItemCons
|
||||
return options;
|
||||
}
|
||||
|
||||
function onSelectedContextMenu(ev: Event, params: ContextMenuParams): void {
|
||||
function onSelectedContextMenu(ev, params) {
|
||||
const items = cutCopyPasteSelectContextMenus(params);
|
||||
const popupMenu = Menu.buildFromTemplate(items);
|
||||
|
||||
@@ -237,7 +233,7 @@ function onSelectedContextMenu(ev: Event, params: ContextMenuParams): void {
|
||||
ev.preventDefault();
|
||||
}
|
||||
|
||||
function onEditableContextMenu(ev: Event, params: ContextMenuParams): void {
|
||||
function onEditableContextMenu(ev: Event, params: ContextMenuParams) {
|
||||
const items: MenuItemConstructorOptions[] = [
|
||||
{ role: 'undo' },
|
||||
{ role: 'redo', enabled: params.editFlags.canRedo },
|
||||
@@ -263,11 +259,7 @@ ipcMain.on('userDownloadAction', function(ev: IpcMainEvent, { id, open = false }
|
||||
});
|
||||
|
||||
export default (webContents: WebContents): void => {
|
||||
webContents.setWindowOpenHandler((details) => {
|
||||
safeOpenURL(details.url);
|
||||
return { action: "deny" };
|
||||
});
|
||||
|
||||
webContents.on('new-window', onWindowOrNavigate);
|
||||
webContents.on('will-navigate', (ev: Event, target: string): void => {
|
||||
if (target.startsWith("vector://")) return;
|
||||
return onWindowOrNavigate(ev, target);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
"module": "commonjs",
|
||||
"moduleResolution": "node",
|
||||
"target": "es2016",
|
||||
"noImplicitAny": false,
|
||||
"sourceMap": false,
|
||||
"outDir": "./lib",
|
||||
"rootDir": "./src",
|
||||
|
||||
Reference in New Issue
Block a user