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>
93 lines
4.0 KiB
TypeScript
93 lines
4.0 KiB
TypeScript
// 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.
|
|
//
|
|
// 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(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({
|
|
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
|
|
// ist weg, Minimieren/Maximieren/Schließen sitzen im UI und gezogen
|
|
// wird an der Kopfzeile (.ziehbar in fenster/stil.css).
|
|
//
|
|
// Wichtig: GRÖSSE ÄNDERN bleibt möglich. Electron setzt für rahmenlose
|
|
// Fenster unter Windows weiterhin WS_THICKFRAME (Option `thickFrame`,
|
|
// Standard true) — die Kanten lassen sich also weiter ziehen, und
|
|
// Doppelklick auf die Ziehfläche maximiert wie gewohnt.
|
|
frame: false,
|
|
// Dunkler Grund SOFORT — sonst blitzt beim Start ein weißes Rechteck,
|
|
// bevor React lädt. Das warme Bühnen-Schwarz des Kino-Mixes
|
|
// (oklch(0.13 0.012 60), siehe fenster/stil.css).
|
|
backgroundColor: '#171412',
|
|
title: 'Rippy',
|
|
webPreferences: {
|
|
preload: join(__dirname, '../bruecke/index.js'),
|
|
contextIsolation: true,
|
|
nodeIntegration: false,
|
|
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)
|
|
|
|
// 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) {
|
|
void fenster.loadURL(startBereich.length > 0 ? `${devUrl}#${startBereich}` : devUrl)
|
|
} else {
|
|
void fenster.loadFile(
|
|
join(__dirname, '../fenster/index.html'),
|
|
startBereich.length > 0 ? { hash: startBereich } : undefined,
|
|
)
|
|
}
|
|
return fenster
|
|
}
|