using System.Windows;
using Notification.Core;
namespace ytLive.ViewModels;
///
/// App Settings as a right-edge drawer (creator ruling 2026-11-01): the gear rail tab opens it
/// immediately, in the same exclusive-slide pattern as Stream Settings / YPP / Socials / TEST.
///
/// It is a separate flag from because the overlay shell now
/// only carries Report Bug / Feature Request / About — settings stopped being a modal.
///
public partial class MainViewModel
{
private bool _settingsDrawerOpen;
private NotificationPosition _toastPosition = NotificationPosition.BottomRight;
private bool _stickyAlertsUntilDismissed;
private bool _lockEditWhileLive;
private bool _editingForcedOff;
public bool StickyAlertsUntilDismissed
{
get => _stickyAlertsUntilDismissed;
set
{
if (!SetProperty(ref _stickyAlertsUntilDismissed, value)) return;
_layoutStore.SaveStickyAlertsUntilDismissed(value);
}
}
/// 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.
public bool LockEditWhileLive
{
get => _lockEditWhileLive;
set
{
if (!SetProperty(ref _lockEditWhileLive, value)) return;
_layoutStore.SaveLockEditWhileLive(value);
}
}
///
/// Applies the edit lock when a session starts or stops. Split out so the rule is testable without
/// starting a real broadcast.
///
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;
set
{
if (!IsSupportedToastPosition(value) || !SetProperty(ref _toastPosition, value)) return;
_layoutStore.SaveNotificationPosition(value);
OnPropertyChanged(nameof(ToastAreaMargin));
}
}
public Thickness ToastAreaMargin => ToastPosition switch
{
NotificationPosition.TopLeft => new Thickness(12, 12, 0, 0),
NotificationPosition.TopRight => new Thickness(0, 12, 12, 0),
NotificationPosition.CenterLeft => new Thickness(12, 0, 0, 0),
NotificationPosition.CenterRight => new Thickness(0, 0, 12, 0),
NotificationPosition.BottomLeft => new Thickness(12, 0, 0, 96),
_ => new Thickness(0, 0, 12, 96),
};
private static bool IsSupportedToastPosition(NotificationPosition position)
=> position is NotificationPosition.TopLeft or NotificationPosition.TopRight
or NotificationPosition.CenterLeft or NotificationPosition.CenterRight
or NotificationPosition.BottomLeft or NotificationPosition.BottomRight;
public bool SettingsDrawerOpen
{
get => _settingsDrawerOpen;
private set => SetProperty(ref _settingsDrawerOpen, value);
}
internal void ToggleSettingsDrawer()
{
if (_settingsDrawerOpen)
{
SettingsDrawerOpen = false;
return;
}
// One drawer at a time, like the rail's other tabs.
BroadcastForm.IsDrawerOpen = false;
Ypp.IsDrawerOpen = false;
TestSession.IsDrawerOpen = false;
if (SocialsDrawerOpen) CloseSocialsDrawer();
SettingsDrawerOpen = true;
}
/// Called by the other drawers when they open, so settings yields to them — and by the
/// window's click-outside guard, so the gear tab retracts like every other drawer (2026-11-05).
internal void CloseSettingsDrawerIfOpen()
{
if (_settingsDrawerOpen) SettingsDrawerOpen = false;
}
}