feat(settings): editing during a session is the creator's call (default: allowed)
Creator ruling 2026-11-12: "we don't care if a creator wants to edit their scene: move stuff around, shrink/grow a webcam view, etc. Why not?" Correct — the app was only ever *forcing* EDIT off at go-live, never enforcing it, so the gun-safety was a habit rather than a rule. App.LockEditWhileLive ships off: a show no longer takes EDIT away. Turning it on restores the old behaviour exactly — go-live flips EDIT off and stop flips it back, and only because the lock took it, so a creator who had already turned EDIT off does not get it handed back on stop. MainViewModel.ApplyEditLockForSession holds the rule so it is testable without starting a broadcast; EditWhileLiveTests covers both settings, the round trip, and the "don't hand it back" case. Settings → Editing carries the checkbox. This is the first slice of TASK 68 (editing while live). 678 pass, 0 warnings. Scope justification: Assets/starting-background.jpg is outside this unit — the creator's replacement art, still awaiting their visual check.
This commit is contained in:
@@ -15,6 +15,8 @@ public partial class MainViewModel
|
||||
private bool _settingsDrawerOpen;
|
||||
private NotificationPosition _toastPosition = NotificationPosition.BottomRight;
|
||||
private bool _stickyAlertsUntilDismissed;
|
||||
private bool _lockEditWhileLive;
|
||||
private bool _editingForcedOff;
|
||||
|
||||
public bool StickyAlertsUntilDismissed
|
||||
{
|
||||
@@ -26,6 +28,43 @@ public partial class MainViewModel
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Lock editing for the duration of a session. Off = edit while live (creator ruling
|
||||
/// 2026-11-12); on = go-live flips EDIT off and stop flips it back, as it always did.</summary>
|
||||
public bool LockEditWhileLive
|
||||
{
|
||||
get => _lockEditWhileLive;
|
||||
set
|
||||
{
|
||||
if (!SetProperty(ref _lockEditWhileLive, value)) return;
|
||||
_layoutStore.SaveLockEditWhileLive(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies the edit lock when a session starts or stops. Split out so the rule is testable without
|
||||
/// starting a real broadcast.
|
||||
/// </summary>
|
||||
internal void ApplyEditLockForSession(bool starting)
|
||||
{
|
||||
if (!LockEditWhileLive)
|
||||
{
|
||||
// The creator may edit during the show; nothing is forced either way.
|
||||
_editingForcedOff = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (starting)
|
||||
{
|
||||
_editingForcedOff = true;
|
||||
EditingActive = false;
|
||||
}
|
||||
else if (_editingForcedOff)
|
||||
{
|
||||
_editingForcedOff = false;
|
||||
EditingActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
public NotificationPosition ToastPosition
|
||||
{
|
||||
get => _toastPosition;
|
||||
|
||||
@@ -298,7 +298,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
// before that (2026-09-25 diagnosis), so chat resolution runs AFTER the pump
|
||||
// starts. Chat is non-fatal — if it fails, the stream continues without chat.
|
||||
LiveScene = StagedScene;
|
||||
EditingActive = false;
|
||||
ApplyEditLockForSession(starting: true);
|
||||
await _framePump.StartAsync(); // never throws; failures log + surface via Failed
|
||||
|
||||
// Check promptly until YouTube confirms the broadcast is live. Health
|
||||
@@ -424,7 +424,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
_sessionStartedAtUtc = null;
|
||||
IsRecording = false;
|
||||
LiveScene = null;
|
||||
EditingActive = true;
|
||||
ApplyEditLockForSession(starting: false);
|
||||
// TASK 41: a stopped test broadcast forgets its drawer session (idempotent)
|
||||
// and drops the TEST face — a test never outlives its run.
|
||||
TestSession.EndTestSilently();
|
||||
|
||||
@@ -347,6 +347,7 @@ public partial class MainViewModel : ViewModelBase
|
||||
_activeLayoutPath = _layoutStore.ActivePath;
|
||||
_toastPosition = _layoutStore.LoadNotificationPosition();
|
||||
_stickyAlertsUntilDismissed = _layoutStore.LoadStickyAlertsUntilDismissed();
|
||||
_lockEditWhileLive = _layoutStore.LoadLockEditWhileLive();
|
||||
_recordFolder = _layoutStore.LoadRecordFolder();
|
||||
|
||||
// What the last few sessions on this tier actually held, if it is worth asking about.
|
||||
|
||||
Reference in New Issue
Block a user