feat(v5): Oberflaeche 5.4.0 — Sprachen je Titel, Staffel/Folge, Vorschau, Kino-Banner v2, Roh-Dateien, Warteschlange
WAS: Der Auswahl-Dialog zeigt je Titel die gemessenen Ton- und Untertitelspuren als Chips (vorbelegt aus der Einstellung, sonst alles, was der Titel hat), Felder fuer Staffel und erste Folge, und zwei Zeilen Zielpfad-Vorschau (gemeinsam/ablagepfad.ts — dieselbe Namensregel wie der Kern). Die Dialoge leben jetzt im App-Zustand statt in der Kachel: ein leerer Takt der Wache raeumte sonst Kachel UND Dialog ab. Die Laufwerks-Kachel ist das Kino-Banner v2: Logo statt Text, Tagline, Zeile Jahr/FSK/Laufzeit/Genre/Bewertung, Darsteller-Streifen, die Hinweise der Nachpruefung, ein Knopf „Laufwerk pruefen" mit Urteil aus dem Windows-Protokoll, und nach dem Rip der Stand der Kompression. Neu in der Uebersicht: die Kompressions-Karte (laeuft/wartet, Abbruch). Neu in den Einstellungen: „Roh-Dateien" mit Regel, Belegung, jedem Vorgang (Neu komprimieren mit Preset, Roh loeschen) und Ordnern ohne Vorgang; der Auswurf-Schalter in „Ablage"; der Datenbank-Pfad unter „Programm". Das Haupt zeigt die Kompression in Taskleiste und Tray und laesst Updates auch auf sie warten. Playwright kommt als Bau-Werkzeug dazu (Commander-Ja nach Regel B; MIT, wird nicht ausgeliefert). Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
3f7f962dff
commit
e3ce8220f1
@@ -0,0 +1,74 @@
|
||||
// Ablage-Namen und die Zielpfad-Vorschau — PUR, ohne Dateisystem, damit
|
||||
// Kern UND Fenster dieselbe Regel benutzen (5.4.0: „Vorschau, welche Datei
|
||||
// landet wo" im Auswahl-Dialog). Die Kern-Seite (kern/ablage/struktur.ts)
|
||||
// baut auf diesen Namen ihre echten Ordner.
|
||||
|
||||
// Zeichen, die in Ordnernamen auf SMB/NTFS/ext4 Ärger machen.
|
||||
// eslint-Hinweis unnötig: bewusst inklusive Steuerzeichen.
|
||||
// eslint-disable-next-line no-control-regex
|
||||
const VERBOTEN = /[<>:"/\\|?*\x00-\x1f]/g
|
||||
|
||||
/** Titel → dateisystem-tauglicher Ordnername (pur). */
|
||||
export function sichererName(titel: string, jahr?: number | string | null): string {
|
||||
let name = (titel ?? '').replace(VERBOTEN, '').trim().replace(/\.+$/, '')
|
||||
name = name.replace(/\s+/g, ' ').slice(0, 150).trim()
|
||||
if (name.length === 0) return ''
|
||||
// Kein doppeltes Jahr: OMDb-Titel tragen es teils schon im Namen.
|
||||
if (jahr !== undefined && jahr !== null && String(jahr).length > 0 && !name.endsWith(`(${jahr})`)) {
|
||||
name = `${name} (${jahr})`
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
export function staffelOrdnerName(staffel: number): string {
|
||||
return `Season ${String(Math.trunc(staffel)).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
export function folgenDateiname(serie: string, staffel: number, folge: number): string {
|
||||
const s = String(Math.trunc(staffel)).padStart(2, '0')
|
||||
const e = String(Math.trunc(folge)).padStart(2, '0')
|
||||
return `${sichererName(serie) || 'Serie'} S${s}E${e}.mkv`
|
||||
}
|
||||
|
||||
export interface VorschauEingabe {
|
||||
ablage: string
|
||||
alsSerie: boolean
|
||||
titel: string
|
||||
jahr: number | null
|
||||
staffel: number | null
|
||||
ersteFolge: number | null
|
||||
/** Zahl der gewählten Folgen (Serie) bzw. Hauptfilme (Film). */
|
||||
hauptTitel: number
|
||||
extras: number
|
||||
/** Der Vorgangsname — gilt, wenn kein Titel erkannt ist. */
|
||||
vorgangsName: string
|
||||
}
|
||||
|
||||
/** Zwei Zeilen: Zielordner und was darin landet (pur). Windows-Trenner,
|
||||
* weil die Vorschau eine Windows-Ablage beschreibt. */
|
||||
export function zielVorschau(e: VorschauEingabe): [string, string] {
|
||||
const wurzel = e.ablage.replace(/[\\/]+$/, '')
|
||||
const titel = e.titel.trim().length > 0 ? e.titel.trim() : e.vorgangsName
|
||||
if (e.alsSerie) {
|
||||
const staffel = e.staffel ?? 1
|
||||
const ordner = `${wurzel}\\Serien\\${sichererName(titel) || 'Unbekannte Serie'}\\${staffelOrdnerName(staffel)}\\`
|
||||
const n = Math.max(1, e.hauptTitel)
|
||||
let inhalt: string
|
||||
if (e.ersteFolge !== null && e.ersteFolge > 0) {
|
||||
const erste = folgenDateiname(titel, staffel, e.ersteFolge)
|
||||
inhalt =
|
||||
n === 1
|
||||
? erste
|
||||
: `${erste} … ${folgenDateiname(titel, staffel, e.ersteFolge + n - 1)} (${n} Folgen, fortlaufend)`
|
||||
} else {
|
||||
inhalt = `${n} ${n === 1 ? 'Folge' : 'Folgen'} — Nummern aus den TMDb-Laufzeiten, sonst bleiben die MakeMKV-Namen`
|
||||
}
|
||||
if (e.extras > 0) inhalt += ` · extras\\ (${e.extras})`
|
||||
return [ordner, inhalt]
|
||||
}
|
||||
const ordner = `${wurzel}\\Filme\\${sichererName(titel, e.jahr) || e.vorgangsName}\\`
|
||||
const teile: string[] = []
|
||||
if (e.hauptTitel > 0) teile.push(e.hauptTitel === 1 ? 'der Hauptfilm' : `${e.hauptTitel} Hauptfilme`)
|
||||
if (e.extras > 0) teile.push(`extras\\ (${e.extras} ${e.extras === 1 ? 'Zugabe' : 'Zugaben'})`)
|
||||
return [ordner, teile.length > 0 ? teile.join(' · ') : 'nichts gewählt']
|
||||
}
|
||||
Reference in New Issue
Block a user