feat(v5): 5.5.0 — Kern und Oberfläche aufgeteilt, Übersicht und Einstellungen neu, Erst-Einrichtung mit Poster-Kulisse
Commander-Wünsche vom 02.09.2026 vor der Freigabe von 5.4.0 (die deshalb nie veröffentlicht wurde): Kern: kern/index.ts ist nur noch Bootstrap und Router; Dienste in kern/dienste/ (Einstellungen, Werkzeuge, Laufwerke, Erkennung, Vorgänge, Speicher, Benachrichtigung, Automatik), Kontext in kern/kontext.ts, Protokoll-Datei in gemeinsam/protokoll.ts, Platz-Rechnung in gemeinsam/platz.ts. Oberfläche: fenster/App.tsx ist nur noch der Rahmen; bausteine.tsx, dialoge/, uebersicht/ (LaufwerkKachel, KompressionsKarte, SpeicherKarte, VerlaufKarte), einstellungen/ (Karten je Funktion, SprachAuswahl), einrichtung/ (ErstEinrichtung, PosterHintergrund). Neu: Bibliothek weg, dafür Verlauf; Speicher-und-Bilanz-Karte (statfs); LED-Fußleiste; MakeMKV-Kopf in die Einstellungen; Sprach-Chips mit Dropdown statt Allgemeinem Preset; Karten Automatik/Benachrichtigung/Allgemein/Update; Durchsuchen bei Werkzeugen; Arbeitsordner lokal (Encode dort, dann in die Ablage); Platz-Prüfung vor dem Rip (Dialog und Kern); Automatik mit Countdown; Serien-Merker über Discs; Rettungs-Abbild mit Nullen nur nach gesehenen Lesefehlern (kern/rip/rettung.ts, Phase rettet, iso:-Quelle); Warteschlange pausieren; Discord/Telegram-Benachrichtigung; Protokoll-Datei je Tag; Fensterlage 80 % mittig, gemerkt; Erst-Einrichtung in acht Schritten vor dem Poster-Grid. Beweise: 413 Tests (neu: speicher, benachrichtigung, automatik, rettung, fensterlage, protokoll, kleinkram-550), drei Typprüfungen, Klick-Beweis mit 29 Schritten inklusive Erst-Einrichtung (zweiter Start mit RIPPY_START_BEREICH=einrichtung), Bilder beweise/klick/01…09. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
6678c81592
commit
3dc6798c79
@@ -0,0 +1,86 @@
|
||||
// Speicher und Statistik in der Übersicht (5.5.0, Commander: „Ist mir zu
|
||||
// leer … wie viel Speicher noch auf dem Server oder auf dem Arbeitsordner
|
||||
// frei ist"). Gemessen im Kern mit fs.statfs — lokal wie auf der Freigabe.
|
||||
import type { SpeicherPlatz, SpeicherStand, Statistik } from '../../gemeinsam/nachrichten'
|
||||
import { FuellBalken, dauerGrob, gbKurz } from '../bausteine'
|
||||
import { speicherLaden } from '../kernverbindung'
|
||||
|
||||
/** Ab hier wird gewarnt: eine Blu-ray braucht rund 50 GB (Roh + Kompression). */
|
||||
export const WENIG_FREI_BYTES = 60e9
|
||||
export const SEHR_WENIG_FREI_BYTES = 20e9
|
||||
|
||||
function Platz({ name, platz, hinweis }: { name: string; platz: SpeicherPlatz; hinweis: string }) {
|
||||
const ton = !platz.ok ? 'rot' : platz.freiBytes < SEHR_WENIG_FREI_BYTES ? 'rot' : platz.freiBytes < WENIG_FREI_BYTES ? 'warn' : 'gold'
|
||||
const belegt = platz.ok && platz.gesamtBytes > 0 ? 1 - platz.freiBytes / platz.gesamtBytes : 0
|
||||
return (
|
||||
<div className="rounded-xl border border-white/8 bg-samt/50 p-3">
|
||||
<div className="flex items-baseline justify-between gap-3">
|
||||
<span className="font-mono text-[10px] tracking-[0.14em] text-nebel">{name}</span>
|
||||
<span className={`font-mono text-[13px] font-semibold ${ton === 'rot' ? 'text-rot' : ton === 'warn' ? 'text-warn' : 'text-schnee'}`}>
|
||||
{platz.ok ? `${gbKurz(platz.freiBytes)} frei` : 'nicht messbar'}
|
||||
</span>
|
||||
</div>
|
||||
<div className="mt-2">
|
||||
<FuellBalken anteil={belegt} ton={ton} />
|
||||
</div>
|
||||
<p className="mt-1.5 break-all font-mono text-[10.5px] text-nebel" title={platz.pfad}>
|
||||
{platz.pfad}
|
||||
{platz.ok && ` · ${gbKurz(platz.gesamtBytes)} gesamt`}
|
||||
{!platz.ok && platz.fehler.length > 0 && ` · ${platz.fehler}`}
|
||||
</p>
|
||||
<div className="mt-1.5 flex flex-wrap items-center gap-2">
|
||||
<span className="text-[10.5px] text-nebel/80">{hinweis}</span>
|
||||
{platz.ok && (
|
||||
<button onClick={() => void window.rippy.ordnerOeffnen(platz.pfad)} className="ml-auto font-mono text-[10.5px] text-nebel hover:text-dunst" title="Im Explorer zeigen">
|
||||
Ordner öffnen
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export function SpeicherKarte({ speicher, statistik }: { speicher: SpeicherStand | null; statistik: Statistik | null }) {
|
||||
return (
|
||||
<div className="rounded-2xl border border-white/10 bg-karte/50 p-5">
|
||||
<div className="flex items-center gap-2.5 font-mono text-[10.5px] tracking-[0.12em] text-nebel">
|
||||
<span className="text-dunst">SPEICHER UND BILANZ</span>
|
||||
<button onClick={() => speicherLaden()} className="ml-auto font-mono text-[10.5px] text-nebel hover:text-dunst" title="Jetzt neu messen">
|
||||
neu messen
|
||||
</button>
|
||||
</div>
|
||||
{speicher === null ? (
|
||||
<p className="mt-3 font-mono text-xs text-nebel">wird gemessen …</p>
|
||||
) : (
|
||||
<div className={`mt-3 grid gap-3 ${speicher.getrennt ? 'sm:grid-cols-2' : ''}`}>
|
||||
{speicher.getrennt ? (
|
||||
<>
|
||||
<Platz name="ARBEITSORDNER (LOKAL)" platz={speicher.arbeit} hinweis="Roh-Dateien und Kompression — eine Blu-ray braucht rund 50 GB." />
|
||||
<Platz name="ABLAGE (SERVER)" platz={speicher.ablage} hinweis="Fertige Filme, Serien und Musik." />
|
||||
</>
|
||||
) : (
|
||||
<Platz name="ABLAGE UND ARBEIT" platz={speicher.ablage} hinweis="Roh-Dateien, Kompression und Fertiges am selben Ort — ein eigener Arbeitsordner geht unter Einstellungen → Ablage." />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
{statistik !== null && statistik.discs > 0 && (
|
||||
<div className="mt-3 grid grid-cols-2 gap-2.5 sm:grid-cols-4">
|
||||
<Zahl label="DISCS" wert={String(statistik.discs)} zusatz={`${statistik.fertige} fertig`} />
|
||||
<Zahl label="VERLUSTFREI GESICHERT" wert={gbKurz(statistik.rohBytes)} zusatz="Summe aller Rips" />
|
||||
<Zahl label="FERTIG ABGELEGT" wert={gbKurz(statistik.fertigBytes)} zusatz="komprimiert oder verschoben" />
|
||||
<Zahl label="JE DISC" wert={statistik.fertige > 0 ? dauerGrob(statistik.dauerS / statistik.fertige) : '—'} zusatz="Rip bis Ablage, im Schnitt" />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function Zahl({ label, wert, zusatz }: { label: string; wert: string; zusatz: string }) {
|
||||
return (
|
||||
<div className="rounded-lg border border-white/10 bg-samt/70 px-3 py-2">
|
||||
<div className="font-mono text-[9px] tracking-[0.14em] text-nebel">{label}</div>
|
||||
<div className="mt-0.5 font-display text-[19px] font-bold leading-tight text-gold-hell">{wert}</div>
|
||||
<div className="font-mono text-[10px] text-nebel/80">{zusatz}</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user