From 36e320babedef6123ce933f25b576362707a5e75 Mon Sep 17 00:00:00 2001 From: Polina Vishneva Date: Wed, 17 Jun 2026 15:28:09 +0200 Subject: [PATCH 1/3] assets/desktop-icon: Add a GNOME-padded Linux icon Also generate a scalable SVG icon bc it's the new standard. --- assets/desktop-icon/build.mjs | 31 +++++++++++++++++++++-------- assets/desktop-icon/icon-linux.png | Bin 0 -> 23048 bytes assets/desktop-icon/icon-linux.svg | 12 +++++++++++ 3 files changed, 35 insertions(+), 8 deletions(-) create mode 100644 assets/desktop-icon/icon-linux.png create mode 100644 assets/desktop-icon/icon-linux.svg diff --git a/assets/desktop-icon/build.mjs b/assets/desktop-icon/build.mjs index 834eec815..46db5edf0 100644 --- a/assets/desktop-icon/build.mjs +++ b/assets/desktop-icon/build.mjs @@ -1,10 +1,14 @@ -// Generate the electron-builder desktop icons from the glyph SVG, all in this -// dir: icon.png (full-bleed square, for Linux/Windows) and icon.icns (macOS -// squircle with Apple's standard padding, since macOS doesn't auto-round). -// Re-run after changing the glyph: `node assets/desktop-icon/build.mjs`. -// Requires ImageMagick (`magick`) and, for the .icns, macOS `iconutil`. +/* Generate the electron-builder desktop icons from the glyph SVG, all in this + * dir. None of Windows/Linux/macOS auto-round, so generate the icons here: + * + * 1. icon.png - full-bleed square for Windows, + * 2. icon-linux.{svg,png} - Linux squircle (GNOME HIG padding and rounding), + * 3. icon.icns - macOS squircle with Apple's standard padding. + * + * Re-run after changing the glyph: `node assets/desktop-icon/build.mjs`. + * Requires ImageMagick (`magick`) and, for the .icns, macOS `iconutil`. */ import {spawnSync} from 'child_process'; -import {mkdirSync, readFileSync, rmSync} from 'fs'; +import {mkdirSync, readFileSync, rmSync, writeFileSync} from 'fs'; import {dirname, join} from 'path'; import {fileURLToPath} from 'url'; @@ -18,6 +22,12 @@ const BG_TO = '#D59EFF'; const MAC_CONTENT = 824; const MAC_MARGIN = (SIZE - MAC_CONTENT) / 2; const MAC_RADIUS = 185; +// GNOME app-icon: a 103×103 rounded square (8px corners) centered in the +// 128 grid. Our icon is 1024x1024, so scaled dimensions are: 824px content, +// 100px margin, 64px radius (same content box as macOS, softer corners). +const GNOME_CONTENT = 824; +const GNOME_MARGIN = (SIZE - GNOME_CONTENT) / 2; +const GNOME_RADIUS = 64; const glyph = readFileSync(join(dir, 'icon.svg'), 'utf8'); const viewBox = glyph.match(/viewBox\s*=\s*"\s*0\s+0\s+([\d.]+)\s+([\d.]+)\s*"/); @@ -57,10 +67,15 @@ function render(svg, out) { } const square = buildSvg({size: SIZE, offset: 0, radius: 0}); -const pngPath = join(dir, 'icon.png'); -render(square, pngPath); +render(square, join(dir, 'icon.png')); console.log('wrote assets/desktop-icon/icon.png'); +const linux = buildSvg({size: GNOME_CONTENT, offset: GNOME_MARGIN, radius: GNOME_RADIUS}); +writeFileSync(join(dir, 'icon-linux.svg'), linux); +console.log('wrote assets/desktop-icon/icon-linux.svg'); +render(linux, join(dir, 'icon-linux.png')); +console.log('wrote assets/desktop-icon/icon-linux.png'); + if (process.platform !== 'darwin') { console.log('[build-app-icon] skipping .icns (needs macOS iconutil)'); process.exit(0); diff --git a/assets/desktop-icon/icon-linux.png b/assets/desktop-icon/icon-linux.png new file mode 100644 index 0000000000000000000000000000000000000000..1ec4987b28e0802c20f8f678ca70df0c8d53a983 GIT binary patch literal 23048 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 bi2Gl^cA_bxG2dJPkefVR{an^LB{Ts5%=x{^ literal 0 HcmV?d00001 diff --git a/assets/desktop-icon/icon-linux.svg b/assets/desktop-icon/icon-linux.svg new file mode 100644 index 000000000..528704bfa --- /dev/null +++ b/assets/desktop-icon/icon-linux.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + From 266b9a3caf1169ec8f9a466ad900d21777fdf1ed Mon Sep 17 00:00:00 2001 From: Polina Vishneva Date: Wed, 17 Jun 2026 12:35:27 +0200 Subject: [PATCH 2/3] electron-builder: Add flatpak target --- electron-builder.yml | 20 ++++++++++++++++++-- package.json | 3 ++- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/electron-builder.yml b/electron-builder.yml index dbc1e1d78..40e62bb28 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -1,4 +1,6 @@ -appId: desu.inutweb +# Flatpak requires appId to be a valid D-Bus bus name. A valid D-Bus bus name +# contains at least 3 segments (intended for reverse dns notation). +appId: pet.tei.inutweb productName: inutweb copyright: abolish copyright law @@ -33,9 +35,23 @@ win: linux: category: Network - icon: assets/desktop-icon/icon.png + icon: assets/desktop-icon/icon-linux.png + syncDesktopName: true target: - AppImage + - flatpak + +# electron-builder defaults to 20.08 for some reason; it's not even +# on Flathub anymore. +flatpak: + runtimeVersion: "25.08" + baseVersion: "25.08" + # electron-builder doesn't add the png icon specified above because it's + # 1024px, and flatpak target skips anything >512px. + # Add a proper scalable icon manually. + files: + - - assets/desktop-icon/icon-linux.svg + - /share/icons/hicolor/scalable/apps/pet.tei.inutweb.svg nsis: oneClick: false diff --git a/package.json b/package.json index 6154708d0..3a17ad1e8 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,7 @@ "version": "1.0.0", "license": "GPL-3.0-only", "main": "dist-electron/main.js", + "desktopName": "pet.tei.inutweb.desktop", "engines": { "node": ">=22" }, @@ -72,4 +73,4 @@ "vitest": "^4.1.0" }, "packageManager": "pnpm@10.34.3+sha512.f2c531b08829d7be7f03c90addc266615f9c5477463e4bf1d275cb263ce9ea57cf0d5599110d94649a9bb3fed9f0b5efcea74a7016b61532a24cb9ad87860c1d" -} \ No newline at end of file +} From 7ae14356938b769ee50835084a315294d31d9209 Mon Sep 17 00:00:00 2001 From: Polina Vishneva Date: Wed, 17 Jun 2026 12:54:06 +0200 Subject: [PATCH 3/3] workflows/desktop-build: Add flatpak job --- .github/workflows/desktop-build.yml | 37 ++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/.github/workflows/desktop-build.yml b/.github/workflows/desktop-build.yml index fc7658ef8..078e8523b 100644 --- a/.github/workflows/desktop-build.yml +++ b/.github/workflows/desktop-build.yml @@ -11,14 +11,27 @@ jobs: matrix: include: - os: macos-latest + target: --mac dmg artifact: macos-dmg pattern: release/*.dmg - os: ubuntu-latest + target: --linux AppImage artifact: linux-appimage pattern: release/*.AppImage + - os: ubuntu-latest + target: --linux flatpak + artifact: linux-flatpak + pattern: release/*.flatpak + container: ghcr.io/flathub-infra/flatpak-github-actions:freedesktop-25.08 + container-options: --privileged runs-on: ${{ matrix.os }} + # Ignored if empty + container: + image: ${{ matrix.container || '' }} + options: ${{ matrix.container-options || '' }} + steps: - name: Checkout code uses: actions/checkout@v4 @@ -39,11 +52,33 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile + # electron-builder always auto-installs the Electron base app via + # "flatpak install --user". flatpak-github-actions' container only has + # flathub as a system remote. Work this around by pre-installing + # (then the bundler just updates it). + - name: Install Flatpak deps + if: matrix.artifact == 'linux-flatpak' + run: flatpak install --system --noninteractive flathub org.electronjs.Electron2.BaseApp//25.08 + + # flatpak-builder's rofiles-fuse doesn't work in containers (no fuse), + # and electron-builder has no way to pass arguments to flatpak-builder, + # so make a wrapper. + - name: Make a flatpak-builder wrapper + if: matrix.artifact == 'linux-flatpak' + run: | + fb="$(command -v flatpak-builder)" + mv "$fb" "$fb.real" + printf '#!/bin/sh\nexec "%s" --disable-rofiles-fuse "$@"\n' "$fb.real" >"$fb" + chmod +x "$fb" + - name: Build - run: pnpm run electron:dist + run: pnpm run electron:dist ${{ matrix.target }} env: # don't try to codesign / notarize in CI CSC_IDENTITY_AUTO_DISCOVERY: false + # flatpak-bundler pipes flatpak's stdout/stderr through 'debug', + # hiding all the diagnostics. + DEBUG: "@malept/flatpak-bundler" - name: Upload artifact uses: actions/upload-artifact@v4