diff --git a/app/web/src/main.js b/app/web/src/main.js index ff1f8c1..64d9b5d 100644 --- a/app/web/src/main.js +++ b/app/web/src/main.js @@ -389,14 +389,11 @@ async function openRecording(id) { const durMs = r.duration_ms || (r.words && r.words.length ? r.words[r.words.length - 1].t_end_ms : 0) || 1; // Draggable module blocks; the saved order wins, unknown/new modules append. - // The transcript is NOT a module: it lives in its own sticky, inner-scrolling - // right column so the (long) text never stretches the page. - const MOD_TITLES = { analyse: 'Zusammenfassung', viz: 'Sprecher-Verlauf', todos: 'ToDos', speakers: 'Sprecher' }; - const mods = { - analyse: ` - ${r.summary ? `

${escapeHtml(r.summary)}

` : '
Noch keine Zusammenfassung.
'} - ${(r.participants && r.participants.length) ? `

Teilnehmer

` : ''}`, - viz: spkOrder.length ? ` + // NOT modules: the transcript (own sticky right column) and the speaker-lane + // visualizer (fixed full-width strip under the player, spanning both columns). + const MOD_TITLES = { analyse: 'Zusammenfassung', todos: 'ToDos', speakers: 'Sprecher' }; + const vizHtml = spkOrder.length ? ` +
${spkOrder.map((sp, i) => ` @@ -410,7 +407,11 @@ async function openRecording(id) {
▶ Abspielen — hier erscheint, was gerade gesprochen wird.
-
Klick in die Spuren springt an die Stelle.
` : '
Keine Sprecherdaten.
', +
` : ''; + const mods = { + analyse: ` + ${r.summary ? `

${escapeHtml(r.summary)}

` : '
Noch keine Zusammenfassung.
'} + ${(r.participants && r.participants.length) ? `

Teilnehmer

` : ''}`, todos: (r.todos && r.todos.length) ? `` : '
Keine ToDos erkannt.
', speakers: spkOrder.length ? `
Namen vergeben → App lernt die Stimme.
@@ -423,7 +424,7 @@ async function openRecording(id) { `).join('')} ` : '', }; - const defOrder = ['analyse', 'viz', 'todos', 'speakers']; + const defOrder = ['analyse', 'todos', 'speakers']; let order = []; try { order = JSON.parse(localStorage.getItem('aime-detail-order') || '[]'); } catch {} order = order.filter(m => mods[m] !== undefined).concat(defOrder.filter(m => !order.includes(m))); @@ -432,6 +433,7 @@ async function openRecording(id) {

${escapeHtml(r.title) || 'Aufnahme #' + r.id} ${analysisBadge(r.analysis_status)}

+ ${vizHtml}
${anaTimeSpan(r) ? `
⏱ Analysezeit: ${anaTimeSpan(r)}
` : ''} ${transcribing ? '
📝 Transkription läuft… lange Aufnahmen dauern (A76-Takt gegen Überhitzung gedrosselt).
' : ''} diff --git a/app/web/src/style.css b/app/web/src/style.css index 184187e..15a86c2 100644 --- a/app/web/src/style.css +++ b/app/web/src/style.css @@ -224,7 +224,11 @@ audio { width: 100%; margin-bottom: 10px; } .mod-body { padding: 12px; } .mod-body h3 { margin: 10px 0 4px; font-size: .9rem; color: var(--muted); } -/* ---- Sprecher-Verlauf: Lanes + Live-Text ---- */ +/* ---- Sprecher-Verlauf: fester Streifen unter dem Player, volle Breite ---- */ +.viz-top { + margin: 4px 0 10px; padding: 10px 12px; background: var(--inset); + border: 1px solid var(--line); border-radius: 12px; +} .viz-wrap { display: flex; gap: 14px; align-items: stretch; } .lanes { flex: 1 1 58%; min-width: 0; position: relative; display: flex; flex-direction: column; gap: 6px; cursor: pointer; } .lane-row { display: flex; align-items: center; gap: 8px; } @@ -247,9 +251,11 @@ audio { width: 100%; margin-bottom: 10px; } background: var(--accent); border-radius: 1px; pointer-events: none; z-index: 2; transition: left .25s linear; } +.lanes { flex: 1 1 66%; } .livebox { - flex: 1 1 42%; min-width: 0; background: var(--surface-2); border-radius: 10px; - padding: 12px; max-height: 200px; overflow-y: auto; align-self: stretch; + flex: 1 1 34%; min-width: 0; background: var(--surface-2); border-radius: 10px; + padding: 10px 12px; max-height: 132px; overflow-y: auto; align-self: stretch; + font-size: 14px; } .live-turn .spk { display: block; font-weight: 650; font-size: 12px; margin-bottom: 4px; } .live-turn.sp0 .spk { color: var(--sp0); } .live-turn.sp1 .spk { color: var(--sp1); } diff --git a/docs/08-changelog.md b/docs/08-changelog.md index beabb04..c6b47e7 100644 --- a/docs/08-changelog.md +++ b/docs/08-changelog.md @@ -3,6 +3,12 @@ Chronik der Entwicklungsschritte. **Regel: jede zukünftige Änderung bekommt hier einen Eintrag** (Datum, Was, Warum, betroffene Dateien/Backups). +## 2026-07-17 — GUI: Sprecher-Verlauf als Vollbreiten-Streifen unter dem Player + +Der Sprecher-Verlauf (Spuren + Live-Text) sitzt jetzt fix unter der Audio-Laufleiste und zieht sich +ueber BEIDE Spalten (oberhalb von Zusammenfassung und Transkript); aus den Drag&Drop-Modulen entfernt. +Lanes ~2/3, Live-Box ~1/3 Breite. Bundle `index-COpkdtd3.js`. + ## 2026-07-17 — GUI: Transkript als eigene Scroll-Spalte Transkript (+ Dialog) aus den Drag&Drop-Modulen herausgelöst: eigene, sticky Spalte rechts neben