Compare commits

..

38 Commits

Author SHA1 Message Date
RiotRobot
55e3fa1652 v1.12.2 2025-10-21 11:54:45 +00:00
RiotRobot
86891dcdd4 v1.12.2-rc.0 2025-10-14 14:48:20 +00:00
ElementRobot
55ee9c0053 Merge pull request #2628 from element-hq/actions/localazy-download
Localazy Download
2025-10-13 07:24:08 +01:00
t3chguy
1fd2214951 [create-pull-request] automated change 2025-10-13 06:08:25 +00:00
ElementRobot
fe253172b3 Merge pull request #2625 from element-hq/actions/localazy-download
Localazy Download
2025-10-10 07:36:41 +01:00
t3chguy
c7cdbcf07b [create-pull-request] automated change 2025-10-10 06:08:09 +00:00
Michael Telatynski
5e882f8e08 Allow Desktop app to be auto-started minimised or focused (#2622) 2025-10-09 14:41:12 +01:00
Michael Telatynski
e5f6bd882f Specify strictVerify to electron-builder mac builds (#2624) 2025-10-09 14:22:35 +01:00
Michael Telatynski
e4f75de04c Tidy knip config (#2623) 2025-10-09 09:04:14 +01:00
Michael Telatynski
1c55aa780f Improve workflows for better reusability (#2608) 2025-10-08 11:45:46 +01:00
ElementRobot
5dd1984896 Merge pull request #2620 from element-hq/actions/localazy-download
Localazy Download
2025-10-08 07:30:05 +01:00
t3chguy
3c78634cd5 [create-pull-request] automated change 2025-10-08 06:08:07 +00:00
RiotRobot
155bbe3634 Merge branch 'master' into develop 2025-10-07 12:37:57 +00:00
Michael Telatynski
a64ed5428c Fix hardlinks appearing in and breaking deb packages (#2609) 2025-10-06 09:55:54 +01:00
ElementRobot
d0a735b25c Merge pull request #2614 from element-hq/actions/localazy-download
Localazy Download
2025-10-06 07:22:32 +01:00
t3chguy
522c6f95ab [create-pull-request] automated change 2025-10-06 06:08:00 +00:00
David Baker
155b6f284a Merge pull request #2597 from element-hq/renovate/all-minor-patch
Update all non-major dependencies
2025-10-01 16:47:11 +01:00
David Baker
8376cef25a Merge pull request #2598 from element-hq/renovate/eslint-stylistic-monorepo
Update dependency @stylistic/eslint-plugin to v5.4.0
2025-10-01 16:46:45 +01:00
renovate[bot]
15f23d4cf9 Update electron (#2599)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-10-01 16:36:19 +01:00
David Baker
ea2b160dcc Merge pull request #2595 from element-hq/renovate/playwright
Update playwright to v1.55.1
2025-10-01 16:28:37 +01:00
renovate[bot]
bc0a8f03db Update all non-major dependencies 2025-10-01 15:25:50 +00:00
David Baker
39eddfdc4b Merge pull request #2604 from element-hq/dbkr/v_for_i_have_a_vendetta_against_people_who_cant_just_decide_on_what_the_format_of_the_damn_file_should_be
Support .node-version either with or without leading 'v'
2025-10-01 16:13:43 +01:00
David Baker
e668edbcec Merge pull request #2605 from element-hq/dependabot/npm_and_yarn/tar-fs-2.1.4
Bump tar-fs from 2.1.3 to 2.1.4
2025-10-01 14:59:01 +01:00
dependabot[bot]
763ebc4ca8 Bump tar-fs from 2.1.3 to 2.1.4
Bumps [tar-fs](https://github.com/mafintosh/tar-fs) from 2.1.3 to 2.1.4.
- [Commits](https://github.com/mafintosh/tar-fs/compare/v2.1.3...v2.1.4)

---
updated-dependencies:
- dependency-name: tar-fs
  dependency-version: 2.1.4
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-01 10:20:59 +00:00
David Baker
cfff1c7640 Spell renovate right
Co-authored-by: Michael Telatynski <7t3chguy@gmail.com>
2025-10-01 11:06:34 +01:00
David Baker
ec1971366a Support .node-version either with or without leading 'v'
As per comment
2025-10-01 10:49:00 +01:00
renovate[bot]
1f803f7051 Update dependency @stylistic/eslint-plugin to v5.4.0 2025-10-01 08:53:49 +00:00
renovate[bot]
c90c79e3ae Update playwright to v1.55.1 2025-10-01 08:53:37 +00:00
David Baker
22100bff80 Merge pull request #2596 from element-hq/renovate/typescript-eslint-monorepo
Update typescript-eslint monorepo to v8.44.1
2025-10-01 09:52:12 +01:00
David Baker
a4b622dd5e Merge pull request #2594 from element-hq/renovate/definitelytyped
Update dependency @types/node to v18.19.127
2025-10-01 09:51:14 +01:00
David Baker
c9a03859bd Merge pull request #2593 from element-hq/renovate/rust-bullseye
Update rust:bullseye Docker digest to 65dd7bb
2025-10-01 09:50:44 +01:00
David Baker
2385c4dd9b Merge pull request #2557 from element-hq/renovate/docker
Update docker/login-action digest to 5e57cd1
2025-10-01 09:50:22 +01:00
David Baker
9d2b1621d6 Merge pull request #2592 from element-hq/renovate/actions-cache-digest
Update actions/cache digest to 0057852
2025-10-01 09:49:59 +01:00
renovate[bot]
35db60092b Update rust:bullseye Docker digest to 65dd7bb 2025-09-30 21:14:12 +00:00
renovate[bot]
0a97f12323 Update typescript-eslint monorepo to v8.44.1 2025-09-30 13:14:17 +00:00
renovate[bot]
cd671919e2 Update dependency @types/node to v18.19.127 2025-09-30 13:13:49 +00:00
renovate[bot]
8e964cd782 Update actions/cache digest to 0057852 2025-09-30 13:13:23 +00:00
renovate[bot]
64d8341deb Update docker/login-action digest to 5e57cd1 2025-09-29 10:48:58 +00:00
25 changed files with 974 additions and 651 deletions

View File

@@ -51,7 +51,7 @@ jobs:
tests-done:
needs: [windows, linux, macos]
runs-on: ubuntu-24.04
if: always()
if: ${{ !cancelled() }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5

View File

@@ -39,15 +39,39 @@ on:
The artifact can also contain any additional files which will be applied as overrides to the checkout root before building,
for example icons in the `build/` directory to override the app icons.
default: "webapp"
test:
type: boolean
required: false
default: true
description: "Whether to run the test stage after building"
test-args:
type: string
required: false
description: "Additional arguments to pass to playwright"
runs-on:
type: string
required: false
description: "The runner image to use, normally set for you, may be needed for running in private repos."
artifact-prefix:
type: string
required: false
description: "An optional prefix to add to the artifact name, useful for distinguishing builds in private repos."
default: ""
targets:
type: string
required: false
description: "List of targets to build"
default: "tar.gz deb"
env:
SQLCIPHER_BUNDLED: ${{ inputs.sqlcipher == 'static' && '1' || '' }}
MAX_GLIBC: 2.31 # bullseye-era glibc, used by glibc-check.sh
permissions: {} # No permissions required
jobs:
build:
name: Build Linux ${{ inputs.arch }} SQLCipher ${{ inputs.sqlcipher }}
# We build on native infrastructure as matrix-seshat fails to cross-compile properly
# https://github.com/matrix-org/seshat/issues/135
runs-on: ${{ inputs.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04' }}
runs-on: ${{ inputs.runs-on || (inputs.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04') }}
env:
HAK_DOCKER_IMAGE: ghcr.io/element-hq/element-desktop-dockerbuild
steps:
@@ -90,7 +114,7 @@ jobs:
- name: Cache .hak
id: cache
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
key: ${{ runner.os }}-${{ github.ref_name }}-${{ inputs.sqlcipher }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion', 'dockerbuild/*') }}
path: |
@@ -109,7 +133,7 @@ jobs:
- name: "Get modified files"
id: changed_files
if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request'
if: steps.cache.outputs.cache-hit != 'true' && github.event_name == 'pull_request' && github.repository == 'element-hq/element-desktop'
uses: tj-actions/changed-files@823fcebdb31bb35fdf2229d9f769b400309430d0 # v46
with:
files: |
@@ -152,19 +176,20 @@ jobs:
fi
# Workaround for https://github.com/electron-userland/electron-builder/issues/6116
# and https://github.com/electron-userland/electron-builder/issues/5721
- name: Install fpm
if: inputs.arch == 'arm64'
run: |
sudo apt-get install ruby-dev build-essential
sudo gem install fpm
echo "USE_SYSTEM_FPM=true" >> $GITHUB_ENV
- name: Build App
run: yarn build --publish never -l ${{ steps.config.outputs.build-args }}
run: yarn build --publish never ${{ steps.config.outputs.build-args }} -l ${{ inputs.targets }}
env:
VARIANT_PATH: variant.json
# Only set for Nightly builds
VERSION: ${{ inputs.version }}
# Workaround for https://github.com/electron-userland/electron-builder/issues/5721
USE_HARD_LINKS: false
- name: Check native libraries
run: |
@@ -172,11 +197,9 @@ jobs:
shopt -s globstar
FILES=$(file dist/**/*.node)
echo "$FILES"
echo $FILES
if [ grep -v "$ARCH" ]; then
exit 1
fi
! echo "$FILES" | grep -v "$ARCH"
LIBS=$(readelf -d dist/**/*.node | grep NEEDED)
echo "$LIBS"
@@ -198,27 +221,46 @@ jobs:
- name: Upload Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }}
name: ${{ inputs.artifact-prefix }}linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }}
path: |
dist
!dist/*-unpacked/**
retention-days: 1
- name: Assert all required files are present
- name: Assert deb is present and valid
if: contains(inputs.targets, 'deb')
run: |
test -f ./dist/element-desktop*$ARCH.deb
test -f ./dist/element-desktop*.tar.gz
DEB_LISTING=$(dpkg-deb --fsys-tarfile ./dist/element-desktop*.deb | tar -tv)
echo "deb listing: "
echo "$DEB_LISTING"
! echo "$DEB_LISTING" | grep '^h'
env:
ARCH: ${{ inputs.arch }}
- name: Assert tar.gz is present
if: contains(inputs.targets, 'tar.gz')
run: |
test -f ./dist/element-desktop*.tar.gz
TAR_GZ_LISTING=$(tar -tvf ./dist/element-desktop*.tar.gz)
echo "tar.gz listing: "
echo "$TAR_GZ_LISTING"
! echo "$TAR_GZ_LISTING" | grep '^h'
test:
name: Test Linux ${{ inputs.arch }} SQLCipher ${{ inputs.sqlcipher }}
needs: build
if: inputs.test && contains(inputs.targets, 'deb')
uses: ./.github/workflows/build_test.yaml
with:
artifact: linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }}
runs-on: ${{ inputs.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04' }}
project: linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }}
artifact: ${{ inputs.artifact-prefix }}linux-${{ inputs.arch }}-sqlcipher-${{ inputs.sqlcipher }}
runs-on: ${{ inputs.runs-on || (inputs.arch == 'arm64' && 'ubuntu-22.04-arm' || 'ubuntu-22.04') }}
executable: /opt/Element*/element-desktop*
prepare_cmd: |
sudo apt-get -qq update
sudo apt install ./dist/*.deb
blob_report: ${{ inputs.blob_report }}
args: ${{ inputs.test-args }}

View File

@@ -49,9 +49,29 @@ on:
The artifact can also contain any additional files which will be applied as overrides to the checkout root before building,
for example icons in the `build/` directory to override the app icons.
default: "webapp"
test:
type: boolean
required: false
default: true
description: "Whether to run the test stage after building"
test-args:
type: string
required: false
description: "Additional arguments to pass to playwright"
artifact-prefix:
type: string
required: false
description: "An optional prefix to add to the artifact name, useful for distinguishing builds in private repos."
default: ""
targets:
type: string
required: false
description: "List of targets to build"
default: "dmg zip"
permissions: {} # No permissions required
jobs:
build:
name: Build macOS Universal
runs-on: macos-14 # M1
environment: ${{ inputs.sign && 'packages.element.io' || '' }}
steps:
@@ -66,7 +86,7 @@ jobs:
- name: Cache .hak
id: cache
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
key: ${{ runner.os }}-${{ hashFiles('hakHash', 'electronVersion') }}
path: |
@@ -105,7 +125,7 @@ jobs:
- name: "[Signed] Build App"
if: inputs.sign != ''
run: |
yarn build:universal --publish never
yarn build:universal --publish never -m ${{ inputs.targets }}
env:
APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }}
APPLE_ID: ${{ secrets.APPLE_ID }}
@@ -127,7 +147,7 @@ jobs:
- name: "[Unsigned] Build App"
if: inputs.sign == ''
run: |
yarn build:universal --publish never
yarn build:universal --publish never -m ${{ inputs.targets }}
env:
CSC_IDENTITY_AUTO_DISCOVERY: false
VARIANT_PATH: variant.json
@@ -162,22 +182,30 @@ jobs:
- name: Upload Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: macos
name: ${{ inputs.artifact-prefix }}macos
path: |
dist
!dist/mac-universal/**
retention-days: 1
- name: Assert all required files are present
- name: Assert zip is present
if: contains(inputs.targets, 'zip')
run: |
test -f ./dist/Element*.dmg
test -f ./dist/Element*-mac.zip
- name: Assert dmg is present
if: contains(inputs.targets, 'dmg')
run: |
test -f ./dist/Element*.dmg
test:
name: Test macOS Universal
needs: build
if: inputs.test && contains(inputs.targets, 'dmg')
uses: ./.github/workflows/build_test.yaml
with:
artifact: macos
project: macos
artifact: ${{ inputs.artifact-prefix }}macos
runs-on: macos-14
executable: /Users/runner/Applications/Element*.app/Contents/MacOS/Element*
# We need to mount the DMG and copy the app to the Applications folder as a mounted DMG is
@@ -187,3 +215,4 @@ jobs:
rsync -a /Volumes/Element/Element*.app ~/Applications/ &&
hdiutil detach /Volumes/Element
blob_report: ${{ inputs.blob_report }}
args: ${{ inputs.test-args }}

View File

@@ -10,6 +10,10 @@ on:
type: string
required: true
description: "The name of the artifact to download"
project:
type: string
required: true
description: "The Playwright project to use for testing"
executable:
type: string
required: true
@@ -22,12 +26,19 @@ on:
type: boolean
default: false
description: "Whether to upload a blob report instead of the HTML report"
args:
type: string
required: false
description: "Additional arguments to pass to playwright, for e.g. skipping specific tests"
permissions: {}
jobs:
test:
name: Test ${{ inputs.project }}
runs-on: ${{ inputs.runs-on }}
steps:
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
with:
repository: ${{ github.repository == 'element-hq/element-web-pro' && 'element-hq/element-desktop' || github.repository }}
- uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
with:
@@ -69,7 +80,7 @@ jobs:
uses: coactions/setup-xvfb@6b00cf1889f4e1d5a48635647013c0508128ee1a
timeout-minutes: 20
with:
run: yarn test --project=${{ inputs.artifact }} ${{ runner.os != 'Linux' && '--ignore-snapshots' || '' }} ${{ inputs.blob_report == false && '--reporter=html' || '' }}
run: yarn test --project=${{ inputs.project }} ${{ runner.os != 'Linux' && '--ignore-snapshots' || '' }} ${{ inputs.blob_report == false && '--reporter=html' || '' }} ${{ inputs.args }}
env:
ELEMENT_DESKTOP_EXECUTABLE: ${{ steps.executable.outputs.path }}

View File

@@ -53,9 +53,33 @@ on:
The artifact can also contain any additional files which will be applied as overrides to the checkout root before building,
for example icons in the `build/` directory to override the app icons.
default: "webapp"
test:
type: boolean
required: false
default: true
description: "Whether to run the test stage after building"
test-runs-on:
type: string
required: false
description: "The runner image to use for testing, normally set for you, may be needed for running in private repos."
test-args:
type: string
required: false
description: "Additional arguments to pass to playwright"
artifact-prefix:
type: string
required: false
description: "An optional prefix to add to the artifact name, useful for distinguishing builds in private repos."
default: ""
targets:
type: string
required: false
description: "List of targets to build"
default: "squirrel msi"
permissions: {} # No permissions required
jobs:
build:
name: Build Windows ${{ inputs.arch }}
runs-on: windows-2025
environment: ${{ inputs.sign && 'packages.element.io' || '' }}
env:
@@ -95,7 +119,7 @@ jobs:
- name: Cache .hak
id: cache
uses: actions/cache@0400d5f644dc74513175e3cd8d07132dd4860809 # v4
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
with:
key: ${{ runner.os }}-${{ inputs.arch }}-${{ hashFiles('hakHash', 'electronVersion') }}
path: |
@@ -208,7 +232,7 @@ jobs:
MASTER_KEY_FILE: C:\Users\runneradmin\eSignerCKA\master.key
- name: Build App
run: yarn build --publish never -w ${{ steps.config.outputs.build-args }}
run: yarn build --publish never ${{ steps.config.outputs.build-args }} -w ${{ inputs.targets }}
env:
VARIANT_PATH: variant.json
# Only set for Nightly builds
@@ -236,24 +260,36 @@ jobs:
- name: Upload Artifacts
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4
with:
name: win-${{ inputs.arch }}
name: ${{ inputs.artifact-prefix }}win-${{ inputs.arch }}
path: |
dist
retention-days: 1
- name: Assert all required files are present
- name: Assert executable is present
run: |
Test-Path './dist/win-*unpacked/Element*.exe'
- name: Assert all Squirrel files are present
if: contains(inputs.targets, 'squirrel')
run: |
Test-Path './dist/squirrel-windows*/Element Setup*.exe'
Test-Path './dist/squirrel-windows*/element-desktop-*-full.nupkg'
Test-Path './dist/squirrel-windows*/RELEASES'
- name: Assert MSI is present
if: contains(inputs.targets, 'msi')
run: |
Test-Path './dist/Element*.msi'
test:
name: Test Windows ${{ inputs.arch }}
needs: build
if: inputs.test
uses: ./.github/workflows/build_test.yaml
with:
artifact: win-${{ inputs.arch }}
runs-on: ${{ inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2022' }}
project: win-${{ inputs.arch }}
artifact: ${{ inputs.artifact-prefix }}win-${{ inputs.arch }}
runs-on: ${{ inputs.test-runs-on || (inputs.arch == 'arm64' && 'windows-11-arm' || 'windows-2022') }}
executable: ./dist/win*-unpacked/Element*.exe
blob_report: ${{ inputs.blob_report }}
args: ${{ inputs.test-args }}

View File

@@ -42,7 +42,7 @@ jobs:
run: docker run -v $PWD:/project element-desktop-dockerbuild yarn install
- name: Log in to the Container registry
uses: docker/login-action@184bdaa0721073962dff0199f1fb9940f07167d1
uses: docker/login-action@5e57cd118135c172c3672efd75eb46360885c0ef
if: github.event_name != 'pull_request'
with:
registry: ${{ env.REGISTRY }}

View File

@@ -1 +1 @@
v22.19.0
22.20.0

View File

@@ -1,3 +1,29 @@
Changes in [1.12.2](https://github.com/element-hq/element-desktop/releases/tag/v1.12.2) (2025-10-21)
====================================================================================================
## ✨ Features
* Allow Desktop app to be auto-started minimised or focused ([#2622](https://github.com/element-hq/element-desktop/pull/2622)). Contributed by @t3chguy.
* Room List: Extend the viewport to avoid so many black spots when scrolling the room list ([#30867](https://github.com/element-hq/element-web/pull/30867)). Contributed by @langleyd.
* Hide calling buttons in room header before a room is created ([#30816](https://github.com/element-hq/element-web/pull/30816)). Contributed by @Half-Shot.
* Improve invite dialog ui - Part 2 ([#30836](https://github.com/element-hq/element-web/pull/30836)). Contributed by @florianduros.
## 🐛 Bug Fixes
* Fix hardlinks appearing in and breaking deb packages ([#2609](https://github.com/element-hq/element-desktop/pull/2609)). Contributed by @t3chguy.
* Fix platform settings race condition and make auto-launch tri-state ([#30977](https://github.com/element-hq/element-web/pull/30977)). Contributed by @t3chguy.
* Fix: member count in header and member list ([#30982](https://github.com/element-hq/element-web/pull/30982)). Contributed by @florianduros.
* Fix duration of voice message in timeline ([#30973](https://github.com/element-hq/element-web/pull/30973)). Contributed by @florianduros.
* Fix voice notes rendering at 00:00 when playback had not begun. ([#30961](https://github.com/element-hq/element-web/pull/30961)). Contributed by @Half-Shot.
* Improve handling of animated images, add support for AVIF animations ([#30932](https://github.com/element-hq/element-web/pull/30932)). Contributed by @t3chguy.
* Update key storage toggle when key storage status changes ([#30934](https://github.com/element-hq/element-web/pull/30934)). Contributed by @uhoreg.
* Fix jitsi widget popout ([#30908](https://github.com/element-hq/element-web/pull/30908)). Contributed by @dbkr.
* Improve keyboard navigation on invite dialog ([#30930](https://github.com/element-hq/element-web/pull/30930)). Contributed by @florianduros.
* Prefer UIA flows with supported UIA stages ([#30926](https://github.com/element-hq/element-web/pull/30926)). Contributed by @richvdh.
* Enhance accessibility of dropdown ([#30928](https://github.com/element-hq/element-web/pull/30928)). Contributed by @florianduros.
* Improve accessibility of the `\<AvatarSetting> component ([#30907](https://github.com/element-hq/element-web/pull/30907)). Contributed by @MidhunSureshR.
Changes in [1.12.1](https://github.com/element-hq/element-desktop/releases/tag/v1.12.1) (2025-10-07)
====================================================================================================
## ✨ Features

View File

@@ -1,6 +1,6 @@
# Docker image to facilitate building Element Desktop's native bits using a glibc version (2.31)
# with broader compatibility, down to Debian bullseye & Ubuntu focal.
FROM rust:bullseye@sha256:8f72d971a31b278cebdb2eb64a44c3900ff27c716a4ef6f4db05946d10c9ae4e
FROM rust:bullseye@sha256:65dd7bbc1811b11827fcc842491b90dcd5ebc7153132596911986932a59a0e12
ENV DEBIAN_FRONTEND=noninteractive

View File

@@ -3,6 +3,9 @@
set -x
declare -A archMap=(["amd64"]="x64" ["arm64"]="arm64")
ARCH="${archMap["$TARGETARCH"]}"
NODE_VERSION=$(cat /.node-version)
curl --proto "=https" -L "https://nodejs.org/dist/$NODE_VERSION/node-$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
# The .node-version file generally doesn't have the 'v' (renovate does not put the 'v' and will
# strip it on upgrade if it's there) but the 'v' is also widely supported so we probably ought
# to just work either way.
NODE_VERSION=$(cat /.node-version | sed -e 's/^v//')
curl --proto "=https" -L "https://nodejs.org/dist/v$NODE_VERSION/node-v$NODE_VERSION-$TARGETOS-$ARCH.tar.gz" | tar xz -C /usr/local --strip-components=1 && \
unlink /usr/local/CHANGELOG.md && unlink /usr/local/LICENSE && unlink /usr/local/README.md

View File

@@ -129,7 +129,7 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
linux: {
target: ["tar.gz", "deb"],
category: "Network;InstantMessaging;Chat",
icon: "build/icon.png",
icon: "icon.png",
executableName: variant.name, // element-desktop or element-desktop-nightly
},
deb: {
@@ -151,12 +151,12 @@ const config: Omit<Writable<Configuration>, "electronFuses"> & {
fpm: ["--deb-pre-depends", "libc6 (>= 2.31)"],
},
mac: {
target: ["dmg", "zip"],
category: "public.app-category.social-networking",
darkModeSupport: true,
hardenedRuntime: true,
gatekeeperAssess: true,
// XXX: we cannot specify this due to https://github.com/electron/osx-sign/issues/344
// strictVerify: true,
strictVerify: true,
entitlements: "./build/entitlements.mac.plist",
icon: "build/icon.icns",
mergeASARs: true,

View File

@@ -1,7 +1,7 @@
import { KnipConfig } from "knip";
export default {
entry: ["src/electron-main.ts", "src/preload.ts", "electron-builder.ts", ".eslintrc-*.js", "scripts/**", "hak/**"],
entry: ["src/preload.cts", "electron-builder.ts", "scripts/**", "hak/**"],
project: ["**/*.{js,ts}"],
ignoreDependencies: [
// Brought in via hak scripts
@@ -10,6 +10,8 @@ export default {
"@action-validator/*",
// Used for git pre-commit hooks
"husky",
// Required for `patch-package`
"postinstall-postinstall",
],
ignoreBinaries: ["jq", "scripts/in-docker.sh"],
} satisfies KnipConfig;

View File

@@ -3,7 +3,7 @@
"productName": "Element",
"main": "lib/electron-main.js",
"exports": "./lib/electron-main.js",
"version": "1.12.1",
"version": "1.12.2",
"description": "Element: the future of secure communication",
"author": {
"name": "Element",
@@ -57,7 +57,7 @@
"test:open": "yarn test --ui",
"test:screenshots:build": "docker build playwright -t element-desktop-playwright --platform linux/amd64",
"test:screenshots:run": "docker run --rm --network host -v $(pwd):/work/element-desktop -v /var/run/docker.sock:/var/run/docker.sock --platform linux/amd64 -it element-desktop-playwright",
"postinstall": "electron-builder install-app-deps"
"postinstall": "patch-package && electron-builder install-app-deps"
},
"dependencies": {
"@sentry/electron": "^7.0.0",
@@ -77,19 +77,19 @@
"@babel/preset-env": "^7.18.10",
"@babel/preset-typescript": "^7.18.6",
"@electron/asar": "4.0.1",
"@playwright/test": "1.55.0",
"@playwright/test": "1.55.1",
"@stylistic/eslint-plugin": "^5.0.0",
"@types/auto-launch": "^5.0.1",
"@types/counterpart": "^0.18.1",
"@types/minimist": "^1.2.1",
"@types/node": "18.19.124",
"@types/node": "18.19.127",
"@types/pacote": "^11.1.1",
"@typescript-eslint/eslint-plugin": "^8.0.0",
"@typescript-eslint/parser": "^8.0.0",
"app-builder-lib": "26.0.20",
"chokidar": "^4.0.0",
"detect-libc": "^2.0.0",
"electron": "38.1.0",
"electron": "38.2.0",
"electron-builder": "26.0.20",
"electron-builder-squirrel-windows": "26.0.20",
"electron-devtools-installer": "^4.0.0",
@@ -107,6 +107,8 @@
"matrix-web-i18n": "^3.2.1",
"mkdirp": "^3.0.0",
"pacote": "^21.0.0",
"patch-package": "^8.0.1",
"postinstall-postinstall": "^2.1.0",
"prettier": "^3.0.0",
"rimraf": "^6.0.0",
"tar": "^7.0.0",
@@ -117,7 +119,7 @@
"matrix-seshat": "^4.0.1"
},
"resolutions": {
"@types/node": "18.19.124",
"@types/node": "18.19.127",
"config-file-ts": "0.2.8-rc1",
"node-abi": "4.14.0"
}

View File

@@ -0,0 +1,18 @@
diff --git a/node_modules/@types/auto-launch/index.d.ts b/node_modules/@types/auto-launch/index.d.ts
index a30a77c..e512ce1 100644
--- a/node_modules/@types/auto-launch/index.d.ts
+++ b/node_modules/@types/auto-launch/index.d.ts
@@ -25,6 +25,13 @@ interface AutoLaunchOptions {
declare class AutoLaunch {
constructor(options: AutoLaunchOptions);
+ /**
+ * This type describes the internal options of the `auto-launch` package which allows us to update options after initialization.
+ */
+ readonly opts: {
+ isHiddenOnLaunch: boolean;
+ };
+
/**
* Enables auto-launch at start up.
*/

View File

@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/playwright:v1.55.0-jammy@sha256:55db7b712a981e9cc1ec757a4511cd01c5ed4e20bd7c84b2dee4e1d320102b9d
FROM mcr.microsoft.com/playwright:v1.55.1-jammy@sha256:a012a91c32e36b3300514684c5bdb60c07f01464abd03380320179e5273427ab
WORKDIR /work/element-desktop

View File

@@ -7,7 +7,6 @@ Please see LICENSE files in the repository root for full details.
import { type BrowserWindow } from "electron";
import type AutoLaunch from "auto-launch";
import { type AppLocalization } from "../language-helper.js";
// global type extensions need to use var for whatever reason
@@ -18,7 +17,6 @@ declare global {
var mainWindow: BrowserWindow | null;
var appQuitting: boolean;
var appLocalization: AppLocalization;
var launcher: AutoLaunch;
var vectorConfig: IConfigOptions;
var trayConfig: {
// eslint-disable-next-line camelcase

50
src/auto-launch.ts Normal file
View File

@@ -0,0 +1,50 @@
/*
Copyright 2025 New Vector Ltd.
SPDX-License-Identifier: AGPL-3.0-only OR GPL-3.0-only OR LicenseRef-Element-Commercial
Please see LICENSE files in the repository root for full details.
*/
import BaseAutoLaunch from "auto-launch";
import Store from "./store.js";
export type AutoLaunchState = "enabled" | "minimised" | "disabled";
// Wrapper around auto-launch to get/set the `isHidden` option
export class AutoLaunch extends BaseAutoLaunch {
private static internalInstance?: AutoLaunch;
public static get instance(): AutoLaunch {
if (!AutoLaunch.internalInstance) {
if (!Store.instance) throw new Error("Store not initialized");
AutoLaunch.internalInstance = new AutoLaunch({
name: global.vectorConfig.brand || "Element",
isHidden: Store.instance.get("openAtLoginMinimised"),
mac: {
useLaunchAgent: true,
},
});
}
return AutoLaunch.internalInstance;
}
public async getState(): Promise<AutoLaunchState> {
if (!(await this.isEnabled())) {
return "disabled";
}
return this.opts.isHiddenOnLaunch ? "minimised" : "enabled";
}
public async setState(state: AutoLaunchState): Promise<void> {
const openAtLoginMinimised = state === "minimised";
Store.instance?.set("openAtLoginMinimised", openAtLoginMinimised);
this.opts.isHiddenOnLaunch = openAtLoginMinimised;
if (state !== "disabled") {
return this.enable();
} else {
return this.disable();
}
}
}

View File

@@ -24,7 +24,6 @@ import {
} from "electron";
// eslint-disable-next-line n/file-extension-in-import
import * as Sentry from "@sentry/electron/main";
import AutoLaunch from "auto-launch";
import path, { dirname } from "node:path";
import windowStateKeeper from "electron-window-state";
import fs, { promises as afs } from "node:fs";
@@ -169,59 +168,74 @@ function loadLocalConfigFile(): Json {
}
}
let loadConfigPromise: Promise<void> | undefined;
// Loads the config from asar, and applies a config.json from userData atop if one exists
// Writes config to `global.vectorConfig`. Does nothing if `global.vectorConfig` is already set.
async function loadConfig(): Promise<void> {
if (global.vectorConfig) return;
// Writes config to `global.vectorConfig`. Idempotent, returns the same promise on subsequent calls.
function loadConfig(): Promise<void> {
if (loadConfigPromise) return loadConfigPromise;
const asarPath = await getAsarPath();
async function actuallyLoadConfig(): Promise<void> {
const asarPath = await getAsarPath();
try {
console.log(`Loading app config: ${path.join(asarPath, LocalConfigFilename)}`);
global.vectorConfig = loadJsonFile(asarPath, LocalConfigFilename);
} catch {
// it would be nice to check the error code here and bail if the config
// is unparsable, but we get MODULE_NOT_FOUND in the case of a missing
// file or invalid json, so node is just very unhelpful.
// Continue with the defaults (ie. an empty config)
global.vectorConfig = {};
}
try {
// Load local config and use it to override values from the one baked with the build
const localConfig = loadLocalConfigFile();
// 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))) {
// 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>,
);
try {
console.log(`Loading app config: ${path.join(asarPath, LocalConfigFilename)}`);
global.vectorConfig = loadJsonFile(asarPath, LocalConfigFilename);
} catch {
// it would be nice to check the error code here and bail if the config
// is unparsable, but we get MODULE_NOT_FOUND in the case of a missing
// file or invalid json, so node is just very unhelpful.
// Continue with the defaults (ie. an empty config)
global.vectorConfig = {};
}
global.vectorConfig = Object.assign(global.vectorConfig, localConfig);
} catch (e) {
if (e instanceof SyntaxError) {
void dialog.showMessageBox({
type: "error",
title: `Your ${global.vectorConfig.brand || "Element"} is misconfigured`,
message:
`Your custom ${global.vectorConfig.brand || "Element"} configuration contains invalid JSON. ` +
`Please correct the problem and reopen ${global.vectorConfig.brand || "Element"}.`,
detail: e.message || "",
try {
// Load local config and use it to override values from the one baked with the build
const localConfig = loadLocalConfigFile();
// 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))) {
// 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>,
);
}
global.vectorConfig = Object.assign(global.vectorConfig, localConfig);
} catch (e) {
if (e instanceof SyntaxError) {
void dialog.showMessageBox({
type: "error",
title: `Your ${global.vectorConfig.brand || "Element"} is misconfigured`,
message:
`Your custom ${global.vectorConfig.brand || "Element"} configuration contains invalid JSON. ` +
`Please correct the problem and reopen ${global.vectorConfig.brand || "Element"}.`,
detail: e.message || "",
});
}
// Could not load local config, this is expected in most cases.
}
// Tweak modules paths as they assume the root is at the same level as webapp, but for `vector://vector/webapp` it is not.
if (Array.isArray(global.vectorConfig.modules)) {
global.vectorConfig.modules = global.vectorConfig.modules.map((m) => {
if (m.startsWith("/")) {
return "/webapp" + m;
}
return m;
});
}
// Could not load local config, this is expected in most cases.
}
loadConfigPromise = actuallyLoadConfig();
return loadConfigPromise;
}
// Configure Electron Sentry and crashReporter using sentry.dsn in config.json if one is present.
@@ -239,7 +253,7 @@ async function configureSentry(): Promise<void> {
}
}
// Set up globals for Tray and AutoLaunch
// Set up globals for Tray
async function setupGlobals(): Promise<void> {
const asarPath = await getAsarPath();
await loadConfig();
@@ -250,15 +264,6 @@ async function setupGlobals(): Promise<void> {
icon_path: path.join(path.dirname(asarPath), "build", iconFile),
brand: global.vectorConfig.brand || "Element",
};
// launcher
global.launcher = new AutoLaunch({
name: global.vectorConfig.brand || "Element",
isHidden: true,
mac: {
useLaunchAgent: true,
},
});
}
global.appQuitting = false;

View File

@@ -32,6 +32,11 @@
"speech_start_speaking": "Mulai Berbicara",
"speech_stop_speaking": "Berhenti Berbicara"
},
"eol": {
"no_more_updates": "Anda menggunakan versi macOS yang tidak didukung. Harap tingkatkan untuk menerima pembaruan %(brand)s.",
"title": "Sistem tidak didukung",
"warning": "Anda menggunakan versi macOS yang tidak didukung. Harap perbarui untuk memastikan%(brand)s terus bekerja."
},
"file_menu": {
"label": "Berkas"
},

View File

@@ -23,7 +23,7 @@
"brand_help": "%(brand)s Hjelp",
"help": "Hjelp",
"no": "Nei",
"preferences": "Brukervalg",
"preferences": "Innstillinger",
"yes": "Ja"
},
"confirm_quit": "Er du sikker på at du vil slutte?",
@@ -32,6 +32,11 @@
"speech_start_speaking": "Begynn å snakke",
"speech_stop_speaking": "Slutt å snakke"
},
"eol": {
"no_more_updates": "Du kjører en versjon av macOS som ikke støttes. Oppgrader for å motta oppdateringer fr %(brand)s.",
"title": "Systemet støttes ikke",
"warning": "Du bruker en versjon av macOS som ikke støttes. Oppgrader for å sikre at %(brand)s fortsetter å fungere."
},
"file_menu": {
"label": "Fil"
},

View File

@@ -32,6 +32,11 @@
"speech_start_speaking": "Zacznij mówić",
"speech_stop_speaking": "Przestań mówić"
},
"eol": {
"no_more_updates": "Korzystasz z nieobsługiwanej wersji systemu macOS. Zaktualizuj system, aby uzyskać aktualizacje %(brand)s.",
"title": "System nie jest obsługiwany",
"warning": "Korzystasz z nieobsługiwanej wersji systemu macOS. Zaktualizuj system, aby dalej korzystać z %(brand)s."
},
"file_menu": {
"label": "Plik"
},

View File

@@ -32,9 +32,15 @@
"speech_start_speaking": "Говорите",
"speech_stop_speaking": "Перестаньте говорить"
},
"eol": {
"title": "Система не поддерживается"
},
"file_menu": {
"label": "Файл"
},
"icon_overlay": {
"description_error": "Ошибка"
},
"menu": {
"hide": "Скрыть",
"hide_others": "Скрыть прочие",

View File

@@ -9,6 +9,7 @@ import { ipcMain } from "electron";
import * as tray from "./tray.js";
import Store from "./store.js";
import { AutoLaunch, type AutoLaunchState } from "./auto-launch.js";
interface Setting {
read(): Promise<any>;
@@ -18,15 +19,11 @@ interface Setting {
const Settings: Record<string, Setting> = {
"Electron.autoLaunch": {
async read(): Promise<any> {
return global.launcher.isEnabled();
async read(): Promise<AutoLaunchState> {
return AutoLaunch.instance.getState();
},
async write(value: any): Promise<void> {
if (value) {
return global.launcher.enable();
} else {
return global.launcher.disable();
}
async write(value: AutoLaunchState): Promise<void> {
return AutoLaunch.instance.setState(value);
},
},
"Electron.warnBeforeExit": {

View File

@@ -89,6 +89,8 @@ interface StoreData {
safeStorageBackendOverride?: boolean;
/** whether to perform a migration of the safeStorage data */
safeStorageBackendMigrate?: boolean;
/** whether to open the app at login minimised, only valid when app.openAtLogin is true */
openAtLoginMinimised: boolean;
}
/**
@@ -232,6 +234,10 @@ class Store extends ElectronStore<StoreData> {
safeStorageBackendMigrate: {
type: "boolean",
},
openAtLoginMinimised: {
type: "boolean",
default: true,
},
},
});
}

1153
yarn.lock
View File

File diff suppressed because it is too large Load Diff