refactor: split SocialsDialogViewModel under 500 lines — 500-limit Phase 3, Commit D
SocialsDialogViewModel.cs 515 -> 334. Extracted the DialogEntry record + the row-level SocialSlotViewModel (service/logo/lock/edit/validate state, computed Show* flags) into a new SocialSlotViewModel.cs partial. The dialog VM keeps the sign-in gate, validation orchestration, and commit. DialogEntry stays public in the same namespace. Zero behavior change; build 0 warnings; 246 pass, only the 2 known failures. Docs: ViewModels/index.md Phase 3 tracker updated in same commit.
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
using System.ComponentModel;
|
||||
using ytLive.Helpers;
|
||||
using ytLive.Models;
|
||||
using ytLive.ViewModels;
|
||||
|
||||
namespace ytLive.ViewModels;
|
||||
public sealed record DialogEntry(SocialService Service, string Handle, string ProfileUrl, string? FediverseSoftware = null);
|
||||
|
||||
/// <summary>
|
||||
/// One of the six fixed dialog rows. Row 0 is always YouTube (signed-in account
|
||||
/// or a sign-in prompt); rows 1-5 hold validated entries, an empty slot, or — on
|
||||
/// the free tier — a locked "Premium" slot. Rows are a positional projection of
|
||||
/// the dialog's working list, so deleting an entry makes the ones above advance up.
|
||||
/// </summary>
|
||||
public sealed class SocialSlotViewModel : ViewModelBase
|
||||
{
|
||||
public int Index { get; }
|
||||
public bool IsYoutube => Index == 0;
|
||||
|
||||
private SocialService _service = SocialService.Link;
|
||||
public SocialService Service
|
||||
{
|
||||
get => _service;
|
||||
set { if (SetProperty(ref _service, value)) OnPropertyChanged(nameof(LogoData)); }
|
||||
}
|
||||
|
||||
public string LogoData => Service == SocialService.Fediverse
|
||||
? SocialServiceIcons.LogoDataForFediverse(FediverseSoftware)
|
||||
: SocialServiceIcons.LogoDataFor(Service);
|
||||
public string LockedIconData => SocialServiceIcons.LockedIconData;
|
||||
public string DoNotIconData => SocialServiceIcons.DoNotIconData;
|
||||
|
||||
private bool _isLocked;
|
||||
public bool IsLocked
|
||||
{
|
||||
get => _isLocked;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isLocked, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowAddButton));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isFilled;
|
||||
public bool IsFilled
|
||||
{
|
||||
get => _isFilled;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isFilled, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowEditButton));
|
||||
OnPropertyChanged(nameof(ShowDeleteButton));
|
||||
OnPropertyChanged(nameof(ShowAddButton));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isSignIn;
|
||||
public bool IsSignIn
|
||||
{
|
||||
get => _isSignIn;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isSignIn, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowSignInButton));
|
||||
OnPropertyChanged(nameof(ShowDeleteButton));
|
||||
OnPropertyChanged(nameof(ShowLogo));
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isEditing;
|
||||
public bool IsEditing
|
||||
{
|
||||
get => _isEditing;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isEditing, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowEditBox));
|
||||
OnPropertyChanged(nameof(ShowDisplay));
|
||||
OnPropertyChanged(nameof(ShowEditButton));
|
||||
OnPropertyChanged(nameof(ShowDeleteButton));
|
||||
OnPropertyChanged(nameof(ShowAddButton));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isValidating;
|
||||
public bool IsValidating
|
||||
{
|
||||
get => _isValidating;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isValidating, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowBusy));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _handle = string.Empty;
|
||||
public string Handle
|
||||
{
|
||||
get => _handle;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _handle, value))
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
|
||||
private string? _fediverseSoftware;
|
||||
public string? FediverseSoftware
|
||||
{
|
||||
get => _fediverseSoftware;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _fediverseSoftware, value))
|
||||
OnPropertyChanged(nameof(LogoData));
|
||||
}
|
||||
}
|
||||
|
||||
public string ProfileUrl { get; set; } = string.Empty;
|
||||
|
||||
private string? _error;
|
||||
public string? Error
|
||||
{
|
||||
get => _error;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _error, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(HasError));
|
||||
OnPropertyChanged(nameof(ShowError));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _editText = string.Empty;
|
||||
public string EditText
|
||||
{
|
||||
get => _editText;
|
||||
set => SetProperty(ref _editText, value);
|
||||
}
|
||||
|
||||
/// <summary>The last text submitted for validation (used to skip re-validating
|
||||
/// identical input — e.g. a LostFocus firing as the user clicks Cancel).</summary>
|
||||
public string? LastValidatedInput { get; set; }
|
||||
|
||||
public string DisplayText =>
|
||||
IsYoutube
|
||||
? (IsSignIn ? "Sign in to YouTube" : Handle)
|
||||
: IsLocked ? "Unlock with Premium"
|
||||
: IsFilled ? Handle
|
||||
: "No social yet";
|
||||
|
||||
public bool HasError => !string.IsNullOrEmpty(Error);
|
||||
public bool ShowError => HasError;
|
||||
public bool ShowLogo => IsYoutube ? !IsSignIn : IsFilled;
|
||||
public bool ShowBusy => IsValidating;
|
||||
public bool ShowEditBox => IsEditing;
|
||||
public bool ShowDisplay => !IsEditing && !IsValidating;
|
||||
public bool ShowSignInButton => IsYoutube && IsSignIn && !IsValidating;
|
||||
public bool ShowAddButton => !IsYoutube && !IsLocked && !IsFilled && !IsEditing && !IsValidating;
|
||||
public bool ShowEditButton => !IsYoutube && IsFilled && !IsEditing && !IsValidating;
|
||||
public bool ShowDeleteButton => (IsFilled || IsYoutube) && !IsEditing && !IsValidating;
|
||||
public bool ShowDoNot => !IsYoutube && !IsLocked && (!IsFilled || HasError || IsValidating);
|
||||
|
||||
public SocialSlotViewModel(int index) => Index = index;
|
||||
}
|
||||
@@ -8,187 +8,6 @@ using ytLive.Services;
|
||||
|
||||
namespace ytLive.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// A validated social entry in the dialog's working copy (non-YouTube slots).
|
||||
/// </summary>
|
||||
public sealed record DialogEntry(SocialService Service, string Handle, string ProfileUrl, string? FediverseSoftware = null);
|
||||
|
||||
/// <summary>
|
||||
/// One of the six fixed dialog rows. Row 0 is always YouTube (signed-in account
|
||||
/// or a sign-in prompt); rows 1-5 hold validated entries, an empty slot, or — on
|
||||
/// the free tier — a locked "Premium" slot. Rows are a positional projection of
|
||||
/// the dialog's working list, so deleting an entry makes the ones above advance up.
|
||||
/// </summary>
|
||||
public sealed class SocialSlotViewModel : ViewModelBase
|
||||
{
|
||||
public int Index { get; }
|
||||
public bool IsYoutube => Index == 0;
|
||||
|
||||
private SocialService _service = SocialService.Link;
|
||||
public SocialService Service
|
||||
{
|
||||
get => _service;
|
||||
set { if (SetProperty(ref _service, value)) OnPropertyChanged(nameof(LogoData)); }
|
||||
}
|
||||
|
||||
public string LogoData => Service == SocialService.Fediverse
|
||||
? SocialServiceIcons.LogoDataForFediverse(FediverseSoftware)
|
||||
: SocialServiceIcons.LogoDataFor(Service);
|
||||
public string LockedIconData => SocialServiceIcons.LockedIconData;
|
||||
public string DoNotIconData => SocialServiceIcons.DoNotIconData;
|
||||
|
||||
private bool _isLocked;
|
||||
public bool IsLocked
|
||||
{
|
||||
get => _isLocked;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isLocked, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowAddButton));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isFilled;
|
||||
public bool IsFilled
|
||||
{
|
||||
get => _isFilled;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isFilled, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowEditButton));
|
||||
OnPropertyChanged(nameof(ShowDeleteButton));
|
||||
OnPropertyChanged(nameof(ShowAddButton));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isSignIn;
|
||||
public bool IsSignIn
|
||||
{
|
||||
get => _isSignIn;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isSignIn, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowSignInButton));
|
||||
OnPropertyChanged(nameof(ShowDeleteButton));
|
||||
OnPropertyChanged(nameof(ShowLogo));
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isEditing;
|
||||
public bool IsEditing
|
||||
{
|
||||
get => _isEditing;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isEditing, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowEditBox));
|
||||
OnPropertyChanged(nameof(ShowDisplay));
|
||||
OnPropertyChanged(nameof(ShowEditButton));
|
||||
OnPropertyChanged(nameof(ShowDeleteButton));
|
||||
OnPropertyChanged(nameof(ShowAddButton));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _isValidating;
|
||||
public bool IsValidating
|
||||
{
|
||||
get => _isValidating;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _isValidating, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(ShowBusy));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _handle = string.Empty;
|
||||
public string Handle
|
||||
{
|
||||
get => _handle;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _handle, value))
|
||||
OnPropertyChanged(nameof(DisplayText));
|
||||
}
|
||||
}
|
||||
|
||||
private string? _fediverseSoftware;
|
||||
public string? FediverseSoftware
|
||||
{
|
||||
get => _fediverseSoftware;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _fediverseSoftware, value))
|
||||
OnPropertyChanged(nameof(LogoData));
|
||||
}
|
||||
}
|
||||
|
||||
public string ProfileUrl { get; set; } = string.Empty;
|
||||
|
||||
private string? _error;
|
||||
public string? Error
|
||||
{
|
||||
get => _error;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _error, value))
|
||||
{
|
||||
OnPropertyChanged(nameof(HasError));
|
||||
OnPropertyChanged(nameof(ShowError));
|
||||
OnPropertyChanged(nameof(ShowDoNot));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private string _editText = string.Empty;
|
||||
public string EditText
|
||||
{
|
||||
get => _editText;
|
||||
set => SetProperty(ref _editText, value);
|
||||
}
|
||||
|
||||
/// <summary>The last text submitted for validation (used to skip re-validating
|
||||
/// identical input — e.g. a LostFocus firing as the user clicks Cancel).</summary>
|
||||
public string? LastValidatedInput { get; set; }
|
||||
|
||||
public string DisplayText =>
|
||||
IsYoutube
|
||||
? (IsSignIn ? "Sign in to YouTube" : Handle)
|
||||
: IsLocked ? "Unlock with Premium"
|
||||
: IsFilled ? Handle
|
||||
: "No social yet";
|
||||
|
||||
public bool HasError => !string.IsNullOrEmpty(Error);
|
||||
public bool ShowError => HasError;
|
||||
public bool ShowLogo => IsYoutube ? !IsSignIn : IsFilled;
|
||||
public bool ShowBusy => IsValidating;
|
||||
public bool ShowEditBox => IsEditing;
|
||||
public bool ShowDisplay => !IsEditing && !IsValidating;
|
||||
public bool ShowSignInButton => IsYoutube && IsSignIn && !IsValidating;
|
||||
public bool ShowAddButton => !IsYoutube && !IsLocked && !IsFilled && !IsEditing && !IsValidating;
|
||||
public bool ShowEditButton => !IsYoutube && IsFilled && !IsEditing && !IsValidating;
|
||||
public bool ShowDeleteButton => (IsFilled || IsYoutube) && !IsEditing && !IsValidating;
|
||||
public bool ShowDoNot => !IsYoutube && !IsLocked && (!IsFilled || HasError || IsValidating);
|
||||
|
||||
public SocialSlotViewModel(int index) => Index = index;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// View model for the Social Media Site Promotion dialog. Owns the working copy
|
||||
/// of the social bar config: the six fixed slots, the sign-in gate, per-row
|
||||
|
||||
@@ -69,5 +69,6 @@ commit, tag `refactor-commit-N`, no per-commit push).
|
||||
- [x] **Commit A · `refactor-commit-A`** — **core** → `MainViewModel.cs` 758 → **495**. Moved source add/remove/image block to new **`MainViewModel.Sources.cs`** (234 lines: `AddSource`, `NextSourceName`, `AddImage`, `BuildImageCandidates`, `PickImageBytes`, `AddAsset`, `AddImageSource`, `AddReusedImage`, `RemoveElement`) and WebView2 hosting (`RegisterLoadedWebSources`, `InitWebView2`, `OnWebView2PreviewBitmapChanged`) to new **`MainViewModel.Web.cs`**. Pruned now-dead usings (`Microsoft.Win32`, `NAudio.CoreAudioApi`, `System.Windows.Media.Imaging`, `Collections.ObjectModel/Specialized`). Pending: Streaming, Background, SocialsDialogViewModel, LayoutStore.
|
||||
- [x] **Commit B · `refactor-commit-B`** — **Streaming** → `MainViewModel.Streaming.cs` 789 → **330** + new **`MainViewModel.Streaming.Operations.cs`** (459 lines). Moved the go-live/record/health operation bodies (`StartSession`, `BeginRecordOnly`, `BeginGoLive`, `StartRecordFile`, `PrepareAndStartLiveAsync`, `PollHealthAsync`/`OnHealthPollTick`/`ApplyHealthIssue`, `StopStream`, `FinalizeRecordingAsync`, `UniquePath`, `ChooseRecordFolder`, `ResetRecordFolder`, `DefaultRecordFolder`, `OnFramePumpFailed`, `OnFramePumpHealthUpdated`, `ApplyHealth`, `ResetHealth`, `BuildEncoderOptions`) into the Operations partial; Streaming.cs keeps state + quality/resolution tiers + session timer + command declarations. Pruned dead usings both files. Pending: Background, SocialsDialogViewModel, LayoutStore.
|
||||
- [x] **Commit C · `refactor-commit-C`** — **Background** → `MainViewModel.Background.cs` 567 → **418** + new **`MainViewModel.Background.Model.cs`** (163 lines). Moved the static scene-model helpers (`LoadBackgroundImage`, `CreatePlaceholderSnapshot`, `EnsureBackground`, `CreateBackground`, `NormalizeBackgrounds`, `AllBackgrounds`, `ResolveAutoCaptureKey`, `MonitorKeyPrefix`) into the Model partial; Background.cs keeps capture/live state + operations (`UpdateActiveBackground`, `UpdateBackgroundImage`, `RefreshSnapshotsAsync`, `ReacquireScreenCaptures`, `OnScreenPreviewBitmapChanged`, `OnFullscreenMonitorChanged`, `RefreshBackgroundAutoCapture`, `BrowseBackground`, `ClearBackgroundCaptureAsync`, `RedesignateBackgroundAsync`, `ChangeBackgroundCaptureAsync`, `SetBackgroundCapture`, `DefaultBackgroundAsset`, `HealBackgrounds`, `StampDefaultBackgroundAsset`). Pending: SocialsDialogViewModel, LayoutStore.
|
||||
- [x] **Commit D · `refactor-commit-D`** — **SocialsDialog** → `SocialsDialogViewModel.cs` 515 → **334** + new **`SocialSlotViewModel.cs`** (183 lines). Moved the `DialogEntry` record + the row-level `SocialSlotViewModel` (six-fixed-slot row VM: service/logo/lock/edit/validate state + computed `Show*` flags) into its own file; `SocialsDialogViewModel.cs` keeps the dialog VM (sign-in gate, validation orchestration, commit). `DialogEntry` stays `public` in the same namespace so both files see it. Pending: LayoutStore.
|
||||
The partial `.cs` files land next to `MainViewModel.cs` in this folder as the split
|
||||
proceeds; each partial carries its own `using`s and re-declares nothing from core.
|
||||
Reference in New Issue
Block a user