From 3c668c47bf15aec979d1ba71196f96e16d43a73a Mon Sep 17 00:00:00 2001 From: Roman Date: Wed, 14 Oct 2020 17:29:15 +0300 Subject: [PATCH] moved generating tray icons to build step Signed-off-by: Roman --- build/build_tray_icon.ts | 51 +++++++++++++++++ build/icons/tray_icon.png | Bin 0 -> 448 bytes build/icons/tray_icon@2x.png | Bin 0 -> 973 bytes build/icons/tray_icon@3x.png | Bin 0 -> 1479 bytes build/icons/tray_icon_dark.png | Bin 0 -> 478 bytes build/icons/tray_icon_dark@2x.png | Bin 0 -> 1145 bytes build/icons/tray_icon_dark@3x.png | Bin 0 -> 1775 bytes package.json | 11 ++-- src/main/tray.ts | 52 +++++------------- src/main/window-manager.ts | 6 +- src/renderer/components/icon/logo-kontena.svg | 7 --- 11 files changed, 74 insertions(+), 53 deletions(-) create mode 100644 build/build_tray_icon.ts create mode 100644 build/icons/tray_icon.png create mode 100644 build/icons/tray_icon@2x.png create mode 100644 build/icons/tray_icon@3x.png create mode 100644 build/icons/tray_icon_dark.png create mode 100644 build/icons/tray_icon_dark@2x.png create mode 100644 build/icons/tray_icon_dark@3x.png delete mode 100644 src/renderer/components/icon/logo-kontena.svg diff --git a/build/build_tray_icon.ts b/build/build_tray_icon.ts new file mode 100644 index 0000000000..2324f43295 --- /dev/null +++ b/build/build_tray_icon.ts @@ -0,0 +1,51 @@ +// Generate tray icons from SVG to PNG + different sizes and colors (B&W) +// Command: `yarn build:tray-icons` +import path from "path" +import sharp from "sharp"; +import jsdom from "jsdom" +import fs from "fs-extra" + +export async function generateTrayIcon( + { + outputFilename = "tray_icon", // e.g. output tray_icon_dark@2x.png + svgIconPath = path.resolve(__dirname, "../src/renderer/components/icon/logo-lens.svg"), + outputFolder = path.resolve(__dirname, "./icons"), + dpiSuffix = "2x", + pixelSize = 32, + shouldUseDarkColors = false, // managed by electron.nativeTheme.shouldUseDarkColors + } = {}) { + outputFilename += shouldUseDarkColors ? "_dark" : "" + dpiSuffix = dpiSuffix !== "1x" ? `@${dpiSuffix}` : "" + const pngIconDestPath = path.resolve(outputFolder, `${outputFilename}${dpiSuffix}.png`) + try { + // Modify .SVG colors + const trayIconColor = shouldUseDarkColors ? "white" : "black"; + const svgDom = await jsdom.JSDOM.fromFile(svgIconPath); + const svgRoot = svgDom.window.document.body.getElementsByTagName("svg")[0]; + svgRoot.innerHTML += `` + const svgIconBuffer = Buffer.from(svgRoot.outerHTML); + + // Resize and convert to .PNG + const pngIconBuffer: Buffer = await sharp(svgIconBuffer) + .resize({ width: pixelSize, height: pixelSize }) + .png() + .toBuffer(); + + // Save icon + await fs.writeFile(pngIconDestPath, pngIconBuffer); + console.info(`[DONE]: Tray icon saved at "${pngIconDestPath}"`); + } catch (err) { + console.error(`[ERROR]: ${err}`); + } +} + +// Run +const iconSizes: Record = { + "1x": 16, + "2x": 32, + "3x": 48, +}; +Object.entries(iconSizes).forEach(([dpiSuffix, pixelSize]) => { + generateTrayIcon({ dpiSuffix, pixelSize, shouldUseDarkColors: false }); + generateTrayIcon({ dpiSuffix, pixelSize, shouldUseDarkColors: true }); +}); diff --git a/build/icons/tray_icon.png b/build/icons/tray_icon.png new file mode 100644 index 0000000000000000000000000000000000000000..73c7346d33abfc2e53b2f9a1e3043ba09ba3a5f0 GIT binary patch literal 448 zcmV;x0YCnUP)@aCkc-s@pssQA;?2Y_@g&J;0K0VngPfZs zj0q2k3tX6lGB4TvUo+2Z^|I_8mZOka-L=SB-5b-%r2}?h12$nB8cdSgz)2?cn^RgG zpbJjn01inv^B6Aqs@hD2DIThT-%hct;2)pR4RLys|}_Dw4Q0000p2Uj) literal 0 HcmV?d00001 diff --git a/build/icons/tray_icon@2x.png b/build/icons/tray_icon@2x.png new file mode 100644 index 0000000000000000000000000000000000000000..71206802ac07cfb5dac96338fc0b29dc5a78cb38 GIT binary patch literal 973 zcmV;;12X)HP)`iRvwty-*#-PA`bWTAp!r67pVg#_JL z!JRwNO=|^T2x1j1E`+*Kx)JJ=ZUhk#5kW*j(M?fTA`}F5kv6T3+B|MN6aNXnC-){d z$-vj<&YhX_pEGA3*Kz)p79moGR-sO45ZVH?XPSj&!fIiiQ14JN#=ixJD%nGhz z5$~=d0>6CPn&*^|A;YhPe)9M>+M0JiVLSh44wbG_?$Ut9gFa>4wn?kL&xKtuyhV7R z#>~O#k^)@y+$o&I?-Utk!H6J3b3C1QHCdl%`m)M zc;R8#RZbQJv?0rLYEEsNvfNI`YvnN;(nUvPm2gRzCm|^gDU+{L^7 zH3+Z~yGO~#Temq4mudl7YIGU{G*l_T_8X>U$cNhk=fIrLb{VTdgiXXgp98MsX_%qJ zSzpB}u;Di$ZWq3J9OIs+Vbd;f!qoNPfC&=%0kx#ZkP8dy zv@HlQ9vu^o3xn7`HMah&!bIg9MW=@haSoaCQcY_?Kx-A(Y|TX&`QVXki?A`OBJ*Dk z#OVs23Wz-|Ct&=J@|@>;kFZxQao<%?4i4id7#~!g>!o}_SgF1l%I*VxWaw^a?t(ki zHw3q}LZ3nC6bVRFx(qcj%xxk-+a#`jH&k6D$j2!&3ol3D(c>~7stI7eBen_$(S9B_ vTbv3$&-pXmZaVF_U`A3jP)UIq2$??$ zrf_C3doY0&JrMj+f)P4n1zJXpM5IHcg3}Kp3yrAgfmx9~h%CdPq?+;GIcHj%zExjq z_IciO-0*SlIcM*+*V=2Xz1Lbh2>xj`LA#({0PVqltzH3Ypna_1c$(+m<~mFh+#~1` zbPIYi!1Y@!xCL}h5-h^|tTfW-F9do8O9WR6+5*$s!TeZ341&%bEzn5A*MfUV1Matj z)!v1UBZ6i|j9|=S(0Qf+4Ij-0F}__ej~4p~XlB1)4GYkX0ggzN18&S^p!04)8WD|A z#CdN;I34KR>`dEM-GkKCa-S-gxe-a!im?Zd(zDEgTBl_Po-?s>^C&niWmSP_5 zGmPKWMFkk6iMN8rwT8hcC*#hKW)b733zoxFc+QZd)B7*~3YG6Yb9b3tRH(M%HK&IFzpTtJL>z$yPqU|i|7Bmfg~jGPJ@dx+UM z#t#VkvC7&m5e#@V6DIhRSAgyu8W_dzM;L#unb0!6ANG72F@BX`gPE&o{3MQ#aRRh^ zG!SL5|CcbnlL#~8dj*eUCkb$Z&Jk?#YzSExj}@Se4zflHp@=lF2;*0pKHp={o@h?| z^98%9-$=}vF_u>VJ(@pDa75o0IRj%q!SimM%Ey@Cu13#pv2GK5XiRc6hZe>Opc70L z{9)|e5(;URj}n|L*a06pJc04R^L(q|y#j*73J@Ufu)B%x0NR576EZMvTirant@s_Y zNJ)M%P5>8Y-yk>}&&y&=i3M0{gs%trn;mnL;H?aTcz2-(1@9BF*JGSoO>1@wjHe0W z7IVn6^F>J}bQfN(z`NsU$7mY+cR|~kF?QWba|?MQJzo>E<$5*HO`SUN{z5w1Lt6b0 zg7TX##0!FTf-}saH|Pl@`+cE=+L*@p3p`=Lni9>&no%$2aKYSjf^(>k3;JH6MCw_e z0Qzwca@+tBC&%HP6$qet?iI#lH1O*%f!}5__x}knN;bBY25rW>gMy39q-C0rJH3CP zx!7z5Xm0h>*l1LRSWYROBm4_8uqv7^$Pg{2O@5pyzlta}ND_c!{@W?*T3^BLWBuSU zZ0tA13%1w5QRi z;l^tvI_=BE-~tNle171KM(-|I_I|PjEvOIOZ{jcw(&DVbs{xm2|0wue@MQ*kf!}X% z>7Wd?rNAF~ zZJxAMSNz79nro~HEu<}SqyUB!prx8mDaUv^Cg-+Q?}t5pkhqP872R<;6S>^nrTI!X zD!>r>&hk`761UL?5pETnhTe&}X3%aECY<*BP;;7q|15CJ_XBBn2UgYn36+kd(&bEy zd((`mOaLGA+sSDMJ$9c|{eH;gnAtXgvU0YdzoAaYQ&11*ATxCNKICgsq_5`8r%ftt>##t?rAsL(uZ#TJX0D h%+Eg*xozdN{s!je5-4cpd;S0b002ovPDHLkV1f{0ueSgI literal 0 HcmV?d00001 diff --git a/build/icons/tray_icon_dark.png b/build/icons/tray_icon_dark.png new file mode 100644 index 0000000000000000000000000000000000000000..568d13e00bf9d5f86d7c5f9445783fc37f383676 GIT binary patch literal 478 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 tray?.setImage(getTrayIcon())); -// update icon when MacOS dark/light theme has changed -nativeTheme.on("updated", async () => { - if (tray) { - trayIcon = await createTrayIconFromSvg(); - tray.setImage(trayIcon); - } -}); - -export async function initTray(windowManager: WindowManager) { - trayIcon = await createTrayIconFromSvg(); // generate icon once on tray activation +export function getTrayIcon(isDark = nativeTheme.shouldUseDarkColors): string { + return path.resolve(__static, "../build/icons", `tray_icon${isDark ? "_dark" : ""}.png`) +} +export function initTray(windowManager: WindowManager) { const dispose = autorun(() => { - const menu = createTrayMenu(windowManager); - buildTray(trayIcon, menu); + try { + const menu = createTrayMenu(windowManager); + buildTray(getTrayIcon(), menu); + } catch (err) { + logger.error(`[TRAY]: building failed: ${err}`); + } }) return () => { dispose(); @@ -44,24 +37,7 @@ export async function initTray(windowManager: WindowManager) { } } -export async function createTrayIconFromSvg(filePath = trayIconPath): Promise { - // modify icon's svg - const svgDom = await jsdom.JSDOM.fromFile(filePath); - const svgRoot = svgDom.window.document.body.getElementsByTagName("svg")[0]; - const trayIconColor = nativeTheme.shouldUseDarkColors ? "white" : "black"; - svgRoot.innerHTML += `` - const svgIconBuffer = Buffer.from(svgRoot.outerHTML); - - // convert to .png or .ico and resize - const pngIcon = await sharp(svgIconBuffer).png().toBuffer(); - const iconSize = isMac ? 16 : 32; // todo: verify on windows/linux - return nativeImage.createFromBuffer(pngIcon).resize({ - width: iconSize, - height: iconSize - }); -} - -export async function buildTray(icon: NativeImage, menu: Menu) { +export function buildTray(icon: string | NativeImage, menu: Menu) { logger.info("[TRAY]: build start"); if (!tray) { diff --git a/src/main/window-manager.ts b/src/main/window-manager.ts index e768058fb3..fcee752b05 100644 --- a/src/main/window-manager.ts +++ b/src/main/window-manager.ts @@ -81,10 +81,10 @@ export class WindowManager { this.disposers.menuAutoUpdater = initMenu(this); } - protected async initTray() { - this.disposers.trayAutoBind = reaction(() => userStore.preferences.trayEnabled, async isEnabled => { + protected initTray() { + this.disposers.trayAutoBind = reaction(() => userStore.preferences.trayEnabled, isEnabled => { if (isEnabled) { - this.disposers.trayAutoUpdater = await initTray(this); + this.disposers.trayAutoUpdater = initTray(this); } else if (this.disposers.trayAutoUpdater) { this.disposers.trayAutoUpdater(); } diff --git a/src/renderer/components/icon/logo-kontena.svg b/src/renderer/components/icon/logo-kontena.svg deleted file mode 100644 index 6b05f1ba17..0000000000 --- a/src/renderer/components/icon/logo-kontena.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file