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:
Hitonabi
2026-09-02 17:51:15 +02:00
co-authored by Claude Fable 5.1
parent 6678c81592
commit 3dc6798c79
67 changed files with 6961 additions and 3950 deletions
+62
View File
@@ -0,0 +1,62 @@
// Tests der Fensterlage (haupt/fensterlage.ts, 5.5.0): 80 % des
// Arbeitsbereichs, mittig, Mindestmaß; gemerkte Lage nur, wenn sie noch auf
// einem Bildschirm liegt; Lesen/Schreiben der Datei.
import { mkdtempSync, rmSync, writeFileSync } from 'node:fs'
import { tmpdir } from 'node:os'
import { join } from 'node:path'
import { afterAll, describe, expect, it } from 'vitest'
import { anfangsLage, lageLesen, lageSchreiben, liegtSichtbar, startLage } from '../src/haupt/fensterlage'
const ordner = mkdtempSync(join(tmpdir(), 'rippy-lage-'))
afterAll(() => rmSync(ordner, { recursive: true, force: true }))
describe('startLage', () => {
it('Full HD ohne Taskleiste: 80 % und mittig', () => {
expect(startLage({ x: 0, y: 0, width: 1920, height: 1040 })).toEqual({ x: 192, y: 104, width: 1536, height: 832, maximiert: false })
})
it('kleiner Bildschirm: Mindestmaß 1100 × 720, aber nie größer als der Bildschirm', () => {
expect(startLage({ x: 0, y: 0, width: 1280, height: 720 })).toEqual({ x: 90, y: 0, width: 1100, height: 720, maximiert: false })
expect(startLage({ x: 0, y: 0, width: 1024, height: 600 })).toEqual({ x: 0, y: 0, width: 1024, height: 600, maximiert: false })
})
it('Zweitmonitor rechts: der Versatz des Arbeitsbereichs zählt mit', () => {
const l = startLage({ x: 1920, y: 0, width: 2560, height: 1400 })
expect(l.x).toBe(1920 + 256)
expect(l.width).toBe(2048)
})
})
describe('liegtSichtbar / anfangsLage', () => {
const bildschirme = [
{ x: 0, y: 0, width: 1920, height: 1080 },
{ x: 1920, y: 0, width: 2560, height: 1440 },
]
it('auf einem Bildschirm: ja; im Nirgendwo eines abgestöpselten Monitors: nein', () => {
expect(liegtSichtbar({ x: 100, y: 100, width: 1200, height: 800, maximiert: false }, bildschirme)).toBe(true)
expect(liegtSichtbar({ x: 2500, y: 200, width: 1200, height: 800, maximiert: false }, bildschirme)).toBe(true)
expect(liegtSichtbar({ x: -3000, y: 200, width: 1200, height: 800, maximiert: false }, bildschirme)).toBe(false)
expect(liegtSichtbar({ x: 100, y: 100, width: 300, height: 200, maximiert: false }, bildschirme)).toBe(false)
})
it('anfangsLage: gemerkt, wenn sichtbar — sonst Start', () => {
const arbeit = { x: 0, y: 0, width: 1920, height: 1040 }
const gemerkt = { x: 2000, y: 50, width: 1400, height: 900, maximiert: true }
expect(anfangsLage(gemerkt, arbeit, bildschirme)).toBe(gemerkt)
expect(anfangsLage({ ...gemerkt, x: 9000 }, arbeit, bildschirme)).toEqual(startLage(arbeit))
expect(anfangsLage(null, arbeit, bildschirme)).toEqual(startLage(arbeit))
})
})
describe('lageLesen / lageSchreiben', () => {
it('Runde durch die Datei', () => {
const pfad = join(ordner, 'fenster-lage.json')
lageSchreiben(pfad, { x: 10, y: 20, width: 1300, height: 850, maximiert: true })
expect(lageLesen(pfad)).toEqual({ x: 10, y: 20, width: 1300, height: 850, maximiert: true })
})
it('fehlende oder kaputte Datei heißt Startlage (null)', () => {
expect(lageLesen(join(ordner, 'gibt-es-nicht.json'))).toBeNull()
const kaputt = join(ordner, 'kaputt.json')
writeFileSync(kaputt, '{"x": "zehn"}')
expect(lageLesen(kaputt)).toBeNull()
writeFileSync(kaputt, 'kein json')
expect(lageLesen(kaputt)).toBeNull()
})
})