Fix icon generation
Signed-off-by: Sebastian Malton <sebastian@malton.name>
1
Makefile
@ -56,6 +56,7 @@ integration: build
|
|||||||
build: node_modules binaries/client
|
build: node_modules binaries/client
|
||||||
yarn run npm:fix-build-version
|
yarn run npm:fix-build-version
|
||||||
$(MAKE) build-extensions -B
|
$(MAKE) build-extensions -B
|
||||||
|
yarn run build:tray-icons
|
||||||
yarn run compile
|
yarn run compile
|
||||||
ifeq "$(DETECTED_OS)" "Windows"
|
ifeq "$(DETECTED_OS)" "Windows"
|
||||||
# https://github.com/ukoloff/win-ca#clear-pem-folder-on-publish
|
# https://github.com/ukoloff/win-ca#clear-pem-folder-on-publish
|
||||||
|
|||||||
@ -31,113 +31,70 @@ function getSvgStyling(colouring: "dark" | "light"): string {
|
|||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getBaseIconTemplates() {
|
async function getBaseIconImage() {
|
||||||
const svgData = await readFile(inputFile, { encoding: "utf-8" });
|
const svgData = await readFile(inputFile, { encoding: "utf-8" });
|
||||||
const dom = new JSDOM(`<body>${svgData}</body>`);
|
const dom = new JSDOM(`<body>${svgData}</body>`);
|
||||||
const root = dom.window.document.body.getElementsByTagName("svg")[0];
|
const root = dom.window.document.body.getElementsByTagName("svg")[0];
|
||||||
|
|
||||||
root.innerHTML += getSvgStyling("light");
|
root.innerHTML += getSvgStyling("light");
|
||||||
|
|
||||||
return root.outerHTML;
|
return Buffer.from(root.outerHTML);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateNormalImages(template: string, size: number, name: string) {
|
async function generateImage(image: Buffer, size: number, namePrefix: string) {
|
||||||
|
sharp(image)
|
||||||
|
.resize({ width: size, height: size })
|
||||||
|
.toFile(path.join(outputFolder, `${namePrefix}.png`));
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateImages(image: Buffer, size: number, name: string) {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
sharp(Buffer.from(template))
|
generateImage(image, size, name),
|
||||||
.resize({ width: size, height: size })
|
generateImage(image, size*2, `${name}@2x`),
|
||||||
.png()
|
generateImage(image, size*3, `${name}@3x`),
|
||||||
.toFile(path.join(outputFolder, `${name}.png`)),
|
generateImage(image, size*4, `${name}@4x`),
|
||||||
sharp(Buffer.from(template))
|
|
||||||
.resize({ width: size*2, height: size*2 })
|
|
||||||
.png()
|
|
||||||
.toFile(path.join(outputFolder, `${name}@2x.png`)),
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateUpdateAvailableImages(template: string, size: number, name: string, noticeSvg: string) {
|
async function generateUpdateAvailableImages(baseImage: Buffer) {
|
||||||
const circleSvg = new JSDOM(`
|
const noticeIconImage = await getNoticeIconImage();
|
||||||
<body>
|
const circleBuffer = await sharp(Buffer.from(`
|
||||||
<svg viewBox="0 0 32 32">
|
<svg viewBox="0 0 64 64">
|
||||||
<circle cx="20" cy="20" r="6" />
|
<circle cx="32" cy="32" r="32" fill="black" />
|
||||||
</svg>
|
</svg>
|
||||||
<style>
|
`))
|
||||||
circle {
|
|
||||||
fill: "black" !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</body>
|
|
||||||
`).window.document.getElementsByTagName("svg")[0];
|
|
||||||
|
|
||||||
circleSvg.innerHTML += getSvgStyling("dark");
|
|
||||||
|
|
||||||
const circleBuffer = await sharp(Buffer.from(circleSvg.outerHTML))
|
|
||||||
.resize({
|
|
||||||
width: Math.floor(size/1.5),
|
|
||||||
height: Math.floor(size/1.5),
|
|
||||||
})
|
|
||||||
.toBuffer();
|
.toBuffer();
|
||||||
|
|
||||||
await sharp(circleBuffer)
|
return sharp(baseImage)
|
||||||
.toFile(path.join(outputFolder, "circle.png"));
|
.resize({ width: 128, height: 128 })
|
||||||
|
.composite([
|
||||||
await Promise.all([
|
{
|
||||||
sharp(Buffer.from(template))
|
input: circleBuffer,
|
||||||
.resize({ width: size, height: size })
|
top: 64,
|
||||||
.composite([
|
left: 64,
|
||||||
{
|
blend: "dest-out",
|
||||||
input: circleBuffer,
|
},
|
||||||
gravity: "southeast",
|
{
|
||||||
/**
|
input: (
|
||||||
* The `clear` blend rule is buggy and currently doesn't work
|
await sharp(noticeIconImage)
|
||||||
*
|
.resize({
|
||||||
* https://github.com/lovell/sharp/issues/3247
|
width: 60,
|
||||||
*/
|
height: 60,
|
||||||
blend: "clear",
|
})
|
||||||
},
|
.toBuffer()
|
||||||
{
|
),
|
||||||
input: (
|
top: 66,
|
||||||
await sharp(Buffer.from(noticeSvg))
|
left: 66,
|
||||||
.resize({
|
},
|
||||||
width: Math.floor(size/1.5),
|
])
|
||||||
height: Math.floor(size/1.5),
|
.toBuffer();
|
||||||
})
|
|
||||||
.toBuffer()
|
|
||||||
),
|
|
||||||
gravity: "southeast",
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.png()
|
|
||||||
.toFile(path.join(outputFolder, `${name}.png`)),
|
|
||||||
sharp(Buffer.from(template))
|
|
||||||
.composite([
|
|
||||||
{
|
|
||||||
input: circleBuffer,
|
|
||||||
gravity: "southeast",
|
|
||||||
blend: "clear",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
input: (
|
|
||||||
await sharp(Buffer.from(noticeSvg))
|
|
||||||
.resize({
|
|
||||||
width: Math.floor((size * 2)/1.5),
|
|
||||||
height: Math.floor((size * 2)/1.5),
|
|
||||||
})
|
|
||||||
.toBuffer()
|
|
||||||
),
|
|
||||||
gravity: "southeast",
|
|
||||||
},
|
|
||||||
])
|
|
||||||
.resize({ width: size*2, height: size*2 })
|
|
||||||
.png()
|
|
||||||
.toFile(path.join(outputFolder, `${name}@2x.png`)),
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getNoticeSvg(): Promise<string> {
|
async function getNoticeIconImage() {
|
||||||
const svgData = await readFile(noticeFile, { encoding: "utf-8" });
|
const svgData = await readFile(noticeFile, { encoding: "utf-8" });
|
||||||
const noticeSvgRoot = new JSDOM(svgData).window.document.getElementsByTagName("svg")[0];
|
const noticeSvgRoot = new JSDOM(svgData).window.document.getElementsByTagName("svg")[0];
|
||||||
|
|
||||||
return noticeSvgRoot.outerHTML;
|
return Buffer.from(noticeSvgRoot.outerHTML);
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateTrayIcons() {
|
async function generateTrayIcons() {
|
||||||
@ -145,21 +102,14 @@ async function generateTrayIcons() {
|
|||||||
console.log("Generating tray icon pngs");
|
console.log("Generating tray icon pngs");
|
||||||
await ensureOutputFoler();
|
await ensureOutputFoler();
|
||||||
|
|
||||||
const baseTemplate = await getBaseIconTemplates();
|
const baseIconImage = await getBaseIconImage();
|
||||||
const noticeTemplate = await getNoticeSvg();
|
const updateAvailableImage = await generateUpdateAvailableImages(baseIconImage);
|
||||||
|
|
||||||
void noticeTemplate;
|
|
||||||
void generateUpdateAvailableImages;
|
|
||||||
|
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
generateNormalImages(baseTemplate, size, "trayIconTemplate"),
|
generateImages(baseIconImage, size, "trayIconTemplate"),
|
||||||
// generateUpdateAvailableImages(baseTemplate, size, "trayIconDarkUpdateAvailableTemplate", noticeTemplate),
|
generateImages(updateAvailableImage, size, "trayIconUpdateAvailableTemplate"),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
console.warn("Did not update:", [
|
|
||||||
"trayIconUpdateAvailableTemplate.png",
|
|
||||||
"trayIconUpdateAvailableTemplate@2x.png",
|
|
||||||
]);
|
|
||||||
console.log("Generated all images");
|
console.log("Generated all images");
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error(error);
|
console.error(error);
|
||||||
|
|||||||
BIN
build/tray/trayIconTemplate@3x.png
Normal file
|
After Width: | Height: | Size: 1.0 KiB |
BIN
build/tray/trayIconTemplate@4x.png
Normal file
|
After Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 5.4 KiB After Width: | Height: | Size: 466 B |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 1.0 KiB |
BIN
build/tray/trayIconUpdateAvailableTemplate@3x.png
Normal file
|
After Width: | Height: | Size: 1.6 KiB |
BIN
build/tray/trayIconUpdateAvailableTemplate@4x.png
Normal file
|
After Width: | Height: | Size: 2.4 KiB |