fix(theater): auto-exit Theater Mode when both visualizer subsystems are disabled

Adds CoerceTheaterMode() to WaveformVisualizerControlState; ToggleLava/ToggleWaveform
call it before NotifyChanged so all observers see consistent state in one Changed cycle.
Covers the dead-end escape route bug (Phase 20 review finding).
This commit is contained in:
daniel-c-harvey
2026-06-20 22:03:39 -04:00
parent fa01b9c8e0
commit 14f3af41e4
3 changed files with 106 additions and 0 deletions
@@ -226,12 +226,14 @@
private void ToggleLava()
{
ControlState.LavaEnabled = !ControlState.LavaEnabled;
ControlState.CoerceTheaterMode();
ControlState.NotifyChanged();
}
private void ToggleWaveform()
{
ControlState.WaveformEnabled = !ControlState.WaveformEnabled;
ControlState.CoerceTheaterMode();
ControlState.NotifyChanged();
}
@@ -160,6 +160,19 @@ public sealed class WaveformVisualizerControlState
/// </summary>
public event Action? Changed;
/// <summary>
/// Enforces the Theater-Mode invariant: Theater Mode cannot remain on when both visualizer
/// subsystems are off (there is nothing to go to theater FOR). Call this after mutating
/// <see cref="LavaEnabled"/> or <see cref="WaveformEnabled"/> and before
/// <see cref="NotifyChanged"/> so all observers see a consistent, coerced state in the same
/// <see cref="Changed"/> cycle.
/// </summary>
public void CoerceTheaterMode()
{
if (TheaterMode && !LavaEnabled && !WaveformEnabled)
TheaterMode = false;
}
/// <summary>Raise <see cref="Changed"/>. Called by the controls component after mutating a value.</summary>
public void NotifyChanged() => Changed?.Invoke();
}