diff --git a/electron-builder.yml b/electron-builder.yml index 3cc90d26d..1a6ea96f4 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -78,7 +78,7 @@ dmg: win: forceCodeSigning: false verifyUpdateCodeSignature: false - signAndEditExecutable: false + signAndEditExecutable: true extraResources: - from: resources/bin/win32-${arch} to: bin diff --git a/electron/main/index.ts b/electron/main/index.ts index 42f4aed88..206467ba9 100644 --- a/electron/main/index.ts +++ b/electron/main/index.ts @@ -2,7 +2,7 @@ * Electron Main Process Entry * Manages window creation, system tray, and IPC handlers */ -import { app, BrowserWindow, session, shell } from 'electron'; +import { app, BrowserWindow, nativeImage, session, shell } from 'electron'; import { join } from 'path'; import { GatewayManager } from '../gateway/manager'; import { registerIpcHandlers } from './ipc-handlers'; @@ -22,6 +22,33 @@ let mainWindow: BrowserWindow | null = null; const gatewayManager = new GatewayManager(); const clawHubService = new ClawHubService(); +/** + * Resolve the icons directory path (works in both dev and packaged mode) + */ +function getIconsDir(): string { + if (app.isPackaged) { + // Packaged: icons are in extraResources → process.resourcesPath/resources/icons + return join(process.resourcesPath, 'resources', 'icons'); + } + // Development: relative to dist-electron/main/ + return join(__dirname, '../../resources/icons'); +} + +/** + * Get the app icon for the current platform + */ +function getAppIcon(): Electron.NativeImage | undefined { + if (process.platform === 'darwin') return undefined; // macOS uses the app bundle icon + + const iconsDir = getIconsDir(); + const iconPath = + process.platform === 'win32' + ? join(iconsDir, 'icon.ico') + : join(iconsDir, 'icon.png'); + const icon = nativeImage.createFromPath(iconPath); + return icon.isEmpty() ? undefined : icon; +} + /** * Create the main application window */ @@ -33,6 +60,7 @@ function createWindow(): BrowserWindow { height: 800, minWidth: 960, minHeight: 600, + icon: getAppIcon(), webPreferences: { preload: join(__dirname, '../preload/index.js'), nodeIntegration: false, diff --git a/electron/main/tray.ts b/electron/main/tray.ts index c3c8a6117..a1b975780 100644 --- a/electron/main/tray.ts +++ b/electron/main/tray.ts @@ -7,22 +7,42 @@ import { join } from 'path'; let tray: Tray | null = null; +/** + * Resolve the icons directory path (works in both dev and packaged mode) + */ +function getIconsDir(): string { + if (app.isPackaged) { + return join(process.resourcesPath, 'resources', 'icons'); + } + return join(__dirname, '../../resources/icons'); +} + /** * Create system tray icon and menu */ export function createTray(mainWindow: BrowserWindow): Tray { - // Create tray icon - const iconPath = join(__dirname, '../../resources/icons/tray-icon.png'); - - // Create a template image for macOS (adds @2x support automatically) - let icon = nativeImage.createFromPath(iconPath); - - // If icon doesn't exist, create a simple placeholder - if (icon.isEmpty()) { - // Create a simple 16x16 icon as placeholder - icon = nativeImage.createEmpty(); + // Use platform-appropriate icon for system tray + const iconsDir = getIconsDir(); + let iconPath: string; + + if (process.platform === 'win32') { + // Windows: use .ico for best quality in system tray + iconPath = join(iconsDir, 'icon.ico'); + } else if (process.platform === 'darwin') { + // macOS: use 16x16 PNG as template image + iconPath = join(iconsDir, '16x16.png'); + } else { + // Linux: use 32x32 PNG + iconPath = join(iconsDir, '32x32.png'); } - + + let icon = nativeImage.createFromPath(iconPath); + + // Fallback to icon.png if platform-specific icon not found + if (icon.isEmpty()) { + icon = nativeImage.createFromPath(join(iconsDir, 'icon.png')); + } + // On macOS, set as template image for proper dark/light mode support if (process.platform === 'darwin') { icon.setTemplateImage(true); diff --git a/public/icons/icon.png b/public/icons/icon.png deleted file mode 100644 index 8c1712923..000000000 Binary files a/public/icons/icon.png and /dev/null differ