This commit is contained in:
kai
2026-08-26 11:06:46 +02:00
parent b7128e8aaf
commit b7d664beac
+59
View File
@@ -11,6 +11,7 @@
.patch-preview { width: 140px; height: 140px; object-fit: contain; padding: 4px; background: #242424; border: 2px dashed #78716c; border-radius: 12px; }
.patch-placeholder { display: grid; place-items: center; font-size: 2.5rem; }
.patch-upload { display: grid; gap: 8px; }
.patch-upload-status { min-height: 1.2em; color: var(--muted); font-size: .85rem; }
</style>
</head>
<body>
@@ -26,6 +27,7 @@
<div><strong>{{ patch.name }}</strong><div class="admin-meta">{{ patch.description }} · {{ patch.code }}</div></div>
<form class="patch-upload" method="post" action="/admin/patches/{{ patch.code }}" enctype="multipart/form-data">
<input type="file" name="image" accept="image/jpeg,image/png,image/webp" required>
<span class="patch-upload-status">Das Bild wird vor dem Upload automatisch optimiert.</span>
<button class="button" type="submit">{% if patch.image_path %}Bild ersetzen{% else %}Bild hochladen{% endif %}</button>
</form>
{% if patch.image_path %}<form method="post" action="/admin/patches/{{ patch.code }}/delete" onsubmit="return confirm('Patch-Bild entfernen und wieder das Symbol verwenden?');"><button class="admin-danger" type="submit">Bild entfernen</button></form>{% endif %}
@@ -34,5 +36,62 @@
</div>
</section>
</main>
<script>
const patchForms = document.querySelectorAll(".patch-upload");
async function optimizePatchImage(file) {
const bitmap = await createImageBitmap(file);
const maxSide = 800;
const scale = Math.min(1, maxSide / Math.max(bitmap.width, bitmap.height));
const canvas = document.createElement("canvas");
canvas.width = Math.max(1, Math.round(bitmap.width * scale));
canvas.height = Math.max(1, Math.round(bitmap.height * scale));
const context = canvas.getContext("2d");
context.imageSmoothingEnabled = true;
context.imageSmoothingQuality = "high";
context.drawImage(bitmap, 0, 0, canvas.width, canvas.height);
bitmap.close();
let quality = 0.9;
let blob;
do {
blob = await new Promise(resolve => canvas.toBlob(resolve, "image/webp", quality));
quality -= 0.1;
} while (blob && blob.size > 700 * 1024 && quality >= 0.5);
if (!blob) {
throw new Error("Bild konnte nicht verarbeitet werden");
}
return new File([blob], "patch.webp", {type: "image/webp"});
}
patchForms.forEach(form => {
form.addEventListener("submit", async event => {
if (form.dataset.optimized === "true") return;
event.preventDefault();
const input = form.querySelector('input[type="file"]');
const status = form.querySelector(".patch-upload-status");
const button = form.querySelector('button[type="submit"]');
const file = input.files[0];
if (!file) return;
button.disabled = true;
status.textContent = "Bild wird optimiert …";
try {
const optimized = await optimizePatchImage(file);
const transfer = new DataTransfer();
transfer.items.add(optimized);
input.files = transfer.files;
form.dataset.optimized = "true";
status.textContent = `Optimiert: ${Math.ceil(optimized.size / 1024)} KB wird hochgeladen …`;
form.requestSubmit();
} catch (error) {
console.error("Patch image optimization failed:", error);
status.textContent = "Das Bild konnte nicht optimiert werden. Bitte ein kleineres JPG, PNG oder WebP wählen.";
button.disabled = false;
}
});
});
</script>
</body>
</html>