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
+43 -11
View File
@@ -1,17 +1,29 @@
// Fenster anlegen (KONZEPT § 4.2). Das Fenster zeigt an, sonst nichts —
// kein Node-Zugriff, contextIsolation an, alles läuft über die Brücke
// (src/bruecke) und den MessagePort zum Kern.
// „Zustand merken" (Position/Größe) kommt mit den Einstellungen im UI (W-5).
import { BrowserWindow } from 'electron'
//
// 5.5.0: Die Größe hängt am Bildschirm (fensterlage.ts) — 80 % des
// Arbeitsbereichs beim ersten Start, danach die zuletzt gemerkte Lage,
// sofern sie noch auf einem Bildschirm liegt.
import { BrowserWindow, screen } from 'electron'
import { join } from 'node:path'
import { fensterrandEntfernen } from './fensterrand'
import { anfangsLage, lageLesen, lageSchreiben, MINDEST_BREITE, MINDEST_HOEHE, type Lage } from './fensterlage'
export function fensterErstellen(): BrowserWindow {
export function fensterErstellen(profilOrdner: string): BrowserWindow {
const lageDatei = join(profilOrdner, 'fenster-lage.json')
const lage = anfangsLage(
lageLesen(lageDatei),
screen.getPrimaryDisplay().workArea,
screen.getAllDisplays().map((d) => d.workArea),
)
const fenster = new BrowserWindow({
width: 1280,
height: 820,
minWidth: 860,
minHeight: 560,
x: lage.x,
y: lage.y,
width: lage.width,
height: lage.height,
minWidth: Math.min(MINDEST_BREITE, 860),
minHeight: Math.min(MINDEST_HOEHE, 560),
show: true,
autoHideMenuBar: true,
// Eigene Titelleiste (Commander-Wunsch 01.09.2026): Der Windows-Rahmen
@@ -35,17 +47,37 @@ export function fensterErstellen(): BrowserWindow {
sandbox: true,
},
})
if (lage.maximiert) fenster.maximize()
// Lage merken — verzögert, damit ein Ziehen nicht hundertmal schreibt.
let zeiger: NodeJS.Timeout | null = null
const merken = (): void => {
if (zeiger !== null) clearTimeout(zeiger)
zeiger = setTimeout(() => {
if (fenster.isDestroyed()) return
const maximiert = fenster.isMaximized()
// Im maximierten Zustand die NORMALE Lage behalten (getNormalBounds),
// sonst würde beim nächsten Start ein riesiges Fenster entmaximiert.
const b = maximiert ? fenster.getNormalBounds() : fenster.getBounds()
const neu: Lage = { x: b.x, y: b.y, width: b.width, height: b.height, maximiert }
lageSchreiben(lageDatei, neu)
}, 400)
}
fenster.on('resize', merken)
fenster.on('move', merken)
fenster.on('maximize', merken)
fenster.on('unmaximize', merken)
// electron-vite: Im dev-Modus bedient ein Vite-Server das Fenster
// (ELECTRON_RENDERER_URL), gebaut wird aus out/fenster geladen.
// RIPPY_START_BEREICH öffnet einen bestimmten Bereich (#einstellungen /
// #bibliothek) — der Smoke-Beweis fotografiert damit auch diese Seiten.
// Der DWM-Rand von Windows 11 (die feine helle Linie ums Fenster) — er
// gehört nicht zum Fensterinhalt, mit CSS ist er nicht zu erreichen.
// Ein Fehlschlag ist kein Ausfall: Unter Windows 10 gibt es ihn nicht.
const rand = fensterrandEntfernen(fenster.getNativeWindowHandle())
if (!rand.ok) console.warn(`[haupt] Fensterrand bleibt: ${rand.fehler}`)
// electron-vite: Im dev-Modus bedient ein Vite-Server das Fenster
// (ELECTRON_RENDERER_URL), gebaut wird aus out/fenster geladen.
// RIPPY_START_BEREICH öffnet einen bestimmten Bereich (#einstellungen /
// #einrichtung) — der Smoke-Beweis fotografiert damit auch diese Seiten.
const devUrl = process.env['ELECTRON_RENDERER_URL']
const startBereich = process.env['RIPPY_START_BEREICH'] ?? ''
if (devUrl !== undefined && devUrl.length > 0) {