refactor(P4): ConvertOptions God Object → 불변 record (init-only)
mutable sealed class(13 sub-record 가변)을 불변 record로 전환 — 배치 병렬 변환(P6)에서 공유해도 안전한 스레드 안전 전제 확보 + 값 의미론. 시그니처(ConvertAsync(ConvertOptions))는 비침습 유지. - ConvertOptions + 13개 옵션 타입(Jpeg/Png/Webp/Avif/Tiff/Bmp/Gif/PdfRender/PdfBuild/HtmlRender/ Ocr/PdfCompress/Ai) → sealed record, 전 프로퍼티 get;init;. 8개 Provider의 READ는 무영향. - 변이 5곳을 with 식/객체 초기화로 교정(WRITE만 깨지므로 국소적): MainWindow.BuildOptions(한 식으로 불변 구성), App.RunQuickAsync(with), OcrProvider(PdfRender 초기화), 특성화 테스트 2곳, ImageOptimProviderTests. - 카테고리 분해(RoutingOptions/OutputOptions)는 reader 파급이 커서 후속으로 보류(비침습 우선). 70개 테스트 전부 그린(골든마스터 동일성 = 동작 불변), 빌드 0경고/0오류.
This commit is contained in:
parent
12bda2dcbf
commit
379a4a738d
6 changed files with 95 additions and 98 deletions
|
|
@ -107,8 +107,7 @@ public partial class App : Application
|
|||
|
||||
try
|
||||
{
|
||||
var options = ConvertOptions.Quick();
|
||||
options.VideoPreferGpu = Settings.Get("video.gpu") != "false";
|
||||
var options = ConvertOptions.Quick() with { VideoPreferGpu = Settings.Get("video.gpu") != "false" };
|
||||
var reporter = new Progress<ConvertProgress>(p => progress.Report(p));
|
||||
var results = await Engine.ConvertManyAsync(files, outputExtension, options, reporter);
|
||||
|
||||
|
|
|
|||
|
|
@ -278,38 +278,35 @@ public partial class MainWindow : Wpf.Ui.Controls.FluentWindow
|
|||
|
||||
private ConvertOptions BuildOptions()
|
||||
{
|
||||
var opts = new ConvertOptions
|
||||
{
|
||||
OnCollision = _conflictRule,
|
||||
};
|
||||
opts.Jpeg.Quality = (int)QualitySlider.Value;
|
||||
opts.Webp.Quality = (int)QualitySlider.Value;
|
||||
opts.Avif.Quality = Math.Clamp((int)QualitySlider.Value - 30, 1, 100);
|
||||
var q = (int)QualitySlider.Value;
|
||||
|
||||
var custom = OutputPathTextBox.Text?.Trim();
|
||||
if (!string.IsNullOrEmpty(custom))
|
||||
{
|
||||
opts.OutputLocation = OutputLocation.Custom;
|
||||
opts.CustomOutputDirectory = custom;
|
||||
}
|
||||
else
|
||||
{
|
||||
opts.OutputLocation = OutputLocation.SubfolderBesideSource;
|
||||
}
|
||||
var hasCustom = !string.IsNullOrEmpty(custom);
|
||||
|
||||
// AI 작업 종류 (txt↔txt / md↔md 등 텍스트 변환 시 LlmProvider가 사용)
|
||||
opts.Ai.Task = (AiTaskCombo?.SelectedIndex ?? 0) switch
|
||||
var aiTask = (AiTaskCombo?.SelectedIndex ?? 0) switch
|
||||
{
|
||||
1 => "translate",
|
||||
2 => "proofread",
|
||||
_ => "summarize",
|
||||
};
|
||||
var targetLang = AiTargetLangBox?.Text?.Trim();
|
||||
opts.Ai.TargetLanguage = string.IsNullOrEmpty(targetLang) ? null : targetLang;
|
||||
|
||||
opts.VideoPreferGpu = _settings.Get("video.gpu") != "false";
|
||||
|
||||
return opts;
|
||||
return new ConvertOptions
|
||||
{
|
||||
OnCollision = _conflictRule,
|
||||
OutputLocation = hasCustom ? OutputLocation.Custom : OutputLocation.SubfolderBesideSource,
|
||||
CustomOutputDirectory = hasCustom ? custom : null,
|
||||
Jpeg = new JpegEncodingOptions { Quality = q },
|
||||
Webp = new WebpEncodingOptions { Quality = q },
|
||||
Avif = new AvifEncodingOptions { Quality = Math.Clamp(q - 30, 1, 100) },
|
||||
Ai = new AiOptions
|
||||
{
|
||||
Task = aiTask,
|
||||
TargetLanguage = string.IsNullOrEmpty(targetLang) ? null : targetLang,
|
||||
},
|
||||
VideoPreferGpu = _settings.Get("video.gpu") != "false",
|
||||
};
|
||||
}
|
||||
|
||||
// ============== Process queue ==============
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue