Rework icon with higher quality and new color

Change icon color to match the primary color of the theme (i.e.,
`#3a65ab`). The new color looks good on both dark and light surfaces
which solves #155.

Introduce SVG logo instead of PNG for better quality and scalability.

Improve icon creation. Introduce an automated script to create different
logo formats in different sizes enabling easier update of logo from
single place.
This commit is contained in:
undergroundwires
2022-10-13 21:26:30 +02:00
parent 64cca1d9b8
commit f4a7ca76b8
21 changed files with 3475 additions and 3 deletions

View File

@@ -53,3 +53,23 @@ jobs:
run: |-
cross-env-shell NODE_ENV=${{ matrix.mode }}
npm run electron:build -- --publish never --mode ${{ matrix.mode }}
create-icons:
strategy:
matrix:
os: [ macos, ubuntu, windows ]
fail-fast: false # Allows to see results from other combinations
runs-on: ${{ matrix.os }}-latest
steps:
-
name: Checkout
uses: actions/checkout@v2
-
name: Setup node
uses: ./.github/actions/setup-node
-
name: Install dependencies
run: npm ci
-
name: Create icons
run: npm run create-icons

View File

@@ -1,5 +1,5 @@
# build
- These are the file that are used by electron.
- Logos are created by from the [PNG icon](./../public/icon.png)
- by running `npx electron-icon-builder --input=./public/icon.png --output=build --flatten`
This folder contains files that are used by Electron to serve the desktop version.
Icons are created from the main logo file and should not be changed manually, see [related documentation](./../img/README.md).

Binary file not shown.

Before

Width:  |  Height:  |  Size: 225 KiB

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 740 B

After

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 963 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 76 KiB

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 KiB

After

Width:  |  Height:  |  Size: 353 KiB

View File

@@ -45,6 +45,7 @@ You could run other types of tests as well, but they may take longer time and ov
- Build web application: `npm run build`
- Build desktop application: `npm run electron:build`
- (Re)create icons (see [documentation](../img/README.md)): `npm run create-icons`
## Recommended extensions

12
img/README.md Normal file
View File

@@ -0,0 +1,12 @@
# img
This folder contains image files and other resources related to images.
## logo.svg
[logo.svg](./logo.svg) is the master logo from which all other icons or images are created from.
It should be the only file that will be changed manually.
[`logo-update.mjs`](./logo-update.mjs) script in this folder updates all the logo files.
It should be executed everytime the logo is changed.
It automates recreation of logo files in different formats.

127
img/logo-update.mjs Normal file
View File

@@ -0,0 +1,127 @@
#!/usr/bin/env bash
import { resolve, join } from 'path';
import { rm, mkdtemp, stat } from 'fs/promises';
import { spawn } from 'child_process';
import { URL, fileURLToPath } from 'url';
class Paths {
constructor(selfDirectory) {
const projectRoot = resolve(selfDirectory, '../');
this.sourceImage = join(projectRoot, 'img/logo.svg');
this.publicDirectory = join(projectRoot, 'public');
this.electronBuildDirectory = join(projectRoot, 'build');
}
toString() {
return `Source image: ${this.sourceImage}\n`
+ `Public directory: ${this.publicDirectory}\n`
+ `Electron build directory: ${this.electronBuildDirectory}`;
}
}
async function main() {
const paths = new Paths(getCurrentScriptDirectory());
console.log(`Paths:\n\t${paths.toString().replaceAll('\n', '\n\t')}`);
await updateDesktopLauncherAndTrayIcon(paths.sourceImage, paths.publicDirectory);
await updateWebFavicon(paths.sourceImage, paths.publicDirectory);
await updateDesktopIcons(paths.sourceImage, paths.electronBuildDirectory);
console.log('🎉 (Re)created icons successfully.');
}
async function updateDesktopLauncherAndTrayIcon(sourceImage, publicFolder) {
await ensureFileExists(sourceImage);
await ensureFolderExists(publicFolder);
const electronTrayIconFile = join(publicFolder, 'icon.png');
console.log(`Updating desktop launcher and tray icon at ${electronTrayIconFile}.`);
await runCommand(
'npx',
'svgexport',
sourceImage,
electronTrayIconFile,
);
}
async function updateWebFavicon(sourceImage, faviconFolder) {
console.log('Updating favicon');
await ensureFileExists(sourceImage);
await ensureFolderExists(faviconFolder);
await runCommand(
'npx',
'icon-gen',
`--input ${sourceImage}`,
`--output ${faviconFolder}`,
'--ico',
'--ico-name \'favicon\'',
'--report',
);
}
async function updateDesktopIcons(sourceImage, electronIconsDir) {
await ensureFileExists(sourceImage);
await ensureFolderExists(electronIconsDir);
const temporaryDir = await mkdtemp('icon-');
const temporaryPngFile = join(temporaryDir, 'icon.png');
console.log(`Converting from SVG (${sourceImage}) to PNG: ${temporaryPngFile}`); // required by icon-builder
await runCommand(
'npx',
'svgexport',
sourceImage,
temporaryPngFile,
'1024:1024',
);
console.log(`Creating electron icons to ${electronIconsDir}.`);
await runCommand(
'npx',
'electron-icon-builder',
`--input="${temporaryPngFile}"`,
`--output="${electronIconsDir}"`,
'--flatten',
);
console.log('Cleaning up temporary directory.');
await rm(temporaryDir, { recursive: true, force: true });
}
async function ensureFileExists(filePath) {
const path = await stat(filePath);
if (!path.isFile()) {
throw new Error(`Not a file: ${filePath}`);
}
}
async function ensureFolderExists(folderPath) {
const path = await stat(folderPath);
if (!path.isDirectory()) {
throw new Error(`Not a directory: ${folderPath}`);
}
}
async function runCommand(...args) {
const command = args.join(' ');
console.log(`Running command: ${command}`);
await new Promise((resolve, reject) => {
const process = spawn(command, { shell: true });
process.stdout.on('data', (stdout) => {
console.log(stdout.toString());
});
process.stderr.on('data', (stderr) => {
console.error(stderr.toString());
});
process.on('error', (err) => {
reject(err);
});
process.on('close', (exitCode) => {
if (exitCode !== 0) {
reject(new Error(`Process exited with non-zero exit code: ${exitCode}`));
} else {
resolve();
}
process.stdin.end();
});
});
}
function getCurrentScriptDirectory() {
return fileURLToPath(new URL('.', import.meta.url));
}
await main();

56
img/logo.svg Normal file
View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
width="90.2998mm" height="90.2998mm"
viewBox="0 0 256 256">
<path id="logo"
fill="#3a65ab" stroke="#3a65ab" stroke-width="1"
d="M 128.00,173.00
C 128.00,173.00 102.00,175.00 102.00,175.00
85.39,174.97 64.02,170.31 49.00,163.22
38.46,158.24 28.39,152.17 20.01,143.96
14.88,138.93 10.72,133.32 7.31,127.00
3.36,119.66 1.10,112.37 1.00,104.00
1.00,104.00 1.00,98.00 1.00,98.00
1.29,73.92 24.76,53.44 44.00,42.43
84.66,19.15 129.75,23.12 169.00,47.00
188.74,59.02 207.93,76.23 208.00,101.00
208.00,101.00 188.00,101.00 188.00,101.00
186.46,86.48 168.72,71.84 157.00,64.61
140.76,54.59 121.33,46.78 102.00,47.00
88.42,47.16 72.20,52.52 60.00,58.32
45.30,65.30 19.83,84.81 21.10,103.00
21.39,107.16 22.92,110.33 24.76,114.00
32.70,129.78 48.16,140.02 64.00,146.72
75.16,151.44 92.90,155.26 105.00,154.99
113.45,154.79 121.81,152.84 130.00,151.00
130.00,151.00 128.00,173.00 128.00,173.00 Z
M 136.00,79.00
C 142.71,81.35 144.84,93.60 144.99,100.00
145.51,122.74 130.31,140.73 107.00,141.00
83.63,141.26 67.43,126.52 66.09,103.00
64.82,80.73 85.85,58.90 104.00,64.00
100.18,69.73 95.45,74.53 96.20,82.00
97.29,92.87 110.06,102.98 121.00,99.03
129.92,95.81 134.61,87.96 136.00,79.00 Z
M 186.00,113.46
C 206.11,110.69 225.57,114.92 239.91,130.01
252.85,143.63 255.21,157.09 255.00,175.00
254.76,195.49 241.26,214.25 223.00,222.88
213.06,227.58 204.72,228.12 194.00,228.00
150.34,227.49 126.71,178.85 146.32,142.00
154.93,125.82 168.55,117.23 186.00,113.46 Z
M 233.00,181.00
C 242.24,158.78 221.84,133.54 199.00,133.01
188.40,132.77 182.75,135.31 174.00,141.00
178.60,146.85 195.92,157.24 203.00,161.86
209.82,166.32 226.61,178.55 233.00,181.00 Z
M 221.00,200.00
C 216.39,194.15 206.42,188.61 200.00,184.33
192.31,179.21 168.77,162.59 162.00,160.00
159.67,165.03 159.94,166.57 160.00,172.00
160.23,190.99 177.11,207.55 196.00,207.99
206.60,208.23 212.25,205.69 221.00,200.00 Z" />
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

3252
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"create-icons": "node img/logo-update.mjs",
"test:unit": "vue-cli-service test:unit",
"test:e2e": "vue-cli-service test:e2e",
"lint": "npm run lint:md && npm run lint:md:consistency && npm run lint:md:relative-urls && npm run lint:eslint && npm run lint:yaml",
@@ -65,12 +66,14 @@
"electron": "^17.1.0",
"electron-builder": "^22.14.13",
"electron-devtools-installer": "^3.2.0",
"electron-icon-builder": "^2.0.1",
"electron-log": "^4.4.6",
"electron-updater": "^5.0.0",
"eslint": "7.32.0",
"eslint-plugin-import": "^2.25.4",
"eslint-plugin-vue": "^8.5.0",
"eslint-plugin-vuejs-accessibility": "^1.1.1",
"icon-gen": "^3.0.1",
"js-yaml-loader": "^1.2.2",
"markdownlint-cli": "^0.31.1",
"remark-cli": "^10.0.1",
@@ -79,6 +82,7 @@
"remark-validate-links": "^11.0.2",
"sass": "^1.49.9",
"sass-loader": "^12.6.0",
"svgexport": "^0.4.2",
"ts-loader": "9.0.1",
"tslib": "^2.3.1",
"typescript": "^4.6.2",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 353 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 16 KiB