Physarum Native — Audio UI Fix + Default-on-Enable Design Spec¶
Status: Approved · 2026-06-05 · author: Johannes (brainstormed with Claude) Builds on: the audio-reactivity v2 iteration. Two on-device fixes: the route editor UI is broken on iPhone (overlapping controls), and there is no default routing pre-wired.
1. Kontext & Feedback (Gerät, 2026-06-05)¶
- Route-Editor-UI kaputt auf iPhone: die Route-Zeile quetscht 3 Menü-Picker (Quelle/Ziel/Mode) +
Remove + Depth-Slider in eine Zeile; die langen camelCase-Ziel-Labels (
moveSpeed,bloomIntensity) sprengen die compact-Breite und überlappen den Slider. - Kein Default-Routing vor-aktiviert: out-of-the-box reagiert nichts; man muss den „Default"-Knopf finden.
2. Festgezurrte Entscheidungen (Brainstorming 2026-06-05)¶
| Achse | Entscheidung |
|---|---|
| Default-Aktivierung | Auto-apply on first enable. Audio bleibt aus bis der Nutzer „Enabled" antippt; in dem Moment, falls routes.isEmpty, werden die 5 Default-Routen + autoGain=true automatisch gesetzt → reagiert sofort. Kein Mic beim App-Start. Der „Default"-Knopf bleibt (re-apply). |
| Route-Editor | 2-Zeilen-Karte je Route. Zeile 1: Quelle-Picker · „→" · Ziel-Picker (kurze Labels) · Remove (rechts). Zeile 2: Mode (segmented Lvl/Trans) · Depth-Slider · Wert. Nichts überläuft. |
| Kurze Ziel-Labels | moveSpeed→Move, turnSpeed→Turn, depositAmount→Deposit, sensorDistance→Sensor, rhythmAmplitude→Rhythm, chaosStrength→Chaos, exposure→Expo, bloomIntensity→Bloom, saturation→Sat, contrast→Contr. |
3. Komponenten¶
3.1 AppState — geteilte Default-Routen + auto-on-enable¶
- Faktor die 5 Default-Routen in eine statische Quelle:
static let defaultAudioRoutes: [AudioRoute] = [...](die exakten 5 aus der Iteration: bass/transient→bloom 1.2, bass/transient→move 0.8, high/transient→exposure 0.6, mid/transient→chaos 0.7, mid/level→saturation 0.4).applyDefaultAudioWiring()nutzt diese Liste. - Neue Methode
setAudioEnabled(_ on: Bool):pushUndo(); wennon && edited.audioReactive.routes.isEmpty→edited.audioReactive.routes = Self.defaultAudioRoutes; edited.audioReactive.autoGain = true; dannedited.audioReactive.enabled = on. (Wenn schon Routen da sind, nurenabledsetzen — der Nutzer hat bereits eine Konfiguration.)
3.2 AudioReactiveSection — Enable-Toggle nutzt setAudioEnabled¶
Der „Enabled"-Toggle ruft state.setAudioEnabled($0) statt direkt edited.audioReactive.enabled = $0.
(Auto-fill der Routen bei erstem Enable.)
3.3 AudioReactiveSection.routeRow — 2-Zeilen-Karten-Redesign¶
Ersetze die einzeilige HStack { sourcePicker; targetPicker; modePicker; remove } + Slider durch:
VStack(spacing: s1) {
HStack { sourcePicker(.menu, kompakt) ; Image("arrow.right") ; targetPicker(.menu, kurzes Label) ; Spacer() ; removeButton }
HStack { modePicker(.segmented Lvl/Trans, feste Breite ~120) ; depthSlider ; valueText("%+.1f") }
}
.padding(.vertical, s1)
.background(Theme.Colors.overlay, in RoundedRectangle) // dezente Karte
shortTarget(_:)-Helper) statt $0.rawValue.
- Mode-Picker wird .segmented (statt .menu) — „Lvl"/„Trans", kompakt.
- Alle bestehenden Bounds-Guards in den Bindings bleiben (kein OOB-Crash bei Remove).
- Depth-Wert dezent rechts (String(format: "%+.1f", depth)).
4. Testing & Verifikation¶
- Unit:
setAudioEnabled(true)auf leeren Routen → 5 Default-Routen + autoGain + enabled;setAudioEnabled(true)mit vorhandenen Routen → Routen unverändert, nur enabled;setAudioEnabled(false)→ enabled=false, Routen unangetastet.AppState.defaultAudioRoutes== die 5 erwarteten (Tabelle). - Build + Sim-Screenshot: Route-Editor-Karten korrekt gelayoutet (kein Überlauf) auf iPhone-Sim; Engine
swift test+ App-Suite grün. - Gerät (Johannes): „Enabled" antippen → 5 Routen erscheinen + reagiert; die Route-Karten sauber lesbar; Mode-Segmented + Depth-Slider bedienbar.
- Gate: App-Suite grün; macOS + iOS-Sim BUILD SUCCEEDED; aufs iPhone deployed.
5. Out-of-scope / Risiken¶
- Kein Mic-on-launch (bewusst — Permission/Akku/App-Store). Audio-Feel-Tuning (Silence-Gate, Over-Boost) bleibt separat.
- Drag-Reorder der Routen, Custom-Depth-Eingabe → später.
- Die
id: \.offset-ForEach + Bounds-Guards bleiben (kein Identifiable-Umbau vonAudioRoute).