fix(gui): Ventilator-Icon und Speicheranzeige auf Aufnahme-Vorrat

Das erste Icon las sich als Kleeblatt. Jetzt vier gebogene Pinwheel-Fluegel
in einem feststehenden Gehaeusering; nur die Fluegel drehen. Form vorab ohne
Browser geprueft (lab/preview_fan.py rendert die Bezier-Kandidaten als PNG).

Die Prozentzahl misst nicht mehr die Partition, sondern den Aufnahme-Vorrat:
100 % = freier Platz + alle Audiodateien unter recordings/, belegt = diese
Dateien. System, Modelle und node_modules fallen aus Zaehler und Nenner
heraus; der df-Wert steht als Fusszeile in der Klappkarte.

sysstat.js scannt recordings/ per readdir+stat (kein du-Prozess) und puffert
60 s; status() ist dadurch async, die Route laeuft ueber wrap().

Doku: Kapitel 07 + Changelog.
This commit is contained in:
Claude
2026-08-17 22:03:17 +02:00
parent 47288c0479
commit db50c9616d
7 changed files with 215 additions and 43 deletions
+23 -12
View File
@@ -83,8 +83,11 @@ function render() {
// Zahlen auf (CPU, RAM, Temperatur bzw. belegt/frei/gesamt).
const sysmon = { timer: null, last: null };
const TURBINE_BLADES = [0, 72, 144, 216, 288].map(a =>
`<path transform="rotate(${a} 12 12)" d="M12 12 C10.1 8.7 9.9 5.2 12 2.3 C14.1 5.2 13.9 8.7 12 12 Z"/>`).join('');
// Ventilator: vier gebogene Flügel im feststehenden Gehäusering. Nur die
// Flügelgruppe dreht sich, der Ring bleibt stehen — sonst sähe man die
// Drehung am runden Gehäuse gar nicht.
const FAN_BLADES = [0, 90, 180, 270].map(a =>
`<path transform="rotate(${a} 12 12)" d="M12 12 C11.4 8.6 11.4 5.4 12.7 3.1 C15.6 4.2 18.2 6.6 18.9 9.4 C17.2 11.2 14.6 12 12 12 Z"/>`).join('');
function sysmonMarkup() {
return `
@@ -96,16 +99,20 @@ function sysmonMarkup() {
</svg>
<span class="sys-val mono" data-disk-pct>–</span>
<div class="sys-pop">
<div class="sys-pop-h">Speicherplatz</div>
<div class="sys-row"><span>Belegt</span><b data-disk-used>–</b></div>
<div class="sys-row"><span>Frei</span><b data-disk-free>–</b></div>
<div class="sys-row"><span>Gesamt</span><b data-disk-total>–</b></div>
<div class="sys-pop-h">Speicher für Aufnahmen</div>
<div class="sys-row"><span>Aufnahmen</span><b data-disk-used>–</b></div>
<div class="sys-bar"><i data-disk-bar style="width:0%"></i></div>
<div class="sys-row"><span>Noch frei</span><b data-disk-free>–</b></div>
<div class="sys-row"><span>Gesamt für Aufnahmen</span><b data-disk-total>–</b></div>
<div class="sys-note">100 % = freier Platz + alle vorhandenen Aufnahmen<br>(also der Platz eines frisch aufgesetzten Systems)</div>
<div class="sys-row sys-sub"><span>Partition gesamt</span><b data-disk-part>–</b></div>
</div>
</div>
<div class="sys-chip" id="sysload" tabindex="0" role="group" aria-label="Systemlast">
<svg class="turbine" viewBox="0 0 24 24" aria-hidden="true" data-turbine>
<g class="tb-blades">${TURBINE_BLADES}</g>
<circle class="tb-hub" cx="12" cy="12" r="2.2"/>
<svg class="fan" viewBox="0 0 24 24" aria-hidden="true">
<circle class="fan-case" cx="12" cy="12" r="10.4"/>
<g class="fan-blades" data-turbine>${FAN_BLADES}</g>
<circle class="fan-hub" cx="12" cy="12" r="2.1"/>
</svg>
<div class="sys-pop">
<div class="sys-pop-h">Systemlast</div>
@@ -142,15 +149,19 @@ function paintSysmon(s) {
}
if (s.disk) {
// Prozent = Aufnahmen / (freier Platz + Aufnahmen). Das System selbst zählt
// bewusst nicht mit: gezeigt wird, wie viel vom Aufnahme-Vorrat weg ist.
const p = Math.round(s.disk.usedPct);
disk.className = 'sys-chip ' + sysLevel(p);
disk.title = `Speicher ${p} % belegt`;
disk.title = `Aufnahmen belegen ${p} % des verfügbaren Platzes`;
set('[data-disk-pct]', p + '%');
const ring = document.querySelector('[data-disk-ring]');
if (ring) ring.setAttribute('stroke-dasharray', `${Math.max(0, Math.min(100, s.disk.usedPct)).toFixed(1)} 100`);
set('[data-disk-used]', sysGb(s.disk.usedBytes));
const db = document.querySelector('[data-disk-bar]'); if (db) db.style.width = Math.min(100, s.disk.usedPct) + '%';
set('[data-disk-used]', `${sysGb(s.disk.recBytes)}${s.disk.recFiles ? ` (${s.disk.recFiles} Dateien)` : ''}`);
set('[data-disk-free]', sysGb(s.disk.freeBytes));
set('[data-disk-total]', sysGb(s.disk.totalBytes));
set('[data-disk-total]', sysGb(s.disk.budgetBytes));
set('[data-disk-part]', `${sysGb(s.disk.totalBytes)} — ${Math.round(s.disk.partPct)} % belegt`);
}
const cpu = s.cpu ? s.cpu.pct : 0;