feat: Offline-Bibliothek + Download-only-Modus

Neuer Modus in der GUI: Image nur herunterladen und dauerhaft unter
./downloads/library/ ablegen, ohne USB-Stick. Baut sich so vorab eine
komplette Offline-Sammlung aller macOS-Versionen auf (z.B. auf externe
Platte kopierbar). Stick-Jobs pruefen jetzt IMMER zuerst die lokale
Bibliothek und ueberspringen den Download bei Treffer -- jeder normale
Stick-Bau traegt so nebenbei zur Bibliothek bei.

Backend: installer.py bekommt job_type (stick|download), persistente
Downloads in library/<name>/ mit meta.json + atomarem .part-Rename,
neue /api/library. Frontend: Modus-Umschalter, Bibliotheks-Status,
Offline-Badges in der Versionsliste.

Live getestet auf aria-wohnung: Container neu gebaut, Katalog laedt 37
Installer, Download-Job End-to-End ueber die echte API (Cache-Miss dann
Cache-Hit verifiziert), Stick-Job-Validierung weiterhin intakt.
This commit is contained in:
ARIA
2026-07-18 10:58:55 +02:00
parent 40964b9130
commit 5c2cdd7543
6 changed files with 307 additions and 46 deletions
+20 -5
View File
@@ -13,6 +13,18 @@
</header>
<main>
<section class="card">
<div class="card-head">
<h2>Modus</h2>
</div>
<div class="mode-toggle">
<button id="modeStick" class="mode-btn active" type="button">Auf USB-Stick schreiben</button>
<button id="modeDownload" class="mode-btn" type="button">Nur herunterladen (Offline-Bibliothek)</button>
</div>
<p class="detail">Im Download-Modus wird das Original-Image dauerhaft unter <code>./downloads/library/</code> im Projektordner abgelegt &mdash; ideal um sich vorab eine komplette Offline-Sammlung aller macOS-Versionen aufzubauen (z.B. auf eine externe Platte), die auch ganz ohne Internet zum Stick-Bauen reicht. Ein Stick-Bau nutzt automatisch bereits heruntergeladene Images wieder, statt sie erneut zu laden.</p>
<div id="libraryStatus" class="status"></div>
</section>
<section class="card">
<div class="card-head">
<h2>1. macOS-Version</h2>
@@ -23,7 +35,7 @@
<p id="versionDetail" class="detail"></p>
</section>
<section class="card">
<section class="card" id="deviceSection">
<div class="card-head">
<h2>2. USB-Stick</h2>
<button id="refreshDevices" class="btn-ghost">neu scannen</button>
@@ -32,10 +44,13 @@
</section>
<section class="card">
<h2>3. Bestaetigen &amp; Schreiben</h2>
<p class="warn">ACHTUNG: Der gesamte Inhalt des gewaehlten Sticks wird geloescht.</p>
<label>Tippe den Geraete-Pfad zur Bestaetigung ein (z.B. <code>/dev/sdb</code>):</label>
<input type="text" id="confirmPath" placeholder="/dev/sdX">
<h2 id="step3Title">3. Bestaetigen &amp; Schreiben</h2>
<div id="stickConfirm">
<p class="warn">ACHTUNG: Der gesamte Inhalt des gewaehlten Sticks wird geloescht.</p>
<label>Tippe den Geraete-Pfad zur Bestaetigung ein (z.B. <code>/dev/sdb</code>):</label>
<input type="text" id="confirmPath" placeholder="/dev/sdX">
</div>
<p id="downloadHint" class="detail" style="display:none">Laedt das Original-Image herunter und legt es dauerhaft in der lokalen Bibliothek ab. Kein Stick noetig, nichts wird geloescht.</p>
<button id="startBtn" disabled>Stick erstellen</button>
</section>