Erster Upload von MX Linux

This commit is contained in:
2026-02-02 09:45:14 +01:00
commit a25d0becaf
109 changed files with 6801 additions and 0 deletions

118
public/apps/pixel.html Normal file
View File

@@ -0,0 +1,118 @@
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="UTF-8">
<title>Pixel Labor</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover">
<script src="../js/tailwind.js"></script>
<style>
@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }
html { width: 100%; height: 100%; background-color: #0f172a; }
body {
position: fixed; top: 0; left: 0; right: 0; bottom: 0; margin: 0;
background-color: #0f172a;
color: white;
overflow: hidden !important;
user-select: none;
touch-action: none;
font-family: sans-serif;
animation: fadeIn 0.4s ease-out;
box-sizing: border-box;
padding-top: calc(10px + env(safe-area-inset-top));
padding-bottom: max(20px, env(safe-area-inset-bottom));
}
.pixel-grid { display: grid; grid-template-columns: repeat(16, 1fr); grid-template-rows: repeat(16, 1fr); gap: 1px; background: #334155; border: 8px solid #10b981; box-shadow: 0 25px 50px -12px rgba(0, 0, 0, 0.7); border-radius: 1rem; overflow: hidden; touch-action: none; width: 100%; height: 100%; aspect-ratio: 1 / 1; }
.cell { background-color: white; cursor: pointer; transition: background-color 0.05s; }
.no-scrollbar::-webkit-scrollbar { display: none; }
button:active { transform: scale(0.95); transition: transform 0.1s; }
@media print { body * { visibility: hidden; } #print-container, #print-container * { visibility: visible; } #print-container { position: fixed; left: 0; top: 0; width: 100%; height: 100%; display: flex !important; align-items: center; justify-content: center; background: white; z-index: 99999; } #print-img { max-width: 90%; max-height: 90%; object-fit: contain; border: 4px solid black; image-rendering: pixelated; } }
</style>
</head>
<body class="flex flex-col p-4"
onclick="if(window.resetIdleTimer) window.resetIdleTimer()"
ontouchstart="if(window.resetIdleTimer) window.resetIdleTimer()">
<div class="flex-none flex justify-between items-center shrink-0 mb-2 px-2 relative z-50 h-16">
<button onclick="goHome()" class="bg-slate-800 text-white border-4 border-slate-600 hover:border-white px-6 py-2 rounded-full text-lg font-black shadow-xl flex items-center gap-2 transition-transform active:scale-95 no-underline focus:outline-none shrink-0 z-50">
🏠 MENÜ
</button>
<div class="absolute inset-0 flex items-center justify-center pointer-events-none z-0">
<h1 class="text-2xl md:text-4xl font-black text-emerald-400 font-mono tracking-wider drop-shadow-[0_4px_4px_rgba(0,0,0,0.8)] uppercase">
&lt;PIXEL&gt;
</h1>
</div>
<button onclick="toggleInfo(); playSound('click')" class="w-12 h-12 bg-slate-800 text-white rounded-full font-bold border-4 border-slate-600 hover:border-white shadow-xl flex items-center justify-center transition-transform active:scale-95 text-xl shrink-0 z-50">
?
</button>
</div>
<div class="flex-1 flex flex-col lg:flex-row items-center justify-center gap-4 min-h-0 w-full max-w-[95rem] mx-auto pb-1">
<div class="relative w-full max-w-[650px] flex-shrink-0 flex items-center justify-center p-1 min-h-0 h-full">
<div id="grid" class="pixel-grid max-h-full"></div>
</div>
<div class="bg-slate-800 p-3 lg:p-4 rounded-[1.5rem] border-4 border-slate-700 flex flex-row lg:flex-col gap-3 shadow-2xl w-full lg:w-auto h-auto lg:h-full justify-between overflow-x-auto lg:overflow-visible lg:overflow-y-auto no-scrollbar">
<div class="grid grid-cols-4 lg:grid-cols-2 gap-2 flex-shrink-0 justify-items-center" id="palette">
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-black border-4 border-slate-600 cursor-pointer active:scale-90 transition ring-4 ring-white shadow-lg" data-color="#000000" onclick="setColor(this)"></div>
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-white border-4 border-slate-600 cursor-pointer active:scale-90 transition shadow-lg" data-color="#ffffff" onclick="setColor(this)"></div>
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-red-500 border-4 border-slate-600 cursor-pointer active:scale-90 transition shadow-lg" data-color="#ef4444" onclick="setColor(this)"></div>
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-blue-500 border-4 border-slate-600 cursor-pointer active:scale-90 transition shadow-lg" data-color="#3b82f6" onclick="setColor(this)"></div>
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-green-500 border-4 border-slate-600 cursor-pointer active:scale-90 transition shadow-lg" data-color="#22c55e" onclick="setColor(this)"></div>
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-yellow-400 border-4 border-slate-600 cursor-pointer active:scale-90 transition shadow-lg" data-color="#facc15" onclick="setColor(this)"></div>
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-purple-500 border-4 border-slate-600 cursor-pointer active:scale-90 transition shadow-lg" data-color="#a855f7" onclick="setColor(this)"></div>
<div class="color-btn w-12 h-12 lg:w-14 lg:h-14 rounded-xl bg-slate-600 border-4 border-slate-500 cursor-pointer active:scale-90 transition flex items-center justify-center text-2xl shadow-lg" data-color="white" onclick="setColor(this)" title="Radierer">🧽</div>
</div>
<div class="h-1 w-full bg-slate-700 my-1 lg:block hidden rounded-full shrink-0"></div>
<div class="w-1 h-full bg-slate-700 mx-2 lg:hidden block rounded-full shrink-0"></div>
<div class="flex flex-col gap-2 w-full min-w-[160px] shrink-0">
<div class="flex gap-2">
<button onclick="downloadArt()" class="flex-1 bg-emerald-600 hover:bg-emerald-500 text-white py-3 px-2 rounded-xl font-black text-base shadow-lg active:translate-y-1 transition border-b-4 border-emerald-800 active:border-b-0 flex items-center justify-center gap-1">💾 SAVE</button>
<button id="btn-print" onclick="window.printArt(this)" class="flex-1 bg-white text-emerald-900 hover:bg-gray-200 py-3 px-2 rounded-xl font-black text-base shadow-lg active:translate-y-1 transition border-b-4 border-gray-300 active:border-b-0 flex items-center justify-center gap-1">🖨️ DRUCK</button>
</div>
<button onclick="clearGrid()" class="bg-slate-700 hover:bg-red-500/80 text-white py-3 px-4 rounded-xl font-bold transition text-base border-b-4 border-slate-900 active:border-b-0 active:translate-y-1 w-full flex items-center justify-center gap-2">🗑️ LÖSCHEN</button>
</div>
</div>
</div>
<div id="info-modal" class="hidden fixed inset-0 z-[200] bg-black/80 backdrop-blur-sm items-center justify-center p-4" onclick="toggleInfo()">
<div class="bg-slate-800 border-4 border-emerald-500 rounded-[2rem] max-w-3xl w-full p-8 shadow-2xl relative" onclick="event.stopPropagation()">
<button onclick="toggleInfo(); playSound('click')" class="absolute top-6 right-6 text-white hover:text-emerald-400 text-4xl font-bold transition"></button>
<h2 class="text-4xl font-black text-white mb-8 border-b border-slate-600 pb-4 flex items-center gap-4"><span class="text-6xl">👾</span> ANLEITUNG</h2>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 text-base">
<div class="p-6 bg-slate-700/50 rounded-2xl border border-slate-600 flex flex-col items-center text-center"><div class="text-4xl mb-4">🎨</div><h3 class="text-emerald-400 font-bold text-xl mb-2">Malen</h3><p class="text-slate-300 leading-snug">Wähle rechts eine <b>Farbe</b> und tippe oder ziehe über die Quadrate.</p></div>
<div class="p-6 bg-slate-700/50 rounded-2xl border border-slate-600 flex flex-col items-center text-center"><div class="text-4xl mb-4">🧽</div><h3 class="text-white font-bold text-xl mb-2">Radieren</h3><p class="text-slate-300 leading-snug">Wähle den <b>Schwamm</b> oder drücke auf "LÖSCHEN", um von vorne zu beginnen.</p></div>
<div class="p-6 bg-slate-700/50 rounded-2xl border border-slate-600 flex flex-col items-center text-center"><div class="text-4xl mb-4">💾</div><h3 class="text-white font-bold text-xl mb-2">Fertig?</h3><p class="text-slate-300 leading-snug">Speichere dein Pixel-Kunstwerk oder drucke es direkt aus.</p></div>
</div>
<button onclick="toggleInfo(); playSound('click')" class="mt-8 w-full bg-emerald-600 hover:bg-emerald-500 text-white font-black py-4 rounded-xl text-xl transition">ALLES KLAR!</button>
</div>
</div>
<div id="print-container" class="hidden"><img id="print-img" src="" alt="Druckvorschau"></div>
<script>
const _soundCache = { 'click': new Audio('../assets/sounds/click.mp3'), 'shutter': new Audio('../assets/sounds/shutter.mp3'), 'success': new Audio('../assets/sounds/success.mp3') };
Object.values(_soundCache).forEach(s => s.load());
window.playSound = function(id) { if (_soundCache[id]) { const s = _soundCache[id].cloneNode(); s.volume = 1.0; s.play().catch(e => console.warn(e)); } };
function playPaintSound() {}
window.goHome = function() { playSound('click'); setTimeout(() => { window.location.href = '../index.html'; }, 300); };
const grid = document.getElementById('grid'); let currentColor = '#000000'; let isDrawing = false; let idleTimer;
function resetIdleTimer() { clearTimeout(idleTimer); idleTimer = setTimeout(() => { window.location.href = '../index.html'; }, 90000); }
['mousedown', 'touchstart', 'scroll', 'keydown', 'input'].forEach(evt => document.addEventListener(evt, resetIdleTimer, {passive: true})); resetIdleTimer();
function toggleInfo() { const m = document.getElementById('info-modal'); m.classList.toggle('hidden'); m.classList.toggle('flex'); }
function initGrid() { grid.innerHTML = ''; for(let i=0; i<256; i++) { const cell = document.createElement('div'); cell.className = 'cell'; cell.addEventListener('mousedown', () => { isDrawing = true; cell.style.backgroundColor = currentColor; playPaintSound(); }); cell.addEventListener('mouseenter', () => { if(isDrawing) { cell.style.backgroundColor = currentColor; } }); cell.addEventListener('touchstart', (e) => { isDrawing = true; cell.style.backgroundColor = currentColor; playPaintSound(); }, {passive: false}); grid.appendChild(cell); } }
grid.addEventListener('touchmove', (e) => { e.preventDefault(); if(!isDrawing) return; const t = e.touches[0]; const el = document.elementFromPoint(t.clientX, t.clientY); if(el && el.classList.contains('cell')) { el.style.backgroundColor = currentColor; } }, {passive: false});
document.body.addEventListener('mouseup', () => isDrawing = false); document.body.addEventListener('touchend', () => isDrawing = false);
function setColor(btn) { playSound('click'); currentColor = btn.getAttribute('data-color'); document.querySelectorAll('.color-btn').forEach(b => b.classList.remove('ring-4', 'ring-white')); btn.classList.add('ring-4', 'ring-white'); }
function clearGrid() { playSound('click'); if(confirm("Wirklich alles löschen?")) { document.querySelectorAll('.cell').forEach(c => c.style.backgroundColor = 'white'); playSound('shutter'); } }
function generateCanvas() { const c = document.createElement('canvas'); const ctx = c.getContext('2d'); const s = 32; c.width = 16 * s; c.height = 16 * s; document.querySelectorAll('.cell').forEach((cell, i) => { const x = (i % 16) * s; const y = Math.floor(i / 16) * s; ctx.fillStyle = cell.style.backgroundColor || 'white'; ctx.fillRect(x, y, s, s); }); return c; }
function downloadArt() { playSound('success'); const c = generateCanvas(); const l = document.createElement('a'); l.download = 'mein-pixel-art.png'; l.href = c.toDataURL(); l.click(); }
window.printArt = async function(el) { playSound('click'); const btn = el || document.getElementById('btn-print'); let oldText = ""; if(btn) { oldText = btn.innerHTML; btn.innerText = "⏳ Sende..."; btn.disabled = true; } const c = generateCanvas(); const d = c.toDataURL(); try { if (window.Capacitor && window.Capacitor.Plugins && window.Capacitor.Plugins.DirectPrinter) { await window.Capacitor.Plugins.DirectPrinter.printBase64({ data: d, name: 'Pixel-Art' }); if(btn) btn.innerText = "✅ Gedruckt!"; playSound('success'); } else { const img = document.getElementById('print-img'); img.src = d; setTimeout(() => { window.print(); }, 100); if(btn) btn.innerText = "✅ OK"; playSound('success'); } } catch (e) { alert("Fehler: " + e.message); if(btn) btn.innerText = "❌ Fehler"; } setTimeout(() => { if(btn) { btn.innerHTML = oldText || '🖨️ <span class="hidden xl:inline">DRUCK</span>'; btn.disabled = false; } }, 3000); }
window.onload = initGrid;
</script>
</body>
</html>