From 3125b083ca97d14742a964e7ab48c5de457b3d71 Mon Sep 17 00:00:00 2001 From: prompt.ac/@jeffrey Date: Wed, 10 Jun 2026 01:17:55 +0000 Subject: [PATCH] ac-electron v0.1.47: theme-aware dock icon (light/dark plates) - generate-icons.mjs emits build/icon-light.png (lavender-white plate) alongside the dark navy default. - main.js swaps the dock icon live on nativeTheme 'updated' instead of always-dark. - build/icon*.png are now packaged in files[] — app.dock.setIcon was a silent no-op in production builds because icon.png never shipped in the asar. Co-Authored-By: Claude Fable 5 (1M context) --- ac-electron/main.js | 16 ++++++++++++---- ac-electron/package-lock.json | 4 ++-- ac-electron/package.json | 4 +++- ac-electron/scripts/generate-icons.mjs | 45 ++++++++++++++++++++++++++------------------- 4 file(s) changed, 43 insertion(s)(+), 26 deletion(s)(-) diff --git a/ac-electron/main.js b/ac-electron/main.js --- a/ac-electron/main.js +++ b/ac-electron/main.js @@ -5,7 +5,7 @@ * Single window type: * - AC Pane (3D flip view with front webview + back terminal) */ -const { app, BrowserWindow, ipcMain, globalShortcut, Menu, Tray, dialog, shell, nativeImage, screen, Notification, net, session, systemPreferences } = require('electron'); +const { app, BrowserWindow, ipcMain, globalShortcut, Menu, Tray, dialog, shell, nativeImage, screen, Notification, net, session, systemPreferences, nativeTheme } = require('electron'); const path = require('path'); const fs = require('fs'); const http = require('http'); @@ -523,18 +523,26 @@ // Set app name before anything else app.setName('Aesthetic.Computer'); process.title = 'Aesthetic.Computer'; -// Set dock icon on macOS -if (process.platform === 'darwin') { - const iconPath = path.join(__dirname, 'build', 'icon.png'); +// Set dock icon on macOS — theme-aware: dark plate in dark mode, light plate +// in light mode, re-applied live whenever the system appearance flips. +function applyDockIcon() { + if (process.platform !== 'darwin' || !app.dock) return; + const variant = nativeTheme.shouldUseDarkColors ? 'icon.png' : 'icon-light.png'; + const iconPath = path.join(__dirname, 'build', variant); try { const icon = nativeImage.createFromPath(iconPath); if (!icon.isEmpty()) { app.dock.setIcon(icon); + console.log(`[dock] icon → ${variant} (${nativeTheme.shouldUseDarkColors ? 'dark' : 'light'} appearance)`); + } else { + console.warn(`[dock] icon missing or empty: ${iconPath}`); } } catch (e) { console.warn('Could not set dock icon:', e.message); } } +applyDockIcon(); +nativeTheme.on('updated', applyDockIcon); // On macOS, hide the dock icon when there are no visible windows so the app // acts as a pure menubar daemon. Shown again as soon as any window opens. diff --git a/ac-electron/package-lock.json b/ac-electron/package-lock.json --- a/ac-electron/package-lock.json +++ b/ac-electron/package-lock.json @@ -1,12 +1,12 @@ { "name": "aesthetic-computer", - "version": "0.1.46", + "version": "0.1.47", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "aesthetic-computer", - "version": "0.1.46", + "version": "0.1.47", "license": "MIT", "dependencies": { "@electron/rebuild": "^4.0.2", diff --git a/ac-electron/package.json b/ac-electron/package.json --- a/ac-electron/package.json +++ b/ac-electron/package.json @@ -1,6 +1,6 @@ { "name": "aesthetic-computer", - "version": "0.1.46", + "version": "0.1.47", "description": "Aesthetic Computer", "homepage": "https://aesthetic.computer", "author": "Aesthetic Computer ", @@ -127,6 +127,8 @@ "webview-preload.js", "offscreen-manager.js", "ff1-bridge.js", "renderer/**/*", + "build/icon.png", + "build/icon-light.png", "build/icons/trayTemplate.png", "build/icons/trayTemplate@2x.png", "build/icons/notepatTrayTemplate.png", diff --git a/ac-electron/scripts/generate-icons.mjs b/ac-electron/scripts/generate-icons.mjs --- a/ac-electron/scripts/generate-icons.mjs +++ b/ac-electron/scripts/generate-icons.mjs @@ -56,14 +56,16 @@ // Ensure directories exist await ensureDir(buildDir); await ensureDir(iconsDir); - // The SVG has a transparent background, let's add a background color - // for the app icon (purple to match the pals theme) - const backgroundColor = '#1a1a2e'; // Dark purple/navy background + // The SVG has a transparent background; the app icon adds a squircle plate + // behind it. Two plates: dark (default / icns) and light (dock swaps to it + // at runtime when the system is in light mode). + const backgroundColor = '#1a1a2e'; // Dark purple/navy plate + const lightBackgroundColor = '#f4f1f7'; // Light lavender-white plate // macOS icon layout: 1024x1024 canvas, ~100px padding around a 824x824 foreground, // then masked by a squircle (rounded rect with rx~228) so the Dock renders it // with the familiar rounded-square silhouette. - console.log('šŸ“± Generating macOS icon (1024x1024, squircle-masked)...'); + console.log('šŸ“± Generating macOS icons (1024x1024, squircle-masked, dark + light)...'); const ICON_SIZE = 1024; const FG_SIZE = 824; const FG_OFFSET = Math.round((ICON_SIZE - FG_SIZE) / 2); @@ -83,21 +85,26 @@ `` + ``, ); - await sharp({ - create: { - width: ICON_SIZE, - height: ICON_SIZE, - channels: 4, - background: backgroundColor, - }, - }) - .composite([ - { input: foreground, top: FG_OFFSET, left: FG_OFFSET }, - { input: squircleMask, blend: 'dest-in' }, - ]) - .png() - .toFile(path.join(buildDir, 'icon.png')); - console.log(' āœ… build/icon.png (squircle)'); + async function squircleIcon(plateColor, outName) { + await sharp({ + create: { + width: ICON_SIZE, + height: ICON_SIZE, + channels: 4, + background: plateColor, + }, + }) + .composite([ + { input: foreground, top: FG_OFFSET, left: FG_OFFSET }, + { input: squircleMask, blend: 'dest-in' }, + ]) + .png() + .toFile(path.join(buildDir, outName)); + console.log(` āœ… build/${outName} (squircle, ${plateColor})`); + } + + await squircleIcon(backgroundColor, 'icon.png'); + await squircleIcon(lightBackgroundColor, 'icon-light.png'); // Generate Linux icons at various sizes console.log('\n🐧 Generating Linux icons...'); -- tangled.sh