feat(android): generate launcher icons from zeavis-logo.svg during CI build
- Add scripts/generate-icons.js using sharp to convert SVG to PNG at all Android density buckets (mdpi 48→xxxhdpi 192) - Add sharp as devDependency - Update CI workflow to run icon generation after tauri android init - Replaces Tauri's default icons with ZeaVis Edu logo Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -136,7 +136,11 @@ jobs:
|
|||||||
rm -rf gen/android
|
rm -rf gen/android
|
||||||
bun tauri android init
|
bun tauri android init
|
||||||
|
|
||||||
- name: Patch AndroidManifest (CAMERA permission)
|
- name: Generate Android launcher icons from SVG logo
|
||||||
|
working-directory: apps/tauri
|
||||||
|
run: bun run scripts/generate-icons.js
|
||||||
|
|
||||||
|
- name: Patch AndroidManifest (CAMERA permission + deep link)
|
||||||
working-directory: apps/tauri
|
working-directory: apps/tauri
|
||||||
run: bash scripts/patch-android-manifest.sh
|
run: bash scripts/patch-android-manifest.sh
|
||||||
|
|
||||||
|
|||||||
@@ -12,5 +12,8 @@
|
|||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tauri-apps/cli": "^2"
|
"@tauri-apps/cli": "^2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"sharp": "0.35.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Generate Android launcher icons from the ZeaVis Edu logo SVG.
|
||||||
|
* Produces PNGs at all required densities and replaces Tauri's default icons.
|
||||||
|
*
|
||||||
|
* Usage: node scripts/generate-icons.js
|
||||||
|
* Requires: bun add sharp (already in devDependencies)
|
||||||
|
*/
|
||||||
|
|
||||||
|
const sharp = require('sharp');
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
const LOGO = path.resolve(__dirname, '../../../.github/assets/zeavis-logo.svg');
|
||||||
|
const RES = path.resolve(__dirname, '../gen/android/app/src/main/res');
|
||||||
|
|
||||||
|
// Android density buckets: [folder, size]
|
||||||
|
const DENSITIES = [
|
||||||
|
['mipmap-mdpi', 48],
|
||||||
|
['mipmap-hdpi', 72],
|
||||||
|
['mipmap-xhdpi', 96],
|
||||||
|
['mipmap-xxhdpi', 144],
|
||||||
|
['mipmap-xxxhdpi', 192],
|
||||||
|
];
|
||||||
|
|
||||||
|
async function generate() {
|
||||||
|
if (!fs.existsSync(LOGO)) {
|
||||||
|
console.error(`ERROR: Logo not found at ${LOGO}`);
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(`Generating icons from ${LOGO}...`);
|
||||||
|
|
||||||
|
for (const [folder, size] of DENSITIES) {
|
||||||
|
const dir = path.join(RES, folder);
|
||||||
|
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
||||||
|
|
||||||
|
const png = await sharp(LOGO)
|
||||||
|
.resize(size, size, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
||||||
|
.png()
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
// Write both legacy and adaptive icon names
|
||||||
|
for (const name of ['ic_launcher.png', 'ic_launcher_foreground.png', 'ic_launcher_round.png']) {
|
||||||
|
fs.writeFileSync(path.join(dir, name), png);
|
||||||
|
}
|
||||||
|
console.log(` ${folder}: ${size}x${size} OK`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also write the legacy icon to drawable for completeness
|
||||||
|
const drawableDir = path.join(RES, 'drawable');
|
||||||
|
if (!fs.existsSync(drawableDir)) fs.mkdirSync(drawableDir, { recursive: true });
|
||||||
|
const refPng = await sharp(LOGO)
|
||||||
|
.resize(144, 144, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
||||||
|
.png()
|
||||||
|
.toBuffer();
|
||||||
|
fs.writeFileSync(path.join(drawableDir, 'ic_launcher.png'), refPng);
|
||||||
|
|
||||||
|
console.log('Done. Android launcher icons generated.');
|
||||||
|
}
|
||||||
|
|
||||||
|
generate().catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
process.exit(1);
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user