fix(electron): real VNCmail+ branding, not just a rename
Every prior distributable DMG this session was built with plain `npx electron-builder`, never `--config electron-builder.config.js`. electron- builder does not auto-detect a file named electron-builder.config.js (its search list is .yml/.yaml/.json/.json5/.js/.cjs/.mjs/.ts, not .config.js), so the config - correct productName/appId/icon and all - was silently ignored on every build. Caught only by actually launching the packaged .app: it booted to "Bulwark Webmail Setup" demanding a token from container logs, default Electron atom icon, output in dist/ instead of dist-electron-builds/. Fixes, each verified against the packaged .app (Playwright _electron.launch, not the build log): - Add dist:mac/win/linux/dir scripts that pass --config explicitly, so this can't recur. - Dedicated 1024x1024 app icon (build-resources/app-icon.png, SRC symbol on #09090b) instead of reusing the web PWA manifest icon. Verified: icns ships at 1024x1024, pixel-identical to the source (mean diff 0.0/255). - electron/main.ts: getDesktopDefaults() sets JMAP_SERVER_URL to the sandbox (the ONLY thing that puts the server into "env-managed" mode and skips the setup wizard - see lib/setup/state.ts), plus APP_NAME/login logo/ favicon/company-name env vars, spread before ...process.env so a real deployment still overrides. Verified: packaged app now opens straight to a login screen with the JMAP endpoint field pre-filled https://stalwart.sandbox.vnc.de, title "VNCmail+", SRC logo. - LOGIN_SHOW_SUBTITLE=false: the subtitle falls back to the login.title i18n string ("Webmail") whenever it differs from APP_NAME - a check written for the original Bulwark pairing where they matched. Hiding it avoids touching that shared string for every other deployment.
This commit is contained in:
Binary file not shown.
|
After Width: | Height: | Size: 100 KiB |
+22
-14
@@ -58,20 +58,28 @@ module.exports = {
|
|||||||
to: ".",
|
to: ".",
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
// STAND-IN ICON, not a dedicated app icon: public/icon-512x512.png is the
|
// Dedicated 1024x1024 app icon: the SRC symbol centred on the SRC dark
|
||||||
// PWA manifest icon (512x512 square PNG). electron-builder can generate
|
// ground (#09090b), generated from public/branding/SRC_Symbol.png into
|
||||||
// .icns/.ico from a single square PNG at build time (see
|
// build-resources/app-icon.png (NOT build/ - that's electron-builder's own
|
||||||
// node_modules/app-builder-lib/out/util/iconConverter.js), so this
|
// gitignored output dir; a source asset living inside it would never get
|
||||||
// produces working icons for every target below - but at only 512x512,
|
// committed, which is exactly the bug this comment is warning about one
|
||||||
// the largest macOS icns representation (1024x1024 "ICON512@2x") gets
|
// paragraph down). 1024 is the size macOS actually wants for the largest
|
||||||
// upsampled and will look soft compared to a real 1024x1024+ source.
|
// icns representation ("ICON512@2x"), so nothing gets upsampled.
|
||||||
// public/branding/Bulwark_Icon_App.svg looks like the intended master for
|
//
|
||||||
// this (as opposed to Bulwark_Favicon.png, sized for browser tabs), but
|
// Deliberately NOT public/icon-512x512.png (what this used to point at):
|
||||||
// it's vector and this environment has no SVG rasterizer (rsvg-convert /
|
// that file is the *web* PWA manifest icon, so retouching it for the
|
||||||
// ImageMagick / Inkscape) to turn it into a proper 1024x1024 PNG. A human
|
// desktop app silently changes the browser/PWA install icon too. Separate
|
||||||
// (or a follow-up step with the right tooling) should export
|
// source, separate concern.
|
||||||
// Bulwark_Icon_App.svg at 1024x1024 and point `icon` at that instead.
|
//
|
||||||
icon: "public/icon-512x512.png",
|
// NOTE for whoever runs this next: electron-builder does NOT auto-detect a
|
||||||
|
// file named `electron-builder.config.js` - its search list is
|
||||||
|
// electron-builder.{yml,yaml,json,json5,js,cjs,mjs,ts}. Packaging must be
|
||||||
|
// invoked with an explicit `--config electron-builder.config.js`, or every
|
||||||
|
// setting in this file is silently ignored and you get stock defaults
|
||||||
|
// (default Electron atom icon, `dist/` output, productName taken from
|
||||||
|
// package.json's `name`). See the `dist:*` scripts in package.json, which
|
||||||
|
// exist so nobody has to remember that.
|
||||||
|
icon: "build-resources/app-icon.png",
|
||||||
mac: {
|
mac: {
|
||||||
target: [
|
target: [
|
||||||
{ target: "dmg", arch: ["x64", "arm64"] },
|
{ target: "dmg", arch: ["x64", "arm64"] },
|
||||||
|
|||||||
@@ -70,6 +70,51 @@ function getServerDataDirs(): Record<string, string> {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Desktop-shell defaults for a fresh, un-configured install.
|
||||||
|
*
|
||||||
|
* Setting JMAP_SERVER_URL puts the standalone server into "env-managed"
|
||||||
|
* mode (see lib/setup/state.ts's detectSetupState()) - the ONLY thing that
|
||||||
|
* disables the setup wizard short of an operator finishing it by hand. Every
|
||||||
|
* distributable build of this desktop shell up to 2026-08-05 skipped this,
|
||||||
|
* so handing someone the packaged app landed them on "Bulwark Webmail
|
||||||
|
* Setup" asking for a token out of container logs they have no access to -
|
||||||
|
* caught only by actually launching the packaged .app and looking, not by
|
||||||
|
* reading the build log.
|
||||||
|
*
|
||||||
|
* The rest are CONFIG_ENV_MAP entries (lib/admin/types.ts) that only matter
|
||||||
|
* while env-managed - once an admin completes the wizard, config.json wins
|
||||||
|
* for everything except jmapServerUrl itself. allowCustomJmapEndpoint keeps
|
||||||
|
* the server field on the login screen editable, so this is a starting
|
||||||
|
* point for the sandbox, not a hard lock to it.
|
||||||
|
*
|
||||||
|
* `...process.env` in startStandaloneServer() below is spread AFTER this
|
||||||
|
* object, so a real deployment env (the Dockerfile path, or a future
|
||||||
|
* per-install override) still wins over these defaults.
|
||||||
|
*/
|
||||||
|
function getDesktopDefaults(): Record<string, string> {
|
||||||
|
return {
|
||||||
|
JMAP_SERVER_URL: "https://stalwart.sandbox.vnc.de",
|
||||||
|
APP_NAME: "VNCmail+",
|
||||||
|
APP_SHORT_NAME: "VNCmail+",
|
||||||
|
LOGIN_LOGO_LIGHT_URL: "/branding/SRC_Symbol.png",
|
||||||
|
LOGIN_LOGO_DARK_URL: "/branding/SRC_Symbol.png",
|
||||||
|
LOGIN_COMPANY_NAME: "VNC AG",
|
||||||
|
FAVICON_URL: "/branding/SRC_Symbol.png",
|
||||||
|
ALLOW_CUSTOM_JMAP_ENDPOINT: "true",
|
||||||
|
// The login page's subtitle falls back to the login.title i18n string
|
||||||
|
// whenever it differs from appName (app/(main)/[locale]/login/page.tsx)
|
||||||
|
// - a check clearly written for the original Bulwark/"Webmail" pairing,
|
||||||
|
// where they matched. With APP_NAME overridden to "VNCmail+" they no
|
||||||
|
// longer match, so the raw translation ("Webmail") surfaces instead of
|
||||||
|
// anything brand-appropriate. Hiding the subtitle avoids editing a
|
||||||
|
// shared i18n string that every other deployment (incl. Bulwark
|
||||||
|
// default) still uses - the SRC logo + "VNCmail+" heading is enough
|
||||||
|
// context on its own.
|
||||||
|
LOGIN_SHOW_SUBTITLE: "false",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locates the standalone server's entrypoint. Packaged builds ship it as an
|
* Locates the standalone server's entrypoint. Packaged builds ship it as an
|
||||||
* extraResource (see electron-builder.config.js) because .next/standalone
|
* extraResource (see electron-builder.config.js) because .next/standalone
|
||||||
@@ -156,6 +201,10 @@ async function startStandaloneServer(): Promise<string> {
|
|||||||
// what travels over it is.
|
// what travels over it is.
|
||||||
serverProcess = spawn(process.execPath, [serverEntry], {
|
serverProcess = spawn(process.execPath, [serverEntry], {
|
||||||
env: {
|
env: {
|
||||||
|
// First, so any real deployment env (a future per-install override,
|
||||||
|
// or this same binary run somewhere JMAP_SERVER_URL is already set)
|
||||||
|
// wins over these desktop-shell defaults - see getDesktopDefaults().
|
||||||
|
...getDesktopDefaults(),
|
||||||
...process.env,
|
...process.env,
|
||||||
ELECTRON_RUN_AS_NODE: "1",
|
ELECTRON_RUN_AS_NODE: "1",
|
||||||
PORT: String(port),
|
PORT: String(port),
|
||||||
|
|||||||
@@ -36,6 +36,11 @@
|
|||||||
"build:standalone": "npm run build:plugins && next build --webpack && node scripts/assemble-standalone.mjs",
|
"build:standalone": "npm run build:plugins && next build --webpack && node scripts/assemble-standalone.mjs",
|
||||||
"build:electron": "node scripts/build-electron.mjs",
|
"build:electron": "node scripts/build-electron.mjs",
|
||||||
"electron:dev": "npm run build:standalone && npm run build:electron && electron .",
|
"electron:dev": "npm run build:standalone && npm run build:electron && electron .",
|
||||||
|
"dist:prepare": "npm run build:standalone && npm run build:electron",
|
||||||
|
"dist:dir": "npm run dist:prepare && electron-builder --config electron-builder.config.js --dir",
|
||||||
|
"dist:mac": "npm run dist:prepare && electron-builder --config electron-builder.config.js --mac",
|
||||||
|
"dist:win": "npm run dist:prepare && electron-builder --config electron-builder.config.js --win",
|
||||||
|
"dist:linux": "npm run dist:prepare && electron-builder --config electron-builder.config.js --linux",
|
||||||
"test:electron": "playwright test -c playwright.electron.config.ts",
|
"test:electron": "playwright test -c playwright.electron.config.ts",
|
||||||
"test:integration:electron": "npm run build:standalone && npm run build:electron && playwright test -c playwright.integration-electron.config.ts"
|
"test:integration:electron": "npm run build:standalone && npm run build:electron && playwright test -c playwright.integration-electron.config.ts"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user