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
@@ -11,23 +11,11 @@ import { existsSync, readdirSync, renameSync } from 'node:fs'
|
||||
// müssen dort physisch funktionieren. Feste Windows-Muster (Katalog,
|
||||
// %ProgramFiles%) bleiben dagegen bei path.win32.
|
||||
import { join } from 'node:path'
|
||||
// EINE Namensregel für Kern und Fenster (5.4.0: die Zielpfad-Vorschau im
|
||||
// Auswahl-Dialog rechnet mit derselben Funktion).
|
||||
import { sichererName, staffelOrdnerName } from '../../gemeinsam/ablagepfad'
|
||||
|
||||
// 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 { sichererName }
|
||||
|
||||
/** Zielordner: sprechender Name; existiert er schon (Disc doppelt
|
||||
* gerippt), wird die Job-Kennung angehängt statt zu überschreiben. */
|
||||
@@ -48,7 +36,7 @@ export function zielordner(
|
||||
/** Jellyfin-Konvention: <basis>/<Serie>/Season NN (pur). */
|
||||
export function serienOrdner(basis: string, serie: string, staffel: number): string {
|
||||
const name = sichererName(serie) || 'Unbekannte Serie'
|
||||
return join(basis, name, `Season ${String(Math.trunc(staffel)).padStart(2, '0')}`)
|
||||
return join(basis, name, staffelOrdnerName(staffel))
|
||||
}
|
||||
|
||||
/** Ordnet Dateien Episoden zu — über Laufzeiten, ordnungserhaltend.
|
||||
|
||||
Reference in New Issue
Block a user