← back to Watches
utils/generate-icons.js
203 lines
/**
* Icon Generator for PWA
* Creates app icons from SVG using canvas
*
* NOTE: This is a simple placeholder generator.
* For production, use real Omega watch imagery or professional icon design.
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const ICON_SIZES = [72, 96, 128, 144, 152, 192, 384, 512];
// SVG icon template (Omega-inspired design)
const iconSVG = (size) => `
<svg width="${size}" height="${size}" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg">
<!-- Background -->
<rect width="512" height="512" fill="#0C1E3C"/>
<!-- Omega Symbol Approximation (Circle with gap) -->
<g transform="translate(256, 256)">
<!-- Outer circle -->
<circle cx="0" cy="0" r="180" fill="none" stroke="#C41E3A" stroke-width="24"/>
<!-- Inner circle -->
<circle cx="0" cy="0" r="120" fill="none" stroke="#C41E3A" stroke-width="16"/>
<!-- Bottom gap -->
<rect x="-20" y="140" width="40" height="80" fill="#0C1E3C"/>
<!-- Bottom extensions -->
<rect x="-140" y="180" width="100" height="24" rx="12" fill="#C41E3A"/>
<rect x="40" y="180" width="100" height="24" rx="12" fill="#C41E3A"/>
<!-- Watch hands -->
<line x1="0" y1="0" x2="0" y2="-80" stroke="#fff" stroke-width="12" stroke-linecap="round"/>
<line x1="0" y1="0" x2="60" y2="40" stroke="#fff" stroke-width="10" stroke-linecap="round"/>
<!-- Center dot -->
<circle cx="0" cy="0" r="16" fill="#C41E3A"/>
<circle cx="0" cy="0" r="8" fill="#fff"/>
</g>
<!-- Text (for larger icons) -->
${size >= 192 ? `<text x="256" y="470" font-family="Arial, sans-serif" font-size="48" font-weight="bold" fill="#C41E3A" text-anchor="middle">OMEGA</text>` : ''}
</svg>
`;
// Generate PNG from SVG (requires sharp or similar, we'll use placeholder approach)
async function generateIcons() {
console.log('Generating PWA icons...');
const iconsDir = path.join(__dirname, '..', 'public', 'icons');
// Ensure icons directory exists
if (!fs.existsSync(iconsDir)) {
fs.mkdirSync(iconsDir, { recursive: true });
}
// Generate SVG icons (as fallback)
for (const size of ICON_SIZES) {
const svg = iconSVG(size);
const filename = `icon-${size}x${size}.svg`;
const filepath = path.join(iconsDir, filename);
fs.writeFileSync(filepath, svg);
console.log(`Created ${filename}`);
}
// Create a simple HTML file that can be used to convert SVG to PNG
const converterHTML = `
<!DOCTYPE html>
<html>
<head>
<title>Icon Converter</title>
<style>
body { font-family: Arial; padding: 20px; }
canvas { border: 1px solid #ccc; margin: 10px; }
.icon-group { margin-bottom: 20px; }
</style>
</head>
<body>
<h1>PWA Icon Converter</h1>
<p>Right-click each canvas and "Save image as..." to create PNG icons.</p>
<div id="icons"></div>
<script>
const sizes = ${JSON.stringify(ICON_SIZES)};
const iconsContainer = document.getElementById('icons');
sizes.forEach(size => {
const div = document.createElement('div');
div.className = 'icon-group';
const title = document.createElement('h3');
title.textContent = \`icon-\${size}x\${size}.png\`;
div.appendChild(title);
const canvas = document.createElement('canvas');
canvas.width = size;
canvas.height = size;
div.appendChild(canvas);
const ctx = canvas.getContext('2d');
// Background
ctx.fillStyle = '#0C1E3C';
ctx.fillRect(0, 0, size, size);
// Scale factor
const scale = size / 512;
ctx.translate(size / 2, size / 2);
ctx.scale(scale, scale);
// Outer circle
ctx.strokeStyle = '#C41E3A';
ctx.lineWidth = 24;
ctx.beginPath();
ctx.arc(0, 0, 180, 0, Math.PI * 2);
ctx.stroke();
// Inner circle
ctx.lineWidth = 16;
ctx.beginPath();
ctx.arc(0, 0, 120, 0, Math.PI * 2);
ctx.stroke();
// Bottom gap
ctx.fillStyle = '#0C1E3C';
ctx.fillRect(-20, 140, 40, 80);
// Bottom extensions
ctx.fillStyle = '#C41E3A';
ctx.beginPath();
ctx.roundRect(-140, 180, 100, 24, 12);
ctx.fill();
ctx.beginPath();
ctx.roundRect(40, 180, 100, 24, 12);
ctx.fill();
// Watch hands
ctx.strokeStyle = '#fff';
ctx.lineWidth = 12;
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(0, -80);
ctx.stroke();
ctx.lineWidth = 10;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(60, 40);
ctx.stroke();
// Center dot
ctx.fillStyle = '#C41E3A';
ctx.beginPath();
ctx.arc(0, 0, 16, 0, Math.PI * 2);
ctx.fill();
ctx.fillStyle = '#fff';
ctx.beginPath();
ctx.arc(0, 0, 8, 0, Math.PI * 2);
ctx.fill();
// Reset transform for text
ctx.setTransform(1, 0, 0, 1, 0, 0);
// Text (for larger icons)
if (size >= 192) {
ctx.fillStyle = '#C41E3A';
ctx.font = \`bold \${48 * scale}px Arial\`;
ctx.textAlign = 'center';
ctx.fillText('OMEGA', size / 2, size - 42 * scale);
}
iconsContainer.appendChild(div);
});
</script>
</body>
</html>
`;
const converterPath = path.join(iconsDir, 'icon-converter.html');
fs.writeFileSync(converterPath, converterHTML);
console.log('Created icon-converter.html');
console.log('\n✅ Icon generation complete!');
console.log(`\nTo create PNG icons:`);
console.log(`1. Open http://45.61.58.125:7600/icons/icon-converter.html in a browser`);
console.log(`2. Right-click each canvas and save as PNG`);
console.log(`3. Save files as icon-72x72.png, icon-96x96.png, etc. in /public/icons/\n`);
}
generateIcons().catch(console.error);