Add Windows support via a Tauri (WebView2) shell
zero-native has no Windows target yet, so add a parallel Tauri shell for Windows that reuses the same frontend: - src-tauri/: Rust commands (yt_search, yt_streams, store_load, store_save) mirroring the Zig bridge; spawns bundled yt-dlp.exe with CREATE_NO_WINDOW; data stored in app_data_dir - frontend bridge now auto-detects window.__TAURI__ vs window.zero and routes accordingly; CSP updated for Tauri IPC - tauri.conf.json bundles yt-dlp.exe as a resource and builds nsis/msi - scripts/make-icon.js generates appicon.png for 'tauri icon' - README: native Windows build steps + WSLg fallback note
This commit is contained in:
92
scripts/make-icon.js
Normal file
92
scripts/make-icon.js
Normal file
@@ -0,0 +1,92 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Generates appicon.png (512x512) — a vermilion tile with a white play glyph.
|
||||
* No image libraries: encodes a PNG by hand with Node's zlib.
|
||||
*
|
||||
* After running this, expand it into all platform sizes with the Tauri CLI:
|
||||
* npm run tauri icon ./appicon.png
|
||||
*/
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const zlib = require('zlib');
|
||||
|
||||
const SIZE = 512;
|
||||
|
||||
// CRC32 (PNG chunk checksums)
|
||||
const CRC_TABLE = (() => {
|
||||
const t = new Uint32Array(256);
|
||||
for (let n = 0; n < 256; n++) {
|
||||
let c = n;
|
||||
for (let k = 0; k < 8; k++) c = c & 1 ? 0xedb88320 ^ (c >>> 1) : c >>> 1;
|
||||
t[n] = c >>> 0;
|
||||
}
|
||||
return t;
|
||||
})();
|
||||
function crc32(buf) {
|
||||
let c = 0xffffffff;
|
||||
for (let i = 0; i < buf.length; i++) c = CRC_TABLE[(c ^ buf[i]) & 0xff] ^ (c >>> 8);
|
||||
return (c ^ 0xffffffff) >>> 0;
|
||||
}
|
||||
function chunk(type, data) {
|
||||
const len = Buffer.alloc(4);
|
||||
len.writeUInt32BE(data.length, 0);
|
||||
const typeBuf = Buffer.from(type, 'ascii');
|
||||
const crc = Buffer.alloc(4);
|
||||
crc.writeUInt32BE(crc32(Buffer.concat([typeBuf, data])), 0);
|
||||
return Buffer.concat([len, typeBuf, data, crc]);
|
||||
}
|
||||
|
||||
// --- paint pixels (RGBA) ---
|
||||
const px = Buffer.alloc(SIZE * SIZE * 4);
|
||||
function set(x, y, r, g, b, a = 255) {
|
||||
const i = (y * SIZE + x) * 4;
|
||||
px[i] = r; px[i + 1] = g; px[i + 2] = b; px[i + 3] = a;
|
||||
}
|
||||
|
||||
// Background: subtle vertical vermilion gradient (#ff6a52 -> #d4321d)
|
||||
for (let y = 0; y < SIZE; y++) {
|
||||
const t = y / SIZE;
|
||||
const r = Math.round(0xff + (0xd4 - 0xff) * t);
|
||||
const g = Math.round(0x6a + (0x32 - 0x6a) * t);
|
||||
const b = Math.round(0x52 + (0x1d - 0x52) * t);
|
||||
for (let x = 0; x < SIZE; x++) set(x, y, r, g, b);
|
||||
}
|
||||
|
||||
// White play triangle, centered, slightly right-nudged for optical balance.
|
||||
const ax = 196, ay = 150, bx = 196, by = 362, cx = 384, cy = 256;
|
||||
function edge(px1, py1, px2, py2, x, y) {
|
||||
return (x - px1) * (py2 - py1) - (y - py1) * (px2 - px1);
|
||||
}
|
||||
for (let y = 120; y < 392; y++) {
|
||||
for (let x = 170; x < 400; x++) {
|
||||
const w0 = edge(bx, by, cx, cy, x, y);
|
||||
const w1 = edge(cx, cy, ax, ay, x, y);
|
||||
const w2 = edge(ax, ay, bx, by, x, y);
|
||||
if ((w0 <= 0 && w1 <= 0 && w2 <= 0) || (w0 >= 0 && w1 >= 0 && w2 >= 0)) {
|
||||
set(x, y, 255, 255, 255);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- encode ---
|
||||
const raw = Buffer.alloc((SIZE * 4 + 1) * SIZE);
|
||||
for (let y = 0; y < SIZE; y++) {
|
||||
raw[y * (SIZE * 4 + 1)] = 0; // filter: none
|
||||
px.copy(raw, y * (SIZE * 4 + 1) + 1, y * SIZE * 4, (y + 1) * SIZE * 4);
|
||||
}
|
||||
const ihdr = Buffer.alloc(13);
|
||||
ihdr.writeUInt32BE(SIZE, 0);
|
||||
ihdr.writeUInt32BE(SIZE, 4);
|
||||
ihdr[8] = 8; // bit depth
|
||||
ihdr[9] = 6; // color type RGBA
|
||||
const png = Buffer.concat([
|
||||
Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]),
|
||||
chunk('IHDR', ihdr),
|
||||
chunk('IDAT', zlib.deflateSync(raw, { level: 9 })),
|
||||
chunk('IEND', Buffer.alloc(0)),
|
||||
]);
|
||||
|
||||
const out = path.join(__dirname, '..', 'appicon.png');
|
||||
fs.writeFileSync(out, png);
|
||||
console.log(`Wrote ${out} (${SIZE}x${SIZE}).`);
|
||||
console.log('Now run: npm run tauri icon ./appicon.png');
|
||||
Reference in New Issue
Block a user