MainViewModel.cs was 1017 lines and 45KB — most of it was bulk-operation
loops, Teams UIA plumbing, and the auto-apply-last-preset state machine
sitting on top of the actual MainViewModel surface (constructor, props,
OnStatsTick). Splits the class via partial-class into themed siblings:
* MainViewModel.cs (was 1017L → now 699L) — fields, properties,
constructor that wires every Command, OnStatsTick + Dispose. This
remains the thin aggregator.
* MainViewModel.TeamsCommands.cs (130L, new) — MakeTeamsCommand helper,
JoinPastedMeeting (body of JoinMeetingCommand), ExtractMeetingTitle
(already-tested static), PollTeamsMeetingState (the 1Hz UIA probe
formerly inlined in OnStatsTick).
* MainViewModel.PresetCommands.cs (108L, new) —
RequestApplyPresetOnStartup (CLI hook), LoadPendingPresetFromPreferences
(called by InitializeAsync), TryAutoApplyPendingPreset (the reconcile
step), and the _pendingPreset* private-field set that backs the path.
* MainViewModel.BulkCommands.cs (149L, new) — EnableAllOnlineAsync,
StopAllIsosAsync (with the default-No confirmation dialog),
SnapshotAll. RecordingCommands.cs from the original punch list is
intentionally absent — the recording surface was axed at 1d1ce6a;
what remains here is bulk-state ops across the participants
collection (note in the file header).
Why partial-class instead of helper-services or composed objects: every
extracted method touches the same private dispatcher / controller /
participants / toast state. Composing would require either passing
those references in (verbose call sites) or extracting them to a
shared private context object (boilerplate). Partial gives us
file-level separation without spreading the state contract.
ExtractMeetingTitle stays internal-static so the existing
MeetingTitleExtractionTests (10 cases) keep finding it. Build clean;
56 App + 104 Engine tests still pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>