Mobile: timed per-track scenes + visual interludes on the remote

Port the Mac app's scene system to the phone control. Each queue entry is
now an independent clone carrying a `cues` list of timed elements (effect /
text / image), each with its own appearance time and visible duration; the
three channels are driven independently from playback progress (advanceCues).
Add visual-only "Intermezzo" queue items (silence audio, run their scene for
a set duration) and make the inter-track gap keep the scene running. New
mobile scene editor lives in the queue card detail (⚙). The queue (with
scenes) is persisted via saveState so it survives a phone reload.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
lucianoandClaude Opus 4.8 committed 2026-06-30 11:29:38 +02:00
1 parent 75627242fe
commit ec4aecaf7c
3 files changed
+330 -40

No files matched your search

+30
View File
@@ -66,6 +66,36 @@ textarea { width: 100%; min-height: 90px; resize: vertical; }
.qgap { display: flex; align-items: center; gap: 6px; margin-top: 8px; font-size: 11px; opacity: .85; }
.qgap input { width: 56px; text-align: center; padding: 6px 4px; }
/* ---- Scene editor (timed elements) ---- */
.lbl .mini { float: right; font-size: 11px; padding: 4px 9px; border-radius: 8px; text-transform: none; letter-spacing: 0; opacity: 1; }
.scbadge { font-style: normal; opacity: .85; margin-left: 2px; }
.scene { margin-top: 10px; border-top: 1px dashed var(--line); padding-top: 9px; }
.sc-title { font-size: 11px; opacity: .8; margin-bottom: 7px; }
.sc-title small { display: block; opacity: .6; font-size: 10px; }
.sc-empty { font-size: 11px; opacity: .55; padding: 6px 0; }
.cue { background: rgba(255,255,255,.04); border: 1px solid var(--line); border-radius: 9px; padding: 7px; margin-bottom: 7px; }
.cue-effect { border-left: 3px solid #8cb6ff; }
.cue-text { border-left: 3px solid #ffd479; }
.cue-image { border-left: 3px solid #9be6a0; }
.cue-head { display: flex; align-items: center; gap: 5px; font-size: 11px; flex-wrap: wrap; }
.cue-head > span:first-child { flex: 1; min-width: 70px; }
.cue-head .cue-at { opacity: .5; }
.cue-head .cue-time { width: 52px; text-align: center; padding: 5px 3px; }
.cue-head .cue-dur { width: 46px; text-align: center; padding: 5px 3px; }
.cue-head .cue-del { padding: 5px 9px; }
.cue-body { margin-top: 7px; display: flex; flex-direction: column; gap: 6px; }
.cue-body input.cue-text { width: 100%; }
.cue-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.cue-row > select { flex: 1; min-width: 0; }
.cue-row > span { font-size: 11px; opacity: .7; }
.cue-row input[type=range] { flex: 1; }
.cue-eff-name, .cue-name { font-size: 11px; opacity: .7; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cue-row .chk { display: flex; align-items: center; gap: 3px; font-size: 11px; flex: 0 0 auto; }
.cue-row .chk input { width: auto; }
.sc-foot { display: flex; gap: 6px; flex-wrap: wrap; }
.sc-foot button { flex: 1; padding: 9px 6px; font-size: 14px; }
.sc-foot .sc-clear { flex: 0 0 auto; }
.nowbar { background: var(--panel); border: 1px solid var(--line); border-radius: 14px; padding: 12px; margin-bottom: 12px; }
.nowbar.hidden { display: none; }
.np-top { display: flex; justify-content: space-between; font-size: 13px; margin-bottom: 6px; }