From 7e18aa9b4f46874c2840cb80731ddd484cb447cf Mon Sep 17 00:00:00 2001 From: dtzp555 Date: Thu, 19 Mar 2026 21:56:35 +1000 Subject: [PATCH] feat: add tray support and cross-platform packaging assets (v0.9.6) - Generate placeholder icons: icon.png (512x512), tray-icon.png (16x16), icon.icns (macOS) - Fix window close behavior: hide to tray instead of quitting - Add tray left-click and double-click handlers to restore window - Add app.dock.hide/show on macOS for proper dock visibility - Bump version to 0.9.6 in package.json, preload.js, openclaw-manager.js Co-Authored-By: Claude Sonnet 4.6 --- assets/icon.icns | Bin 0 -> 29318 bytes assets/icon.png | Bin 0 -> 1880 bytes assets/tray-icon.png | Bin 0 -> 79 bytes main.js | 27 ++++++++++++++++++++++++--- package.json | 2 +- preload.js | 2 +- server/openclaw-manager.js | 2 +- 7 files changed, 27 insertions(+), 6 deletions(-) create mode 100644 assets/icon.icns create mode 100644 assets/icon.png create mode 100644 assets/tray-icon.png diff --git a/assets/icon.icns b/assets/icon.icns new file mode 100644 index 0000000000000000000000000000000000000000..d8cd509ec524a8e018031b1061eec8ac77c21671 GIT binary patch literal 29318 zcmeHQe@qis9RJ>3TS@^bAW$pHxs`>X%%UP{;<&OhspE$TQ>I1>rAh}so~K$ndTB75&zDG4+255`~LHrKn? zd-r{JukXI^^ZmTf>)9-&4uJAnnDsx4UN~;2ZAXA!gHCYREQL^MSCg4sT zSuu{)D^lR(g{VG~Fk16Wn=>*Xj%+J|*<%A4%|aF}SpYZ}0~}d1^g9`{0-G%MI!MVb@x=C13s3k#%#E?P zZ_V;JQSnboZ2h3BH6^MURE6zqi`p+vWM_O1b31BOE}?6#TlI#E{eQA_MGnFCZZuyxs@2T8mz;>Rl0GxrWg@IndSwO)j_ z8jYP{I}`=&a@;XhRU$<7GBNM4jZ3yGqik1Md<(}3AAR8EKP$9qvK5kHk6=$X$EWWe6YKh{6Voi8d5_e045yK4;x*xt1 zDMqKwR14dy2iO75#<6J^gEvAozg2*~zkdjD2OkSk^2?Jen4y|e40G(R-+V}}U(Abt zjP%NT{kj#h`XkZpFe0EatTSvHcsot4*N6_g&Ncpc_?tHB1AX3DzXZK8x_0cru%kwB zGldxLN#1x7an4Z&5|)mR4v$Jp@o@2I;&38~YstQlBNK5m4QN>pZm!b4^chJ_25x4@ z;bvL_K)}%H-Q*0wi<^Iv0x{0u4a6*Wqnz7KcL{K2WlHt${w*5|>-^Qc&>NtE9fAlo z%_6fmV*X-=l?95?ydVm>ZZPhP{16yc;SMG_`8YE)b?(a$f#G`nlxkibu7}IFJD(Fo zks08K)x9c>STtA=#tUv3B8HSkd7yBrqK%Yeh7n>&*2F6Kb?w(kUOiM3Lu@v~spB`6 zkh~g5#?!#sz_x*R3i=K7qS&Wk4~uvM(HCM-MCKSEV7P?ABZksXMJ!aDe^1`{)%4_L zloJ`pqc25v2H6?ps*t%u9urwzz1NULDR=1J$oT*5Me=ZJkxvlSKvWREI-!HdGd)Wj_tcSvl^D zvm(5yx{?gdIr5gh8X>?@h zy`_E!yDZv+Vn2=GM8a%{$Pk87h>h5r#ejnbQy67oXh|b*jHi(~k+>El5s*Yc5&_vz zFKdewF!72=A|Q!CK@yS(NFqoe2}uMb5hRd=Bm$BMbfg7I1SAn8Z2~G0P>Dc65|Ri= zA|Q!?B!W-Rh9m-#2uLDGK9P0}s6;>#0Z9ZT5oq)*!30zyAc=q^0+I+`cYxCwkVNoy z4LF?vr!(Mm1_>k~iGU;mk_bp5jDaL15uSoXn4R6_-#DnNCjaX<{(t@w=!3~_Pn`V? zJo%oNo?bShx&JXqOvdbQ;C)XolS+V=+Jc9~xRK8OP79(>7X-bMGnkL3cRost4SPHF zuPg5#$h^=O*|4_Zx9@NI#m+lmj1`%+x)7Dw9d6piYRXbWkAh-DNND`xbIdL6?&C4U zp6{OwOE=rexxZLYR$_BF_4+Fe%gN*lKUJRYEo-^MW-onBmtSrvvXNA-&S@{p)7cAN zw_2QzP+)3Zo7BOXIj>kNt%U|}rprqI+;Y3!DKf_c0wXmuw6kB;mA+Y0(i1c-SREFz zHZ$jiVr!*i9a(z~tdbmr|QEqas``QPCaE&v|B@#}Yj-&$DTDY{<+p+AL0TA^GK%O>>^j z%go7=E*t-MGpCiKotz0u6{1-oD!M { - isQuitting = true; + // Close → minimize to tray (hide window, keep server running) + mainWindow.on('close', (event) => { + if (!isQuitting) { + event.preventDefault(); + mainWindow.hide(); + if (process.platform === 'darwin' && app.dock) { + app.dock.hide(); + } + } }); mainWindow.on('closed', () => { @@ -148,6 +154,7 @@ function createTray() { if (mainWindow) { mainWindow.show(); mainWindow.focus(); + if (process.platform === 'darwin' && app.dock) app.dock.show(); } else { createWindow(); } @@ -174,11 +181,23 @@ function createTray() { tray.setContextMenu(contextMenu); + // Left-click tray → show window (Windows/Linux; macOS shows context menu by default) + tray.on('click', () => { + if (mainWindow) { + mainWindow.show(); + mainWindow.focus(); + if (process.platform === 'darwin' && app.dock) app.dock.show(); + } else { + createWindow(); + } + }); + // Double-click tray → show window (Windows/Linux) tray.on('double-click', () => { if (mainWindow) { mainWindow.show(); mainWindow.focus(); + if (process.platform === 'darwin' && app.dock) app.dock.show(); } }); } @@ -215,6 +234,8 @@ app.on('activate', () => { // macOS dock click → show window if (mainWindow) { mainWindow.show(); + mainWindow.focus(); + if (process.platform === 'darwin' && app.dock) app.dock.show(); } else { createWindow(); } diff --git a/package.json b/package.json index 64a6201..758be54 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "odo", - "version": "0.9.5", + "version": "0.9.6", "description": "ODO — OpenClaw Dashboard Orchestrator", "main": "main.js", "scripts": { diff --git a/preload.js b/preload.js index 8d2aff3..99eccfd 100644 --- a/preload.js +++ b/preload.js @@ -7,6 +7,6 @@ const { contextBridge } = require('electron'); contextBridge.exposeInMainWorld('odo', { platform: process.platform, - version: '0.9.4', + version: '0.9.6', isElectron: true }); diff --git a/server/openclaw-manager.js b/server/openclaw-manager.js index f36f91c..29fb761 100644 --- a/server/openclaw-manager.js +++ b/server/openclaw-manager.js @@ -24,7 +24,7 @@ const SCRIPT_DIR = __dirname; const MANAGER_CONFIG = path.join(SCRIPT_DIR, 'manager-config.json'); let PORT = 3333; let HOST = '0.0.0.0'; -const APP_VERSION = '0.9.4'; +const APP_VERSION = '0.9.6'; // --port 参数 const portIdx = process.argv.indexOf('--port'); if (portIdx !== -1 && process.argv[portIdx + 1]) PORT = parseInt(process.argv[portIdx + 1]) || 3333;