refactor(P5b-1): CommunityToolkit.Mvvm 도입 + OptionsViewModel 추출 (옵션 로직 테스트화)
MVVM 첫 슬라이스 — 테스트 불가능했던 코드비하인드 BuildOptions의 순수 옵션 구성 로직을 헤드리스 단위테스트 가능한 OptionsViewModel.ToConvertOptions로 추출. XAML 바인딩 미변경(런타임 위험 0). - CommunityToolkit.Mvvm 8.2.2(CPM) + App.csproj. App/ViewModels/OptionsViewModel.cs: ObservableObject + [ObservableProperty](Quality/CustomOutputDirectory/ConflictRule/AiTaskIndex/ TargetLanguage/VideoPreferGpu) → 향후 옵션 패널 직접 바인딩 토대. ToConvertOptions()는 순수. - MainWindow.BuildOptions: 컨트롤 값을 VM에 반영 후 ToConvertOptions() 위임(동작 동일). - Tests → App ProjectReference 추가(App 뷰모델 헤드리스 테스트 가능화). - OptionsViewModelTests 10케이스(품질매핑·AVIF clamp·커스텀폴더 trim·AI작업·대상언어·충돌/GPU). 71 → 81개 테스트 전부 그린, 빌드 0경고/0오류.
This commit is contained in:
parent
729b9b699d
commit
ba5738e705
6 changed files with 136 additions and 29 deletions
55
src/Everything2Everything.App/ViewModels/OptionsViewModel.cs
Normal file
55
src/Everything2Everything.App/ViewModels/OptionsViewModel.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Everything2Everything.Core;
|
||||
|
||||
namespace Everything2Everything.App.ViewModels;
|
||||
|
||||
/// <summary>
|
||||
/// 변환 옵션 패널의 상태 + 불변 ConvertOptions 구성 로직(MVVM ViewModel).
|
||||
/// ToConvertOptions는 순수 함수라 WPF 없이 헤드리스 단위 테스트가 가능하다(P5b: 코드비하인드 BuildOptions 추출).
|
||||
/// ObservableProperty로 노출되어 향후 옵션 패널 XAML을 이 VM에 직접 바인딩할 수 있다.
|
||||
/// </summary>
|
||||
public partial class OptionsViewModel : ObservableObject
|
||||
{
|
||||
/// <summary>JPEG/WebP 품질(1~100). AVIF는 -30 보정.</summary>
|
||||
[ObservableProperty] private int _quality = 85;
|
||||
|
||||
/// <summary>비우면 원본 옆 서브폴더. 값이 있으면 사용자 지정 출력 폴더.</summary>
|
||||
[ObservableProperty] private string? _customOutputDirectory;
|
||||
|
||||
[ObservableProperty] private NameCollision _conflictRule = NameCollision.AppendNumber;
|
||||
|
||||
/// <summary>0=요약, 1=번역, 2=교정 (AI 텍스트 변환).</summary>
|
||||
[ObservableProperty] private int _aiTaskIndex;
|
||||
|
||||
[ObservableProperty] private string? _targetLanguage;
|
||||
|
||||
[ObservableProperty] private bool _videoPreferGpu = true;
|
||||
|
||||
/// <summary>현재 상태로 불변 ConvertOptions를 구성한다(기존 MainWindow.BuildOptions와 동일 동작).</summary>
|
||||
public ConvertOptions ToConvertOptions()
|
||||
{
|
||||
var hasCustom = !string.IsNullOrWhiteSpace(CustomOutputDirectory);
|
||||
var aiTask = AiTaskIndex switch
|
||||
{
|
||||
1 => "translate",
|
||||
2 => "proofread",
|
||||
_ => "summarize",
|
||||
};
|
||||
|
||||
return new ConvertOptions
|
||||
{
|
||||
OnCollision = ConflictRule,
|
||||
OutputLocation = hasCustom ? OutputLocation.Custom : OutputLocation.SubfolderBesideSource,
|
||||
CustomOutputDirectory = hasCustom ? CustomOutputDirectory!.Trim() : null,
|
||||
Jpeg = new JpegEncodingOptions { Quality = Quality },
|
||||
Webp = new WebpEncodingOptions { Quality = Quality },
|
||||
Avif = new AvifEncodingOptions { Quality = Math.Clamp(Quality - 30, 1, 100) },
|
||||
Ai = new AiOptions
|
||||
{
|
||||
Task = aiTask,
|
||||
TargetLanguage = string.IsNullOrWhiteSpace(TargetLanguage) ? null : TargetLanguage.Trim(),
|
||||
},
|
||||
VideoPreferGpu = VideoPreferGpu,
|
||||
};
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue