Files
AX-Copilot/src/AxCopilot/App.Helpers.cs
lacvet aa907d7b79 [Phase46] 대형 파일 분할 리팩터링 2차 — 19개 신규 파셜 파일 생성
## 분할 대상 및 결과

### AgentLoopService.cs (1,334줄 → 846줄)
- AgentLoopService.HtmlReport.cs (151줄): AutoSaveAsHtml, ConvertTextToHtml, EscapeHtml
- AgentLoopService.Verification.cs (349줄): 도구 분류 판별 + RunPostToolVerificationAsync + EmitEvent + CheckDecisionRequired + FormatToolCallSummary

### ChatWindow 분할 (8개 신규 파셜 파일)
- ChatWindow.PlanViewer.cs (474줄): 계획 뷰어 — AddPlanningCard, AddDecisionButtons, CollapseDecisionButtons, ShowPlanButton 등 8개 메서드
- ChatWindow.EventBanner.cs (411줄): AddAgentEventBanner, BuildFileQuickActions
- ChatWindow.TaskDecomposition.cs (1,170줄 → 307줄): RenderSuggestActionChips, BuildFeedbackContext, UpdateProgressBar, BuildDiffView 잔류
- ChatWindow.BottomBar.cs (345줄): BuildBottomBar, BuildCodeBottomBar, ShowLogLevelMenu, ShowLanguageMenu 등
- ChatWindow.MoodMenu.cs (456줄): ShowFormatMenu, ShowMoodMenu, ShowCustomMoodDialog 등
- ChatWindow.CustomPresets.cs (978줄 → 203줄): ShowCustomPresetDialog, SelectTopic 잔류
- ChatWindow.ConversationMenu.cs (255줄): ShowConversationMenu (카테고리/삭제/즐겨찾기 팝업)
- ChatWindow.ConversationTitleEdit.cs (108줄): EnterTitleEditMode

### SettingsViewModel 분할
- SettingsViewModel.LlmProperties.cs (417줄): LLM·에이전트 관련 바인딩 프로퍼티
- SettingsViewModel.Properties.cs (837줄 → 427줄): 기능 토글·테마·스니펫 등 앱 수준 프로퍼티

### TemplateService 분할
- TemplateService.Css.cs (559줄): 11종 CSS 테마 문자열 상수
- TemplateService.cs (734줄 → 179줄): 메서드 로직만 잔류

### PlanViewerWindow 분할
- PlanViewerWindow.StepRenderer.cs (616줄): RenderSteps + SwapSteps + EditStep + 버튼 빌더 9개
- PlanViewerWindow.cs (931줄 → 324줄): Win32/생성자/공개 API 잔류

### App.xaml.cs 분할 (776줄 → 452줄)
- App.Settings.cs (252줄): SetupTrayIcon, OpenSettings, ToggleDockBar, RefreshDockBar, OpenAiChat
- App.Helpers.cs (92줄): LoadAppIcon, IsAutoStartEnabled, SetAutoStart, OnExit

### LlmService.ToolUse.cs 분할 (719줄 → 115줄)
- LlmService.ClaudeTools.cs (180줄): SendClaudeWithToolsAsync, BuildClaudeToolBody
- LlmService.GeminiTools.cs (175줄): SendGeminiWithToolsAsync, BuildGeminiToolBody
- LlmService.OpenAiTools.cs (215줄): SendOpenAiWithToolsAsync, BuildOpenAiToolBody

### SettingsWindow.UI.cs 분할 (802줄 → 310줄)
- SettingsWindow.Storage.cs (167줄): RefreshStorageInfo, BtnStorageCleanup_Click 등
- SettingsWindow.HotkeyUI.cs (127줄): RefreshHotkeyBadges, EnsureHotkeyInCombo, GetKeyName 등
- SettingsWindow.DevMode.cs (90줄): DevModeCheckBox_Checked, UpdateDevModeContentVisibility

## 빌드 결과: 경고 0, 오류 0

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 20:51:26 +09:00

93 lines
3.1 KiB
C#

using Microsoft.Win32;
using AxCopilot.Services;
namespace AxCopilot;
public partial class App
{
// ─── 자동 시작 / 앱 종료 헬퍼 ──────────────────────────────────────
private static System.Drawing.Icon LoadAppIcon()
{
// DPI 인식 아이콘 크기 (기본 16 → 고DPI에서 20/24/32)
var iconSize = System.Windows.Forms.SystemInformation.SmallIconSize;
// 1) 파일 시스템에서 로드 (개발 환경)
try
{
var exeDir = System.IO.Path.GetDirectoryName(Environment.ProcessPath)
?? AppContext.BaseDirectory;
var path = System.IO.Path.Combine(exeDir, "Assets", "icon.ico");
if (System.IO.File.Exists(path))
return new System.Drawing.Icon(path, iconSize);
}
catch (Exception) { }
// 2) 내장 리소스에서 로드 (PublishSingleFile 배포)
try
{
var uri = new Uri("pack://application:,,,/Assets/icon.ico");
var stream = System.Windows.Application.GetResourceStream(uri)?.Stream;
if (stream != null)
return new System.Drawing.Icon(stream, iconSize);
}
catch (Exception) { }
return System.Drawing.SystemIcons.Application;
}
private const string AutoRunKey = @"Software\Microsoft\Windows\CurrentVersion\Run";
private const string AutoRunName = "AxCopilot";
private static bool IsAutoStartEnabled()
{
try
{
using var key = Registry.CurrentUser.OpenSubKey(AutoRunKey, writable: false);
return key?.GetValue(AutoRunName) != null;
}
catch (Exception) { return false; }
}
private static void SetAutoStart(bool enable)
{
try
{
using var key = Registry.CurrentUser.OpenSubKey(AutoRunKey, writable: true);
if (key == null) return;
if (enable)
{
var exePath = Environment.ProcessPath
?? System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName
?? string.Empty;
if (!string.IsNullOrEmpty(exePath))
key.SetValue(AutoRunName, $"\"{exePath}\"");
}
else
{
key.DeleteValue(AutoRunName, throwOnMissingValue: false);
}
}
catch (Exception ex)
{
LogService.Warn($"자동 시작 레지스트리 설정 실패: {ex.Message}");
}
}
protected override void OnExit(System.Windows.ExitEventArgs e)
{
_chatWindow?.ForceClose(); // 미리 생성된 ChatWindow 진짜 닫기
_inputListener?.Dispose();
_clipboardHistory?.Dispose();
_indexService?.Dispose();
_sessionTracking?.Dispose();
_worktimeReminder?.Dispose();
_trayIcon?.Dispose();
try { _singleInstanceMutex?.ReleaseMutex(); } catch (Exception) { }
_singleInstanceMutex?.Dispose();
LogService.Info("=== AX Copilot 종료 ===");
base.OnExit(e);
}
}