fix(ci): center-crop non-square logos before tauri icon generation
tauri icon requires a square source image. Uploaded logos like 727x721 caused Prepare template to fail. Use sharp to center-crop to square before generating platform icons. Co-authored-by: ShuMengya <shumengya666@outlook.com>
This commit is contained in:
47
.github/scripts/generate-app-icons.mjs
vendored
47
.github/scripts/generate-app-icons.mjs
vendored
@@ -1,7 +1,9 @@
|
|||||||
import { execSync } from "node:child_process";
|
import { execSync } from "node:child_process";
|
||||||
import fs from "node:fs";
|
import fs from "node:fs";
|
||||||
|
import os from "node:os";
|
||||||
import path from "node:path";
|
import path from "node:path";
|
||||||
import { fileURLToPath } from "node:url";
|
import { fileURLToPath } from "node:url";
|
||||||
|
import sharp from "sharp";
|
||||||
|
|
||||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
const root = path.resolve(__dirname, "../..");
|
const root = path.resolve(__dirname, "../..");
|
||||||
@@ -37,16 +39,48 @@ function findIconSource(baseDir) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function findIconSourceForJob(root, jobId, distDir) {
|
export function findIconSourceForJob(rootDir, jobId, dist) {
|
||||||
const buildDir = jobId ? path.join(root, "builds", jobId) : null;
|
const buildDir = jobId ? path.join(rootDir, "builds", jobId) : null;
|
||||||
if (buildDir && fs.existsSync(buildDir)) {
|
if (buildDir && fs.existsSync(buildDir)) {
|
||||||
const fromUpload = findIconSource(buildDir);
|
const fromUpload = findIconSource(buildDir);
|
||||||
if (fromUpload) return fromUpload;
|
if (fromUpload) return fromUpload;
|
||||||
}
|
}
|
||||||
return findIconSource(distDir);
|
return findIconSource(dist);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function generateAppIcons(options = {}) {
|
async function ensureSquareIconSource(iconSource) {
|
||||||
|
const meta = await sharp(iconSource).metadata();
|
||||||
|
const width = meta.width ?? 0;
|
||||||
|
const height = meta.height ?? 0;
|
||||||
|
|
||||||
|
if (!width || !height) {
|
||||||
|
throw new Error(`Unable to read icon dimensions: ${iconSource}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (width === height) {
|
||||||
|
return iconSource;
|
||||||
|
}
|
||||||
|
|
||||||
|
const size = Math.min(width, height);
|
||||||
|
const left = Math.floor((width - size) / 2);
|
||||||
|
const top = Math.floor((height - size) / 2);
|
||||||
|
const squarePath = path.join(
|
||||||
|
os.tmpdir(),
|
||||||
|
`web2app-icon-${path.basename(iconSource, path.extname(iconSource))}.png`,
|
||||||
|
);
|
||||||
|
|
||||||
|
await sharp(iconSource)
|
||||||
|
.extract({ left, top, width: size, height: size })
|
||||||
|
.png()
|
||||||
|
.toFile(squarePath);
|
||||||
|
|
||||||
|
console.log(
|
||||||
|
`Normalized icon to square by center crop (${width}x${height} -> ${size}x${size})`,
|
||||||
|
);
|
||||||
|
return squarePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function generateAppIcons(options = {}) {
|
||||||
const { jobId } = options;
|
const { jobId } = options;
|
||||||
if (!fs.existsSync(distDir)) {
|
if (!fs.existsSync(distDir)) {
|
||||||
console.log("No dist directory, keeping default icons");
|
console.log("No dist directory, keeping default icons");
|
||||||
@@ -59,8 +93,9 @@ export function generateAppIcons(options = {}) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const squareSource = await ensureSquareIconSource(iconSource);
|
||||||
console.log(`Generating app icons from: ${path.relative(root, iconSource)}`);
|
console.log(`Generating app icons from: ${path.relative(root, iconSource)}`);
|
||||||
execSync(`npx tauri icon "${iconSource}"`, {
|
execSync(`npx tauri icon "${squareSource}"`, {
|
||||||
cwd: templateDir,
|
cwd: templateDir,
|
||||||
stdio: "inherit",
|
stdio: "inherit",
|
||||||
});
|
});
|
||||||
@@ -74,5 +109,5 @@ const isCli =
|
|||||||
path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
path.resolve(process.argv[1]) === fileURLToPath(import.meta.url);
|
||||||
|
|
||||||
if (isCli) {
|
if (isCli) {
|
||||||
generateAppIcons({ jobId: process.env.JOB_ID });
|
await generateAppIcons({ jobId: process.env.JOB_ID });
|
||||||
}
|
}
|
||||||
|
|||||||
2
.github/scripts/prepare-template.mjs
vendored
2
.github/scripts/prepare-template.mjs
vendored
@@ -99,6 +99,6 @@ if (fs.existsSync(androidConfPath)) {
|
|||||||
patchTauriConfig(androidConfPath);
|
patchTauriConfig(androidConfPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
generateAppIcons({ jobId });
|
await generateAppIcons({ jobId });
|
||||||
|
|
||||||
console.log("Template prepared successfully");
|
console.log("Template prepared successfully");
|
||||||
|
|||||||
824
package-lock.json
generated
824
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -18,6 +18,7 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"adm-zip": "^0.5.17",
|
"adm-zip": "^0.5.17",
|
||||||
"concurrently": "^9.1.2",
|
"concurrently": "^9.1.2",
|
||||||
|
"sharp": "^0.34.2",
|
||||||
"typescript": "~5.6.2",
|
"typescript": "~5.6.2",
|
||||||
"wrangler": "^3.99.0"
|
"wrangler": "^3.99.0"
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user