mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-18 21:16:47 +00:00
68 lines
2.7 KiB
JavaScript
68 lines
2.7 KiB
JavaScript
/**
|
|
* Generates the Android status-bar notification icon from the master
|
|
* white-silhouette SVG.
|
|
*
|
|
* Android renders the small notification icon as a mask: every non-transparent
|
|
* pixel becomes the tint colour and everything else is dropped. Feeding it the
|
|
* launcher icon (a full-bleed coloured square) therefore produces a solid white
|
|
* blob, which is the single most common Capacitor push-notification complaint.
|
|
* public/icons/icon-white.svg is already white-on-transparent, so we only have
|
|
* to rasterise it at the five densities and flatten the colour to pure white so
|
|
* any future edit to that SVG's fill cannot silently change the mask.
|
|
*
|
|
* Referenced from AndroidManifest.xml as @drawable/notification_icon.
|
|
* Run: node scripts/generate-native-icons.mjs
|
|
*/
|
|
import { mkdirSync } from 'fs';
|
|
import { dirname, join } from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
import sharp from 'sharp';
|
|
|
|
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
const clientDir = join(__dirname, '..');
|
|
const source = join(clientDir, 'public', 'icons', 'icon-white.svg');
|
|
const resDir = join(clientDir, 'android', 'app', 'src', 'main', 'res');
|
|
|
|
// Android notification icon sizes, in px, per density bucket (24dp baseline).
|
|
const densities = [
|
|
{ dir: 'drawable-mdpi', size: 24 },
|
|
{ dir: 'drawable-hdpi', size: 36 },
|
|
{ dir: 'drawable-xhdpi', size: 48 },
|
|
{ dir: 'drawable-xxhdpi', size: 72 },
|
|
{ dir: 'drawable-xxxhdpi', size: 96 },
|
|
];
|
|
|
|
for (const { dir, size } of densities) {
|
|
const outDir = join(resDir, dir);
|
|
mkdirSync(outDir, { recursive: true });
|
|
|
|
// Inset the glyph slightly: Android's status bar clips tight to the 24dp box
|
|
// and a mark that touches the edge reads as cropped.
|
|
const glyph = Math.round(size * 0.86);
|
|
|
|
const mask = await sharp(source, { density: 512 })
|
|
.resize(glyph, glyph, { fit: 'contain', background: { r: 0, g: 0, b: 0, alpha: 0 } })
|
|
.extend({
|
|
top: Math.floor((size - glyph) / 2),
|
|
bottom: Math.ceil((size - glyph) / 2),
|
|
left: Math.floor((size - glyph) / 2),
|
|
right: Math.ceil((size - glyph) / 2),
|
|
background: { r: 0, g: 0, b: 0, alpha: 0 },
|
|
})
|
|
.ensureAlpha()
|
|
.toBuffer();
|
|
|
|
// Keep the alpha, force every visible pixel to pure white. `dest-in` composites
|
|
// the white plate through the glyph's alpha channel.
|
|
await sharp({
|
|
create: { width: size, height: size, channels: 4, background: { r: 255, g: 255, b: 255, alpha: 1 } },
|
|
})
|
|
.composite([{ input: mask, blend: 'dest-in' }])
|
|
.png({ compressionLevel: 9 })
|
|
.toFile(join(outDir, 'notification_icon.png'));
|
|
|
|
console.log(` ✓ ${dir}/notification_icon.png (${size}x${size})`);
|
|
}
|
|
|
|
console.log('Android notification icons generated.');
|