137 lines
3.7 KiB
JavaScript
137 lines
3.7 KiB
JavaScript
import "/wasm/wasm_exec.js";
|
|
|
|
const go = new Go();
|
|
let wasmReady = false;
|
|
|
|
WebAssembly.instantiateStreaming(fetch("/wasm/android-icons.wasm"), go.importObject)
|
|
.then((result) => {
|
|
go.run(result.instance);
|
|
wasmReady = true;
|
|
});
|
|
|
|
const fileInput = document.getElementById("file-input");
|
|
const previewArea = document.getElementById("preview-area");
|
|
const prepareBtn = document.getElementById("prepare-btn");
|
|
const statusEl = document.getElementById("status");
|
|
const circlePreview = document.getElementById("circle-preview");
|
|
const circleCanvas = document.getElementById("circle-canvas");
|
|
|
|
let loadedFiles = [];
|
|
|
|
function renderCirclePreview() {
|
|
if (loadedFiles.length === 0) {
|
|
circlePreview.style.display = "none";
|
|
return;
|
|
}
|
|
|
|
const nameLower = (f) => f.name.toLowerCase();
|
|
|
|
let bgFile = loadedFiles.find((f) => /back/.test(nameLower(f)));
|
|
let fgFile = loadedFiles.find((f) => !/back/.test(nameLower(f)) && !/mono/.test(nameLower(f)));
|
|
|
|
// Fallbacks: if only one image or no "back" image, use the first file
|
|
if (!bgFile && !fgFile) {
|
|
bgFile = loadedFiles[0];
|
|
} else if (!bgFile) {
|
|
bgFile = fgFile;
|
|
fgFile = null;
|
|
}
|
|
|
|
const size = 192;
|
|
circleCanvas.width = size;
|
|
circleCanvas.height = size;
|
|
const ctx = circleCanvas.getContext("2d");
|
|
ctx.clearRect(0, 0, size, size);
|
|
|
|
// Clip to circle
|
|
ctx.save();
|
|
ctx.beginPath();
|
|
ctx.arc(size / 2, size / 2, size / 2, 0, Math.PI * 2);
|
|
ctx.closePath();
|
|
ctx.clip();
|
|
|
|
const drawLayer = (src) => {
|
|
return new Promise((resolve) => {
|
|
const img = new Image();
|
|
img.onload = () => {
|
|
ctx.drawImage(img, 0, 0, size, size);
|
|
resolve();
|
|
};
|
|
img.onerror = resolve;
|
|
img.src = src;
|
|
});
|
|
};
|
|
|
|
drawLayer(bgFile.data).then(() => {
|
|
if (fgFile && fgFile !== bgFile) {
|
|
return drawLayer(fgFile.data);
|
|
}
|
|
}).then(() => {
|
|
ctx.restore();
|
|
|
|
// Draw border ring
|
|
ctx.beginPath();
|
|
ctx.arc(size / 2, size / 2, size / 2 - 1.5, 0, Math.PI * 2);
|
|
ctx.closePath();
|
|
ctx.strokeStyle = "rgba(128, 128, 128, 0.5)";
|
|
ctx.lineWidth = 3;
|
|
ctx.stroke();
|
|
|
|
circlePreview.style.display = "block";
|
|
});
|
|
}
|
|
|
|
fileInput.addEventListener("change", () => {
|
|
const files = Array.from(fileInput.files);
|
|
loadedFiles = [];
|
|
previewArea.innerHTML = "";
|
|
circlePreview.style.display = "none";
|
|
|
|
if (files.length === 0) {
|
|
prepareBtn.disabled = true;
|
|
return;
|
|
}
|
|
|
|
files.forEach((file) => {
|
|
const reader = new FileReader();
|
|
reader.onload = (e) => {
|
|
const dataURL = e.target.result;
|
|
loadedFiles.push({ name: file.name, data: dataURL });
|
|
|
|
const item = document.createElement("div");
|
|
item.className = "preview-item";
|
|
|
|
const img = document.createElement("img");
|
|
img.src = dataURL;
|
|
|
|
const label = document.createElement("span");
|
|
label.textContent = file.name;
|
|
|
|
item.appendChild(img);
|
|
item.appendChild(label);
|
|
previewArea.appendChild(item);
|
|
|
|
if (loadedFiles.length === files.length) {
|
|
prepareBtn.disabled = false;
|
|
renderCirclePreview();
|
|
}
|
|
};
|
|
reader.readAsDataURL(file);
|
|
});
|
|
});
|
|
|
|
prepareBtn.addEventListener("click", () => {
|
|
if (!wasmReady) {
|
|
statusEl.textContent = "WASM module is still loading, please wait...";
|
|
return;
|
|
}
|
|
if (loadedFiles.length === 0) {
|
|
return;
|
|
}
|
|
statusEl.textContent = "Preparing...";
|
|
// Pass file data to Go WASM
|
|
setTimeout(() => {
|
|
prepareZip(loadedFiles);
|
|
}, 50);
|
|
});
|