Skip to content

Commit 5669d69

Browse files
committed
fix: resolve headless mode config path on macOS/Linux
Fixed critical bug where headless mode on macOS and Linux was reading per-printer settings from the wrong directory, causing custom camera and LED configurations to appear as "not configured" even though they worked in normal UI mode. Root cause: Module import order caused ConfigManager and PrinterDetailsManager singletons to capture app.getPath('userData') before app.setName('FlashForgeUI') was called, resulting in different paths for headless vs normal mode. Solution: Created bootstrap.ts to set app name before any module imports, ensuring all singletons use the correct userData path across all platforms and execution modes. Also includes CI improvements: - Switch from npm install to npm ci in GitHub Actions for faster builds - Add platform-specific CI build commands - Disable source maps and declaration files in production builds
1 parent 9ba4919 commit 5669d69

5 files changed

Lines changed: 58 additions & 25 deletions

File tree

.github/workflows/release.yml

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,10 @@ jobs:
4141
env:
4242
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
4343

44-
- name: Run npm install
44+
- name: Run npm ci
4545
shell: bash
4646
run: |
47-
npm install --verbose
47+
npm ci
4848
env:
4949
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
5050

@@ -65,21 +65,11 @@ jobs:
6565
run: |
6666
# Use platform-specific build commands
6767
if [[ "$RUNNER_OS" == "Linux" ]]; then
68-
npm run build:linux
68+
npm run build:ci:linux
6969
elif [[ "$RUNNER_OS" == "Windows" ]]; then
70-
npm run build:win
70+
npm run build:ci:win
7171
elif [[ "$RUNNER_OS" == "macOS" ]]; then
72-
npm run build:mac
73-
fi
74-
75-
- name: List Build Artifacts
76-
shell: bash
77-
run: |
78-
echo "Listing contents of dist directory:"
79-
if [[ "$RUNNER_OS" == "Windows" ]]; then
80-
dir /s dist || echo "dist directory not found or empty."
81-
else
82-
ls -R dist || echo "dist directory not found or empty."
72+
npm run build:ci:mac
8373
fi
8474
8575
- name: Upload Build Artifacts

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
"build:linux": "npm run build && electron-builder --linux --publish never --config electron-builder-config.js",
1919
"build:win": "npm run build && electron-builder --win --publish never --config electron-builder-config.js && rimraf dist/win-unpacked",
2020
"build:mac": "npm run build && electron-builder --mac --publish never --config electron-builder-config.js",
21+
"build:ci:linux": "npm run build && electron-builder --linux --publish never --config electron-builder-config.js",
22+
"build:ci:win": "npm run build && electron-builder --win --publish never --config electron-builder-config.js && rimraf dist/win-unpacked",
23+
"build:ci:mac": "npm run build && electron-builder --mac --publish never --config electron-builder-config.js",
2124
"lint": "eslint src/**/*.ts",
2225
"lint:fix": "eslint src/**/*.ts --fix",
2326
"linecount": "powershell -ExecutionPolicy Bypass -File scripts/count_lines.ps1",

src/bootstrap.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* @fileoverview Bootstrap module for FlashForgeUI Electron application.
3+
*
4+
* CRITICAL: This file must be imported FIRST in index.ts, before any other imports.
5+
*
6+
* Purpose:
7+
* Sets the Electron app name and user model ID before any singletons are instantiated.
8+
* This ensures that all services using app.getPath('userData') point to the correct
9+
* directory across all platforms and execution modes (normal UI and headless).
10+
*
11+
* Problem it solves:
12+
* - Singletons like ConfigManager and PrinterDetailsManager capture app.getPath('userData')
13+
* during construction
14+
* - If app.setName() is called after these singletons are created, they will use the wrong
15+
* directory (e.g., "Electron" instead of "FlashForgeUI")
16+
* - This caused headless mode on macOS/Linux to read from a different config directory
17+
* than the main UI, resulting in missing per-printer settings (custom camera/LED config)
18+
*
19+
* Platform-specific userData paths:
20+
* - macOS: ~/Library/Application Support/FlashForgeUI/
21+
* - Linux: ~/.config/FlashForgeUI/
22+
* - Windows: %APPDATA%/FlashForgeUI/
23+
*
24+
* Without this bootstrap (default "Electron" name):
25+
* - macOS: ~/Library/Application Support/Electron/
26+
* - Linux: ~/.config/Electron/
27+
* - Windows: %APPDATA%/Electron/
28+
*/
29+
30+
import { app } from 'electron';
31+
32+
// Set app name BEFORE any singletons are created
33+
// This ensures ConfigManager, PrinterDetailsManager, and all other services
34+
// use the correct userData directory path
35+
app.setName('FlashForgeUI');
36+
37+
// Set AppUserModelId to match electron-builder appId for proper notification routing
38+
// This works across all platforms (Windows uses it for Action Center, macOS for notification attribution)
39+
app.setAppUserModelId('com.ghosttypes.flashforgeui');
40+
41+
console.log('[Bootstrap] App name set to "FlashForgeUI"');
42+
console.log(`[Bootstrap] userData path: ${app.getPath('userData')}`);

src/index.ts

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
* - Managing application-level concerns like power-saving and environment detection.
1818
*/
1919

20+
// CRITICAL: Bootstrap must be imported FIRST to set app name before any singletons are created
21+
import './bootstrap';
22+
2023
import { app, BrowserWindow, dialog, powerSaveBlocker, ipcMain } from 'electron';
2124
import { getConfigManager } from './managers/ConfigManager';
2225
import { getPrinterConnectionManager } from './managers/ConnectionFlowManager';
@@ -73,13 +76,8 @@ if (!gotTheLock) {
7376
});
7477
}
7578

76-
// Set AppUserModelId to match electron-builder appId for proper notification routing
77-
// This works across all platforms (Windows uses it for Action Center, macOS for notification attribution)
78-
app.setAppUserModelId('com.ghosttypes.flashforgeui');
79-
80-
// Ensure app uses the correct name for userData directory
81-
// This must be set before any services that use app.getPath('userData') are initialized
82-
app.setName('FlashForgeUI');
79+
// Note: app.setName() and app.setAppUserModelId() are now called in bootstrap.ts
80+
// to ensure they execute before any singleton initialization
8381

8482
// Initialize global reference for camera IPC handler
8583
global.printerBackendManager = undefined;

tsconfig.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212
"moduleResolution": "node",
1313
"allowSyntheticDefaultImports": true,
1414
"resolveJsonModule": true,
15-
"declaration": true,
16-
"declarationMap": true,
17-
"sourceMap": true,
15+
"declaration": false,
16+
"declarationMap": false,
17+
"sourceMap": false,
1818
"noImplicitAny": true,
1919
"noImplicitReturns": true,
2020
"noImplicitThis": true,

0 commit comments

Comments
 (0)