1
0
mirror of https://github.com/lensapp/lens.git synced 2025-05-20 05:10:56 +00:00

moved generating tray icons to build step

Signed-off-by: Roman <ixrock@gmail.com>
This commit is contained in:
Roman 2020-10-14 17:29:15 +03:00
parent 1b38e6cda6
commit 3c668c47bf
11 changed files with 74 additions and 53 deletions

51
build/build_tray_icon.ts Normal file
View File

@ -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 += `<style>* {fill: ${trayIconColor} !important;}</style>`
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<string, number> = {
"1x": 16,
"2x": 32,
"3x": 48,
};
Object.entries(iconSizes).forEach(([dpiSuffix, pixelSize]) => {
generateTrayIcon({ dpiSuffix, pixelSize, shouldUseDarkColors: false });
generateTrayIcon({ dpiSuffix, pixelSize, shouldUseDarkColors: true });
});

BIN
build/icons/tray_icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 448 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 973 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -32,6 +32,7 @@
"download-bins": "concurrently yarn:download:*", "download-bins": "concurrently yarn:download:*",
"download:kubectl": "yarn run ts-node build/download_kubectl.ts", "download:kubectl": "yarn run ts-node build/download_kubectl.ts",
"download:helm": "yarn run ts-node build/download_helm.ts", "download:helm": "yarn run ts-node build/download_helm.ts",
"build:tray-icons": "yarn run ts-node build/build_tray_icon.ts",
"lint": "eslint $@ --ext js,ts,tsx --max-warnings=0 src/", "lint": "eslint $@ --ext js,ts,tsx --max-warnings=0 src/",
"rebuild-pty": "yarn run electron-rebuild -f -w node-pty" "rebuild-pty": "yarn run electron-rebuild -f -w node-pty"
}, },
@ -89,8 +90,8 @@
"filter": "!**/main.js" "filter": "!**/main.js"
}, },
{ {
"from": "src/renderer/components/icon/logo-lens.svg", "from": "build/icons/",
"to": "static/logo.svg" "to": "build/icons/"
}, },
"LICENSE" "LICENSE"
], ],
@ -177,7 +178,6 @@
"@types/node": "^12.12.45", "@types/node": "^12.12.45",
"@types/proper-lockfile": "^4.1.1", "@types/proper-lockfile": "^4.1.1",
"@types/react-beautiful-dnd": "^13.0.0", "@types/react-beautiful-dnd": "^13.0.0",
"@types/sharp": "^0.26.0",
"@types/tar": "^4.0.3", "@types/tar": "^4.0.3",
"array-move": "^3.0.0", "array-move": "^3.0.0",
"chalk": "^4.1.0", "chalk": "^4.1.0",
@ -207,14 +207,13 @@
"openid-client": "^3.15.2", "openid-client": "^3.15.2",
"path-to-regexp": "^6.1.0", "path-to-regexp": "^6.1.0",
"proper-lockfile": "^4.1.1", "proper-lockfile": "^4.1.1",
"react-beautiful-dnd": "^13.0.0",
"react": "^16.13.1", "react": "^16.13.1",
"react-beautiful-dnd": "^13.0.0",
"react-router": "^5.2.0", "react-router": "^5.2.0",
"request": "^2.88.2", "request": "^2.88.2",
"request-promise-native": "^1.0.8", "request-promise-native": "^1.0.8",
"semver": "^7.3.2", "semver": "^7.3.2",
"serializr": "^2.0.3", "serializr": "^2.0.3",
"sharp": "^0.26.1",
"shell-env": "^3.0.0", "shell-env": "^3.0.0",
"spdy": "^4.0.2", "spdy": "^4.0.2",
"tar": "^6.0.2", "tar": "^6.0.2",
@ -260,6 +259,7 @@
"@types/request": "^2.48.5", "@types/request": "^2.48.5",
"@types/request-promise-native": "^1.0.17", "@types/request-promise-native": "^1.0.17",
"@types/semver": "^7.2.0", "@types/semver": "^7.2.0",
"@types/sharp": "^0.26.0",
"@types/shelljs": "^0.8.8", "@types/shelljs": "^0.8.8",
"@types/spdy": "^3.4.4", "@types/spdy": "^3.4.4",
"@types/tcp-port-used": "^1.0.0", "@types/tcp-port-used": "^1.0.0",
@ -317,6 +317,7 @@
"react-select": "^3.1.0", "react-select": "^3.1.0",
"react-window": "^1.8.5", "react-window": "^1.8.5",
"sass-loader": "^8.0.2", "sass-loader": "^8.0.2",
"sharp": "^0.26.1",
"spectron": "11.0.0", "spectron": "11.0.0",
"style-loader": "^1.2.1", "style-loader": "^1.2.1",
"terser-webpack-plugin": "^3.0.3", "terser-webpack-plugin": "^3.0.3",

View File

@ -1,9 +1,6 @@
import path from "path" import path from "path"
import sharp from "sharp";
import jsdom from "jsdom"
import packageInfo from "../../package.json" import packageInfo from "../../package.json"
import { app, dialog, Menu, NativeImage, nativeImage, nativeTheme, Tray } from "electron" import { app, dialog, Menu, NativeImage, nativeTheme, Tray } from "electron"
import { isDevelopment, isMac } from "../common/vars";
import { autorun } from "mobx"; import { autorun } from "mobx";
import { showAbout } from "./menu"; import { showAbout } from "./menu";
import { AppUpdater } from "./app-updater"; import { AppUpdater } from "./app-updater";
@ -16,26 +13,22 @@ import logger from "./logger";
// note: instance of Tray should be saved somewhere, otherwise it disappears // note: instance of Tray should be saved somewhere, otherwise it disappears
export let tray: Tray; export let tray: Tray;
export let trayIcon: NativeImage;
export const trayIconPath = isDevelopment // refresh icon when MacOS dark/light theme has changed
? path.resolve(__static, "../src/renderer/components/icon/logo-lens.svg") nativeTheme.on("updated", () => tray?.setImage(getTrayIcon()));
: path.resolve(__static, "logo.svg") // electron-builder's extraResources
// update icon when MacOS dark/light theme has changed export function getTrayIcon(isDark = nativeTheme.shouldUseDarkColors): string {
nativeTheme.on("updated", async () => { return path.resolve(__static, "../build/icons", `tray_icon${isDark ? "_dark" : ""}.png`)
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 initTray(windowManager: WindowManager) {
const dispose = autorun(() => { const dispose = autorun(() => {
const menu = createTrayMenu(windowManager); try {
buildTray(trayIcon, menu); const menu = createTrayMenu(windowManager);
buildTray(getTrayIcon(), menu);
} catch (err) {
logger.error(`[TRAY]: building failed: ${err}`);
}
}) })
return () => { return () => {
dispose(); dispose();
@ -44,24 +37,7 @@ export async function initTray(windowManager: WindowManager) {
} }
} }
export async function createTrayIconFromSvg(filePath = trayIconPath): Promise<NativeImage> { export function buildTray(icon: string | NativeImage, menu: Menu) {
// 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 += `<style>* {fill: ${trayIconColor} !important;}</style>`
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) {
logger.info("[TRAY]: build start"); logger.info("[TRAY]: build start");
if (!tray) { if (!tray) {

View File

@ -81,10 +81,10 @@ export class WindowManager {
this.disposers.menuAutoUpdater = initMenu(this); this.disposers.menuAutoUpdater = initMenu(this);
} }
protected async initTray() { protected initTray() {
this.disposers.trayAutoBind = reaction(() => userStore.preferences.trayEnabled, async isEnabled => { this.disposers.trayAutoBind = reaction(() => userStore.preferences.trayEnabled, isEnabled => {
if (isEnabled) { if (isEnabled) {
this.disposers.trayAutoUpdater = await initTray(this); this.disposers.trayAutoUpdater = initTray(this);
} else if (this.disposers.trayAutoUpdater) { } else if (this.disposers.trayAutoUpdater) {
this.disposers.trayAutoUpdater(); this.disposers.trayAutoUpdater();
} }

View File

@ -1,7 +0,0 @@
<svg id="Layer_1" viewBox="0 0 194 219" xmlns="http://www.w3.org/2000/svg">
<g fill="#fff">
<polygon points="98 12.4 71 28.3 44 44.1 17 60 17 91.8 17 123.6 17 155.4 44 171.3 44 139.5 44 107.7 44 75.9 71 60 71 91.8 71 91.8 71 123.6 98 107.7 98 107.7 125 91.8 125 60 152 44.1 125 28.3 98 12.4"/>
<polygon points="152 44.1 152 75.9 152 107.7 125 123.6 152 139.5 152 171.3 179 155.4 179 123.6 179 91.8 179 60 152 44.1"/>
<polygon points="98 139.5 71 155.4 71 155.4 71 187.2 98 203.1 125 187.2 125 155.4 98 139.5"/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 538 B