release: add post-production workspace 0.9.0

This commit is contained in:
hnzio committed 2026-10-30 17:33:13 +01:00
1 parent abc31d920f
commit a6c8606f3c
46 files changed
+10783 -3415

No files matched your search

+137 -43
View File
@@ -21,8 +21,8 @@ spätere API dieselben Regeln verwenden.
## Navigation, Suche und Arbeitsflächen
`+layout.svelte` stellt für angemeldete Nutzer genau die globalen Bereiche Start,
Eingang, Pieces, Streams und Live bereit. Desktop verwendet eine horizontale
`+layout.svelte` stellt für angemeldete Nutzer die globalen Bereiche Start,
Eingang, Pieces, Streams, Live und Post bereit. Desktop verwendet eine horizontale
Kopfzeile, Mobilgeräte eine obere Such-/Kontoleiste und eine Safe-Area-fähige
Bottom-Navigation. `UserMenu.svelte` bündelt Verwaltung, Abmeldung und die weiter
in `localStorage` gespeicherte explizite Auswahl Hell, Dunkel oder System.
@@ -48,11 +48,14 @@ eigener globaler Archivbereich behandelt, sondern von `listShows()` in der
Streamübersicht gefiltert. Der technische `/archiv`-Pfad bleibt für archivierte
und gelöschte Pieces bestehen.
Der Usage-Editor verwendet weiterhin `PieceEditorDialog` und dieselben
Form-Actions. Auf breiten Ansichten öffnet das Dialogelement nicht-modal als
rechte Arbeitsleiste; ohne ausgewählte Usage wird es nicht gerendert. Unterhalb
der mobilen Grenze öffnet dieselbe Komponente modal und nutzt den verfügbaren
Viewport.
`StreamInspector.svelte` ist die dauerhafte rechte Projektion des Streamplans.
Seine flüchtige Auswahl referenziert Show, Abschnitt oder Usage nur über stabile
IDs. Der Standardzustand bearbeitet Show- und Twitch-Metadaten; Abschnitt und
Usage verwenden ihre bestehenden revisionsgeschützten Actions. Die zusätzliche
Action `updateUsageMetadata` liest die aktuelle Usage serverseitig und führt
nicht dargestellte Langtexte, Präsentationswerte, Medien und Werkzeuge in
`updatePieceUsage()` unverändert mit. Ein schmales Clientformular kann private
Felder daher weder versehentlich leeren noch die Geschäftsvalidierung umgehen.
Seit 0.8.1 liest `/suche` die optionalen URL-Filter `type`, `status`, `topic`
und `format` serverseitig. Themen und Formate stammen direkt aus den bestehenden
@@ -60,11 +63,25 @@ Taxonomietabellen; Piece-Filter wirken nicht auf Streams. Die Trefferprojektion
und ihre begrenzten Ausschnitte bleiben unverändert, es entsteht weder ein
Suchindex noch persistenter Filterzustand.
Die Piece-, Planungs- und Live-Arbeitsflächen ändern ausschließlich ihre
Darstellung. Im Streamplan ist der Ablauf die Hauptfläche und die Piece-Auswahl
eine bei Bedarf geöffnete Nebenspalte. Dieselben Formulare, Revisionen,
Drag-Daten, Fokusgrenzen und mobilen Pane-/Sheet-Zustände bleiben die
Interaktionsgrenze.
Die Piece-, Eingangs-, Post-, Planungs- und Live-Arbeitsflächen verwenden eine
gemeinsame Oberflächensprache. Pieces, Eingang und Post teilen die Klasse `unified-workspace`:
links Navigation oder Quellen, mittig die auswählbare Inhaltsprojektion und
rechts `content-quick-inspector` für häufige Felder und Aktionen. Die Auswahl ist
flüchtiger URL- beziehungsweise Browserzustand und erzeugt kein Fachobjekt. Im Streamplan ist der Ablauf die Hauptfläche, der Inspector die
dauerhafte rechte Metadatenspalte und die Piece-Auswahl eine bei Bedarf geöffnete
Nebenspalte. Eine Auswahl schließt diese temporäre Bibliothek. Unterhalb der
Desktopbreite sind Pieces, Ablauf und Details gleichwertige Pane-Zustände.
Revisionen, Drag-Daten und Fokusgrenzen bleiben die Interaktionsgrenze. Live ist
eine reguläre Seite der App-Shell und projiziert Ablauf, Moderationsdokument und
Details ausschließlich lesend. Die lokale Piece-Auswahl und Darstellungsoptionen
ändern weder den tatsächlichen Live-Stand noch Usage-Status, Reihenfolge, Timer
oder öffentliche Ausgabe.
Die gemeinsamen Klassen sind bewusst keine bloße Rasterabstraktion. Pieces und
Post verwenden für linke Kataloge dieselbe `fundus-navigation`-Basis wie Streams
und für rechte Projektionen `stream-inspector` zusammen mit `builder-pane`.
Dadurch bleiben Kopf, Formularrhythmus, Scrollgrenze und Aktionsfuß identisch.
Post ergänzt nur fachliche Felder und eine kompakte Inhaltswerkzeugzeile.
## Laufzeit und Speicher
@@ -95,6 +112,7 @@ technische API. Folgende Grenzen gelten für umgesetzte und spätere Bereiche.
| Freigaben | widerrufbare, gehashte Lesetokens mit Sendung, Umfang, Passwortoption und Ablaufzeit |
| RSS | Feedquellen, Abrufläufe und externe Einträge mit stabiler Herkunfts-ID sowie Status neu/übernommen/verworfen |
| API/Audit | technische Berechtigungen, Idempotenzschlüssel und Audit-Ereignisse mit Akteur, Aktion und Ziel |
| Post | Aufzeichnungsteile, private Markdown-Quellen, revisionierte YouTube-/Clip-/Highlight-Elemente, Thumbnails und valide Exporte |
| Betrieb | Anwendungseinstellungen und spätere Job-Zustände, keine Geheimnisse im Klartext ohne begründete Schutzstrategie |
### Historien- und Kopierregel
@@ -424,9 +442,52 @@ Sendungsroute bindet Mutationen zusätzlich an ihre eigene Sendungs-ID. Die
Verwaltung gruppiert bestehende Freigaben nach Sendung und zeigt deren aktuellen
Status und Termin.
## Postproduktion
`src/lib/server/post.ts` ist die gemeinsame Geschäftsgrenze für den Hauptbereich
`/post`. Jede Übersicht beginnt bei `shows.status = 'completed'`; Post besitzt
keine eigene Sendungsidentität und kann weder Entwürfe noch laufende Streams
nachträglich als abgeschlossen markieren. `post_items` hält gemeinsame Identität,
Typ, Workflowstatus, Herkunft, Position und Revision. Typbezogene 1:1-Tabellen
speichern YouTube-, Social-Clip- oder Twitch-Highlight-Felder.
Migration `0022_post_quick_workbench.sql` ergänzt `social_caption` an
`post_social_clips` und führt vorhandene TikTok-/Instagram-Captions und Hashtags
verlustarm in das gemeinsame Feld über. YouTube Shorts verwendet im aktuellen
Formvertrag ausschließlich `shorts_title`; TikTok und Instagram teilen die
Caption inklusive Hashtags. Die älteren Spalten bleiben für die additive
Migration bestehen, werden von der neuen Oberfläche aber nicht mehr getrennt
bearbeitet.
`post_recording_parts` beschreibt mehrere Teile einer Aufzeichnung. Medienpfade
sind redaktionelle Verweise und müssen für Resolve-Export absolut oder als
`file://` angegeben sein; Framerate und Timebase werden separat validiert.
`post_source_files` speichert Originalinhalt, privaten zufälligen Speichernamen,
SHA-256, Größe sowie ausschließlich aus tatsächlich gefundenen Zeilen abgeleitete
Transkript- und Zeitmarkenprojektionen. `(show_id, sha256)` verhindert Dubletten
innerhalb einer Sendung, ohne Dateien sendungsübergreifend zusammenzuführen.
Kontextdateien und `post_thumbnails` liegen im konfigurierten Uploadverzeichnis.
Die Routen unter `/post/[id]/source` und `/post/[id]/thumbnail` verlangen eine
Redaktionssitzung, prüfen die Zuordnung zur abgeschlossenen Sendung und liefern
private Sicherheitsheader. Originalnamen sind Metadaten und niemals Pfade. Pro
YouTube-Element kann ein Thumbnail ausdrücklich ausgewählt werden.
Exporte unter `/post/[id]/export` lesen dieselbe positiv validierte Projektion.
Resolve-XML benötigt Aufzeichnungspfad, Framerate, Timebase und einen positiven
Start-/Endbereich. SRT wird cueweise vollständig geprüft; unvollständige Daten
führen zu `EXPORT_NOT_READY` statt zu einer scheinbar gültigen Datei. Text- und
JSON-Exporte erzeugen keine externe Veröffentlichung.
`src/lib/server/post-ai.ts` enthält nur Typen für einen später konfigurierbaren
Provideradapter. Es gibt weder Netzwerkaufruf noch automatisch erzeugten Inhalt.
Importierte Quellen und manuelle Bearbeitung bleiben die vollständige
Produktfunktion.
## Oberflächenstruktur
Die Hauptnavigation umfasst Eingang, Fundus, Sendungen, Archiv und Verwaltung.
Die Hauptnavigation umfasst Start, Eingang, Pieces, Streams, Live und Post;
Verwaltung bleibt im Benutzermenü.
Auf dem Desktop liegt sie als feste horizontale Glasleiste oberhalb der
Arbeitsfläche. Bis einschließlich `52rem` ersetzen eine kompakte obere Leiste
und die untere Hauptnavigation diesen Desktopkopf vollständig. Auf breiten
@@ -437,31 +498,34 @@ Die Sendungsübersicht schaltet über zwei gleichwertige Formularaktionen zwisch
Liste und Kalender um. Auf breiten Ansichten erscheint ein siebenspaltiges
Monatsraster ohne Termin-Drag-and-drop; bis `52rem` ersetzt es eine lineare,
touchfreundliche Agenda desselben Monats.
Der Live-Modus ist eine eigene, fokussierte Arbeitsansicht. Die
Präsentationsausgabe verwendet eine separate, strikt reduzierte Datenansicht
ohne interne Anwendungsnavigation.
Die private Route `/live` läuft in derselben authentifizierten App-Shell wie
Streams. Ein Streamkopf zeigt Titel, Termin, Umfang und den expliziten
Nur-Lesen-Zustand. Darunter folgen auf breiten Ansichten Ablauf, Lesedokument und
Details als drei `builder-pane`-/`stream-inspector`-artige Flächen. Bis
einschließlich `72rem` werden diese Bereiche über eine gleichwertige Umschaltung
einzeln gezeigt; bis `52rem` bleiben der kompakte App-Header und die mobile
Bottomnavigation sichtbar.
Die private Route `/live` verwendet ebenfalls einen eigenen authentifizierten
Layoutmodus ohne allgemeine Seitenleiste, mobilen App-Header oder
Bottomnavigation. Ihre Regiefläche belegt die verfügbare Viewporthöhe als Raster
aus fester Statuszeile, unabhängig scrollender Piece- und Ablaufspalte sowie
fester Aktionszeile. Die Breite entscheidet über zwei Spalten oder das mobile
Sheet; eine geringe Desktophöhe verdichtet zusätzlich Abstände und Leisten,
ohne Schrift oder Oberfläche zu skalieren. Unterhalb des schmalen Breakpoints
wird ausschließlich die Ablaufspalte als modales Sheet mit Fokusbegrenzung
eingeblendet; beim Wechsel auf einen breiteren Viewport wird dieser Modalzustand
aufgehoben. Die lokale Betrachtungsnavigation ist keine Live-Action; erst
Präsentieren, Überspringen und Erledigen schreiben den jeweiligen getrennten
Zustand. Die öffentliche `/heinzlive`-Projektion bleibt unverändert. Lokale
Lesepositionen sind an die jeweilige Verwendung gebunden und werden nicht
zwischen Pieces übertragen.
`src/routes/live/+page.server.ts` bietet neben `load` ausschließlich die getrennte
Präsentationsaktion an. Das Auswählen einer Usage, Vor/Zurück, Schriftgröße,
sichtbare Zeiten und das Kopieren von Twitch-Tags bleiben lokaler
Browserzustand. Status-, Fortschritts-, Sortier- und Abschlussänderungen sind
nicht Teil dieser Route. Präsentieren ändert nur `presentation_usage_id` und
damit weder Show-/Usage-Status noch Reihenfolge. Die öffentliche `/heinzlive`-
Projektion und die serverseitigen historischen Live-Dienste bleiben erhalten.
Der Live-Kopf besteht aus zwei regulären Rasterzeilen. Abschnitt und folgendes
Piece sind einzeilig gekürzte, fokussierbare Schaltflächen, die ihren vollständigen
Text lokal aufklappen. Das Regiemenü wird bei Bedarf als fest am Viewport
positionierter Dialog neben dem Kopf gerendert. Dadurch unterliegt es weder dem
Overflow der Regiefläche noch dem durch Glasfilter erzeugten Stacking Context;
seine maximale Höhe bleibt an den Viewport gebunden und intern scrollbar.
Das gemeinsame Arbeitsraster besteht aus einer linken, über Kopf und Inhalt
reichenden Navigation sowie einem rechten Hauptbereich. Dessen freie Kopfzeile
besitzt bewusst keine Pane-Fläche; darunter beginnen Inhalt und optionaler
Inspector. `unified-workspace`, Post-Detail und Live verwenden dieselben
Spaltenwerte `13–16rem / minmax(0, 1fr) / 19–22rem` und `0.85rem` Abstand. Bei
mittleren Breiten folgt der Inspector unter dem Inhalt, mobil übernimmt die
bereichsspezifische Pane-Umschaltung.
Dialog- und Pane-Bewegungen sind reine Oberflächenzustände mit 140–170 ms Dauer.
Der Piece-Dialog animiert Öffnen, explizites Schließen und Backdrop; Disclosure-
Inhalte und mobile Pane-Wechsel blenden kurz ein. Unter
`prefers-reduced-motion: reduce` werden Animationen und Übergänge entfernt.
Icons werden aus dem lokalen Font-Awesome-Classic-Regular-Sprite unter
`static/icons` gerendert. Die Verwaltung lädt zusätzlich die durchsuchbaren
@@ -470,20 +534,50 @@ gleichzeitig. Allgemeine Seiten wie Login oder Navigation laden den Katalog
nicht in ihren Client-Chunk.
Der Fundus ist auf breiten Ansichten ein Raster aus Bibliotheksnavigation,
mittlerer Liste beziehungsweise Piece-Schreibfläche und rechter Kontextspalte.
Kleinere Desktopfenster blenden zuerst den rechten Kontext aus; mobil wird die
Bibliotheksnavigation zur horizontalen Auswahl und im geöffneten Editor ganz
ausgeblendet. URL-Parameter tragen Suche und Filter über den Routenwechsel,
`sessionStorage` ausschließlich die zugehörige flüchtige Listenposition.
mittlerer Liste und rechter Schnellbearbeitung. Kleinere Desktopfenster ordnen
den Inspector unter der Liste an; mobil werden Navigation, Liste und Inspector
gestapelt. URL-Parameter tragen Suche, Filter und ausgewählte Piece-ID über den
Routenwechsel, `sessionStorage` ausschließlich die zugehörige flüchtige
Listenposition. Reduzierte Schnellformulare lesen nicht dargestellte Werte
serverseitig aus dem aktuellen Piece und führen sie unverändert mit.
Der eigenständige Piece-Editor ordnet denselben Formvertrag als redaktionelles
Arbeitsblatt ohne Desktopdialog an. Titel, Einleitung, Moderationsstichpunkte,
Der eigenständige Piece-Editor ordnet denselben Formvertrag als modales
redaktionelles Arbeitsblatt mit eigener URL an. Titel, Einleitung, Moderationsstichpunkte,
Interaktion, Überleitung, private Recherche, Quellen und Werkzeuge bilden die
mittlere Schreibfläche. Status, Dauer, Einordnung, Präsentationsmodi und Medien
liegen auf breiten Ansichten rechts. Alle Werte werden weiterhin gemeinsam über
die bestehende `save`-Action und Piece-Revision gespeichert; separate Bild- und
Präsentationsactions bleiben eigene serverseitige Mutationen.
Der Eingang verwendet dieselbe Darstellung, behält aber zwei Datenarten: neue
`feed_entries` und bereits erzeugte Inbox-Pieces. Die rechte Projektion ruft für
RSS weiterhin ausschließlich Import-/Verwerfactions auf. Post beginnt ebenfalls
in einer dreiteiligen Übersicht; die vollständige Streamzeile und die rechte
Öffnen-Aktion verlinken direkt auf `/post/[id]`. Die Route ist eine normale
Anwendungsseite und übernimmt Seitenkopf, Datumsdarstellung, Feldgeometrie und
responsive Pane-Umschaltung der Streambearbeitung. Darunter stehen
Schnellnavigation, Editor/Übersicht und Inspector. Die linke Navigation
gruppiert YouTube, Social-Clips und Twitch-Highlights und ruft deren Sofortanlage
über dieselbe Post-Action auf. Ohne `item`-Queryparameter bleibt die Auswahl
leer: Die Mitte projiziert alle vorhandenen Post-Inhalte mit Kopieraktionen,
rechts stehen Streamzähler. Mit `item` zeigt dieselbe Mitte den Editor und rechts
dessen Eigenschaften. Mutations-URLs führen `item` mit, damit Upload oder
Speichern die aktuelle Auswahl nicht verlieren.
`createPostItem()` setzt `source_file_id` bereits beim Anlegen, wenn genau eine
Kontextdatei zum Stream existiert. `listPostPieceOptions(showId)` verbindet
`pieces`, `piece_usages` und `show_sections`; dadurch sind nur Original-Pieces
des geöffneten Streams zuordenbar. Editor und Inspector nutzen dieselben Pane-,
Feld- und Aktionsgrundlagen wie der Streamplan. Mobil werden Navigation,
Bearbeitung und Details als drei explizite Pane-Zustände angeboten.
Checkboxen und Radios bleiben im DOM native Formularsteuerungen. Das globale
Stylesheet blendet nur ihre sichtbaren Kästchen aus und projiziert `:checked` und
`:focus-visible` auf das umgebende Label. Damit sind ganze Flächen per Maus,
Touch und Tastatur wählbar, ohne Semantik oder Formübermittlung zu ersetzen. Der
aktive Zustand verwendet wie Post-Navigation und Post-Register den cyanfarbenen
Oberflächenakzent; Gold bleibt Primäraktionen vorbehalten.
`RichMarkdownField` erstellt je sichtbarem Langtext genau eine Tiptap-Instanz mit
StarterKit und offizieller Markdown-Erweiterung. Der Formularwert bleibt rohes
Markdown. Eine Bearbeitung aktualisiert ihn aus `getMarkdown()`, während das