using System.Windows.Input; using ytLive.Helpers; namespace ytLive.ViewModels; /// Which half of the top bar's dual segment is in force. public enum BarWorld { /// Build Scenes — the edit surface. The default at launch (creator ruling 2026-11-12). Build, /// Record / Go Live — the output surface: which output, and the one action that starts it. Output, } /// /// The top bar's one decision (creator ruling 2026-11-12): [ Build Scenes ][ Record / Go Live ]. /// Build Scenes is edit mode — there is no separate EDIT toggle any more, so "may I edit?" and /// "which world am I in?" cannot disagree. /// /// Clicking the highlighted segment is not a no-op: it re-enters that world, which matters while a /// session runs because Build Scenes is the only way back to the layers (see /// ). /// public partial class MainViewModel { private BarWorld _barWorld = BarWorld.Build; public BarWorld BarWorld => _barWorld; public bool IsBuildWorld => _barWorld == BarWorld.Build; public bool IsOutputWorld => _barWorld == BarWorld.Output; /// The output stage belongs to the Record / Go Live world, and only while nothing is /// running — a live session cannot change its output, so its switch is not offered. public bool ShowOutputStage => IsOutputWorld && IsOffline && !IsRecording; // ─── The output stage's three states (creator, builds 728/729) ─── // 1. nothing chosen: [YouTube] [Local MP4] // 2. YouTube chosen: [YouTube(red)] [Live Stream] [Private Stream] (Private = the test run) // 3. Local MP4 chosen: [Local MP4(red)] [Start Recording] -> [End Recording] while recording public bool ShowOutputChoice => ShowOutputStage && !RecordPillOn && !OnAirPillOn; public bool ShowYouTubeSelected => ShowOutputStage && OnAirPillOn; public bool ShowLocalMp4Selected => ShowOutputStage && RecordPillOn; /// The YouTube chip shows while nothing is chosen and while YouTube IS the choice; once /// Local MP4 is chosen the MP4 chip replaces it in the left slot (creator, build 729). public bool YouTubeChipVisible => ShowOutputChoice || ShowYouTubeSelected; public bool LocalMp4ChipVisible => ShowOutputChoice || ShowLocalMp4Selected; public bool ShowStartRecordingAction => ShowLocalMp4Selected && !IsRecording; public bool ShowEndRecordingAction => ShowLocalMp4Selected && IsRecording; public ICommand SelectYouTubeCommand { get; private set; } = null!; public ICommand SelectLocalMp4Command { get; private set; } = null!; public ICommand StartRecordingCommand { get; private set; } = null!; public ICommand TestStreamCommand { get; private set; } = null!; public ICommand GoLiveCommand { get; private set; } = null!; public ICommand EnterBuildWorldCommand { get; private set; } = null!; public ICommand EnterOutputWorldCommand { get; private set; } = null!; private void InitializeWorldCommands() { SelectYouTubeCommand = new RelayCommand(_ => OnAirPillOn = true, _ => ShowOutputChoice); SelectLocalMp4Command = new RelayCommand(_ => RecordPillOn = true, _ => ShowOutputChoice); StartRecordingCommand = new RelayCommand(_ => BeginRecordOnly(), _ => ShowStartRecordingAction); // A signed-out press starts the sign-in flow instead of sitting dead (no-dead-ends rule). TestStreamCommand = new RelayCommand(_ => { if (!IsConnected) { _ = SignInAsync(); return; } BeginTestStream(); }, _ => ShowYouTubeSelected); GoLiveCommand = new RelayCommand(_ => { if (!IsConnected) { _ = SignInAsync(); return; } StartSession(); }, _ => ShowYouTubeSelected); EnterBuildWorldCommand = new RelayCommand(_ => EnterWorld(BarWorld.Build)); EnterOutputWorldCommand = new RelayCommand(_ => EnterWorld(BarWorld.Output)); } /// Everything the output stage shows or hides, in one place so no caller can forget /// one of them. internal void RaiseOutputStage() { OnPropertyChanged(nameof(ShowOutputStage)); OnPropertyChanged(nameof(ShowOutputChoice)); OnPropertyChanged(nameof(ShowYouTubeSelected)); OnPropertyChanged(nameof(YouTubeChipVisible)); OnPropertyChanged(nameof(LocalMp4ChipVisible)); OnPropertyChanged(nameof(ShowLocalMp4Selected)); OnPropertyChanged(nameof(ShowStartRecordingAction)); OnPropertyChanged(nameof(ShowEndRecordingAction)); } /// Switches worlds. Re-entering the current one still re-asserts its edit state, which is /// what lets a creator take EDIT back mid-show by clicking Build Scenes. internal void EnterWorld(BarWorld world) { _barWorld = world; // Entering a world starts with NOTHING chosen inside it (creator, build 729): the output // switches are a fresh decision each time, not a remembered one. if (world == BarWorld.Output) { RecordPillOn = false; OnAirPillOn = false; } OnPropertyChanged(nameof(BarWorld)); OnPropertyChanged(nameof(IsBuildWorld)); OnPropertyChanged(nameof(IsOutputWorld)); EditingActive = world == BarWorld.Build; OnPropertyChanged(nameof(ShowOutputStage)); RaiseOutputStage(); } }