Files
AX-Copilot/src/AxCopilot/Models/AppSettings.cs
lacvet e92800165d [Phase L5-6] 자동화 스케줄러 구현 완료
ScheduleEntry 모델 (AppSettings.Models.cs):
- Id(8자 GUID), Name, Enabled, TriggerType(daily/weekdays/weekly/once)
- TriggerTime(HH:mm), WeekDays(List<int>), TriggerDate(nullable), LastRun(nullable)
- ActionType(app/notification), ActionTarget, ActionArgs

AppSettings.cs:
- [JsonPropertyName("schedules")] public List<ScheduleEntry> Schedules 추가

Services/SchedulerService.cs (197줄 신규):
- System.Threading.Timer 30초 간격 백그라운드 체크
- ShouldFire(): ±1분 윈도우, LastRun.Date == today 중복 방지, once 자동 비활성화
- ExecuteAction(): 앱 실행(ProcessStartInfo) / 알림(NotificationService.Notify)
- ComputeNextRun(): 다음 실행 예정 시각 계산 (핸들러·편집기 공유)
- TriggerLabel(): 트리거 유형 표시명 반환

Handlers/ScheduleHandler.cs (171줄 신규):
- prefix="sched", 서브커맨드: new / edit 이름 / del 이름
- 목록: 트리거 라벨·시각·액션 아이콘·다음 실행 시각 표시
- Enter: 활성/비활성 토글 + 저장

Views/ScheduleEditorWindow.xaml (307줄 신규):
- 트리거 유형 4-세그먼트(매일/주중/매주/한번), 요일 7버튼, 날짜 입력
- 액션 2-세그먼트(앱 실행/알림), 앱 경로+찾아보기+인자, 알림 메시지
- 활성화 ToggleSwitch, 저장/취소 하단바

Views/ScheduleEditorWindow.xaml.cs (230줄 신규):
- OnLoaded에서 기존 항목 로드 (편집) 또는 기본값 초기화
- SetTriggerUi(): 세그먼트 색상·WeekDaysPanel/DatePanel 표시 전환
- WeekDay_Click/SetDaySelected(): 요일 다중 토글
- SetActionUi(): 앱경로 패널 / 알림 패널 전환
- BtnSave_Click(): HH:mm 파싱 + 날짜 검증 + ScheduleEntry 생성·수정 저장

App.xaml.cs:
- _schedulerService 필드 + Phase L5-6 등록 블록 추가
- schedulerService.Start() 호출

docs/LAUNCHER_ROADMAP.md:
- L5-6  완료 표시 + 구현 내용 상세 기록

빌드: 경고 0, 오류 0
2026-04-04 13:07:12 +09:00

335 lines
14 KiB
C#

using System.Text.Json.Serialization;
namespace AxCopilot.Models;
public class AppSettings
{
[JsonPropertyName("version")]
public string Version { get; set; } = "1.0";
/// <summary>
/// AI 기능 활성화 여부. false이면 ! 명령어 차단 + 설정의 AX Agent 탭 숨김.
/// 클로드 버전(AI 미포함 배포)은 false로 설정합니다.
/// </summary>
[JsonPropertyName("ai_enabled")]
public bool AiEnabled { get; set; } = false;
/// <summary>
/// 사내 모드 활성화 여부. true(기본)이면 외부 인터넷 접속 차단.
/// false(사외 모드)이면 웹 검색, 외부 HTTP 요청 허용.
/// 사외 모드 전환은 비밀번호(axgo123!) 인증 필요.
/// </summary>
[JsonPropertyName("internal_mode_enabled")]
public bool InternalModeEnabled { get; set; } = true;
[JsonPropertyName("hotkey")]
public string Hotkey { get; set; } = "Alt+Space";
[JsonPropertyName("launcher")]
public LauncherSettings Launcher { get; set; } = new();
[JsonPropertyName("indexPaths")]
public List<string> IndexPaths { get; set; } = new()
{
"%USERPROFILE%\\Desktop",
"%APPDATA%\\Microsoft\\Windows\\Start Menu"
};
/// <summary>
/// 인덱싱할 파일 확장자 목록 (점 포함). 빈 리스트 = 모든 파일.
/// 기본값: 실행 파일 + 문서 + 이미지 + 텍스트 파일.
/// </summary>
[JsonPropertyName("indexExtensions")]
public List<string> IndexExtensions { get; set; } = new()
{
// 실행 파일
".exe", ".lnk", ".bat", ".ps1", ".url", ".cmd", ".msi",
// 문서
".pdf", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx",
".hwp", ".hwpx",
// 텍스트
".txt", ".md", ".csv", ".json", ".xml", ".yaml", ".yml",
".log", ".ini", ".cfg", ".conf",
// 이미지
".png", ".jpg", ".jpeg", ".gif", ".bmp", ".svg", ".webp", ".ico", ".tiff",
// 기타
".zip", ".7z", ".rar"
};
/// <summary>인덱싱 속도. slow | normal | fast. 기본 normal.</summary>
[JsonPropertyName("indexSpeed")]
public string IndexSpeed { get; set; } = "normal"; // slow | normal | fast
[JsonPropertyName("monitorMismatch")]
public string MonitorMismatch { get; set; } = "warn"; // fit | skip | warn
[JsonPropertyName("profiles")]
public List<WorkspaceProfile> Profiles { get; set; } = new();
[JsonPropertyName("aliases")]
public List<AliasEntry> Aliases { get; set; } = new();
[JsonPropertyName("clipboardTransformers")]
public List<ClipboardTransformer> ClipboardTransformers { get; set; } = new();
[JsonPropertyName("apiAdapters")]
public List<ApiAdapter> ApiAdapters { get; set; } = new();
[JsonPropertyName("plugins")]
public List<PluginEntry> Plugins { get; set; } = new();
[JsonPropertyName("snippets")]
public List<SnippetEntry> Snippets { get; set; } = new();
[JsonPropertyName("quickLinks")]
public List<QuickLinkEntry> QuickLinks { get; set; } = new();
[JsonPropertyName("aiSnippetTemplates")]
public List<AiSnippetTemplate> AiSnippetTemplates { get; set; } = new()
{
new() { Keyword = "email", Name = "업무 이메일", Prompt = "다음 상황에 맞는 업무용 이메일을 작성해주세요: {0}" },
new() { Keyword = "summary", Name = "요약", Prompt = "다음 내용을 간결하게 요약해주세요: {0}" },
new() { Keyword = "translate",Name = "번역", Prompt = "다음 텍스트를 자연스럽게 한국어로 번역해주세요: {0}" },
new() { Keyword = "review", Name = "코드 리뷰", Prompt = "다음 코드를 검토하고 개선점을 제안해주세요:\n{0}" },
new() { Keyword = "commit", Name = "커밋 메시지", Prompt = "다음 변경사항에 대한 git 커밋 메시지를 작성해주세요: {0}" },
};
[JsonPropertyName("clipboardHistory")]
public ClipboardHistorySettings ClipboardHistory { get; set; } = new();
[JsonPropertyName("systemCommands")]
public SystemCommandSettings SystemCommands { get; set; } = new();
[JsonPropertyName("screenCapture")]
public ScreenCaptureSettings ScreenCapture { get; set; } = new();
[JsonPropertyName("reminder")]
public ReminderSettings Reminder { get; set; } = new();
/// <summary>
/// 항목별 글로벌 전용 핫키 목록. 어떤 앱이 포커스를 가져도 해당 핫키로 즉시 실행됩니다.
/// </summary>
[JsonPropertyName("customHotkeys")]
public List<HotkeyAssignment> CustomHotkeys { get; set; } = new();
/// <summary>
/// 앱 세션 목록. session 핸들러로 여러 앱을 지정 레이아웃에 한번에 실행합니다.
/// </summary>
[JsonPropertyName("appSessions")]
public List<AppSession> AppSessions { get; set; } = new();
/// <summary>
/// 자동화 스케줄 목록. SchedulerService가 백그라운드에서 트리거를 확인·실행합니다.
/// </summary>
[JsonPropertyName("schedules")]
public List<ScheduleEntry> Schedules { get; set; } = new();
[JsonPropertyName("llm")]
public LlmSettings Llm { get; set; } = new();
}
public class LauncherSettings
{
[JsonPropertyName("opacity")]
public double Opacity { get; set; } = 0.96;
[JsonPropertyName("maxResults")]
public int MaxResults { get; set; } = 7;
[JsonPropertyName("theme")]
// 지원 값: system | dark | light | oled | nord | monokai | catppuccin | sepia | custom
public string Theme { get; set; } = "system";
[JsonPropertyName("position")]
public string Position { get; set; } = "center-top"; // center-top | center | bottom
[JsonPropertyName("width")]
public double Width { get; set; } = 680;
[JsonPropertyName("webSearchEngine")]
public string WebSearchEngine { get; set; } = "g"; // g | n | d | y | w
[JsonPropertyName("snippetAutoExpand")]
public bool SnippetAutoExpand { get; set; } = true;
[JsonPropertyName("language")]
public string Language { get; set; } = "ko"; // ko | en | ja | zh | vi
[JsonPropertyName("customTheme")]
public CustomThemeColors? CustomTheme { get; set; }
// ─── 기능 토글 ─────────────────────────────────────────────────────────
/// <summary>번호 배지(1~9) 표시 여부. Ctrl+숫자로 바로 실행. 기본 true.</summary>
[JsonPropertyName("showNumberBadges")]
public bool ShowNumberBadges { get; set; } = true;
/// <summary>즐겨찾기 기능 활성화. fav 접두어, Ctrl+B. 기본 true.</summary>
[JsonPropertyName("enableFavorites")]
public bool EnableFavorites { get; set; } = true;
/// <summary>최근 실행 기록 저장 여부. recent 접두어, Ctrl+R. 기본 true.</summary>
[JsonPropertyName("enableRecent")]
public bool EnableRecent { get; set; } = true;
/// <summary>액션 모드 진입 허용 여부. Ctrl+Enter / Alt+Enter / → 키. 기본 true.</summary>
[JsonPropertyName("enableActionMode")]
public bool EnableActionMode { get; set; } = true;
/// <summary>포커스 잃을 때 런처 자동 닫기. 기본 true.</summary>
[JsonPropertyName("closeOnFocusLost")]
public bool CloseOnFocusLost { get; set; } = true;
/// <summary>입력창 좌측 프리픽스 배지 표시. 기본 true.</summary>
[JsonPropertyName("showPrefixBadge")]
public bool ShowPrefixBadge { get; set; } = true;
/// <summary>런처 아이콘 애니메이션 효과 활성화. 기본 true.</summary>
[JsonPropertyName("enableIconAnimation")]
public bool EnableIconAnimation { get; set; } = true;
/// <summary>런처 안내 문구 랜덤 출력 활성화. false이면 고정 문구. 기본 true.</summary>
[JsonPropertyName("enableRandomPlaceholder")]
public bool EnableRandomPlaceholder { get; set; } = true;
/// <summary>런처 무지개 글로우 효과 활성화. 기본 false (성능 고려).</summary>
[JsonPropertyName("enableRainbowGlow")]
public bool EnableRainbowGlow { get; set; } = false;
/// <summary>선택된 아이템 상시 글로우 효과. 기본 false.</summary>
[JsonPropertyName("enableSelectionGlow")]
public bool EnableSelectionGlow { get; set; } = false;
/// <summary>런처 창 테두리 표시 여부. 기본 true(표시).</summary>
[JsonPropertyName("showLauncherBorder")]
public bool ShowLauncherBorder { get; set; } = true;
/// <summary>단축키 헬프 창에서 아이콘 색상을 테마 AccentColor 기준으로 표시. 기본 true(테마색).</summary>
[JsonPropertyName("shortcutHelpUseThemeColor")]
public bool ShortcutHelpUseThemeColor { get; set; } = true;
// ─── 독 바 설정 ──────────────────────────────────────────────────────────
// ─── 선택 텍스트 AI 명령 설정 ───────────────────────────────────────────
/// <summary>선택 텍스트 AI 명령 활성화. 기본 true.</summary>
[JsonPropertyName("enableTextAction")]
public bool EnableTextAction { get; set; } = true;
/// <summary>활성화된 텍스트 AI 명령 목록. 가능한 값: translate, summarize, grammar, explain, rewrite</summary>
[JsonPropertyName("textActionCommands")]
public List<string> TextActionCommands { get; set; } = new() { "translate", "summarize", "grammar", "explain", "rewrite" };
/// <summary>번역 기본 언어. 기본 "한국어↔영어 자동".</summary>
[JsonPropertyName("textActionTranslateLanguage")]
public string TextActionTranslateLanguage { get; set; } = "auto";
// ─── 파일 대화상자 통합 설정 ─────────────────────────────────────────────
/// <summary>열기/저장 대화상자 감지 시 런처 자동 열기. 기본 false.</summary>
[JsonPropertyName("enableFileDialogIntegration")]
public bool EnableFileDialogIntegration { get; set; } = false;
// ─── 클립보드 핀/카테고리 설정 ───────────────────────────────────────────
/// <summary>클립보드 자동 카테고리 분류 활성화. 기본 true.</summary>
[JsonPropertyName("enableClipboardAutoCategory")]
public bool EnableClipboardAutoCategory { get; set; } = true;
/// <summary>최대 핀 고정 개수. 기본 20.</summary>
[JsonPropertyName("maxPinnedClipboardItems")]
public int MaxPinnedClipboardItems { get; set; } = 20;
// ─── 독 바 설정 ──────────────────────────────────────────────────────────
/// <summary>독 바 표시 항목. 가능한 값: launcher, clipboard, capture, agent, clock, cpu, ram, quickinput</summary>
[JsonPropertyName("dockBarItems")]
public List<string> DockBarItems { get; set; } = new() { "launcher", "clipboard", "capture", "agent", "clock", "cpu" };
/// <summary>독 바 앱 시작 시 자동 표시. 기본 false.</summary>
[JsonPropertyName("dockBarAutoShow")]
public bool DockBarAutoShow { get; set; } = false;
/// <summary>독 바 투명도 (0.3~1.0). 기본 0.92.</summary>
[JsonPropertyName("dockBarOpacity")]
public double DockBarOpacity { get; set; } = 0.92;
/// <summary>독 바 무지개 글로우 효과. 기본 false.</summary>
[JsonPropertyName("dockBarRainbowGlow")]
public bool DockBarRainbowGlow { get; set; } = false;
/// <summary>독 바 마지막 위치 X. -1이면 중앙.</summary>
[JsonPropertyName("dockBarLeft")]
public double DockBarLeft { get; set; } = -1;
/// <summary>독 바 마지막 위치 Y. -1이면 하단.</summary>
[JsonPropertyName("dockBarTop")]
public double DockBarTop { get; set; } = -1;
/// <summary>
/// Phase L3-7: 모니터별 독 바 위치.
/// key = 모니터 디바이스 이름 (예: \\.\DISPLAY1), value = [WPF Left, WPF Top].
/// 모니터가 재연결되면 해당 모니터의 저장 위치로 자동 복원됩니다.
/// </summary>
[JsonPropertyName("monitorDockPositions")]
public Dictionary<string, double[]> MonitorDockPositions { get; set; } = new();
}
/// <summary>
/// "theme": "custom" 설정 시 사용할 사용자 정의 색상.
/// settings.json에서 직접 헥스 코드(#RRGGBB)로 지정합니다.
/// </summary>
public class CustomThemeColors
{
[JsonPropertyName("launcherBackground")]
public string LauncherBackground { get; set; } = "#1A1B2E";
[JsonPropertyName("itemBackground")]
public string ItemBackground { get; set; } = "#252637";
[JsonPropertyName("itemSelectedBackground")]
public string ItemSelectedBackground { get; set; } = "#3B4BDB";
[JsonPropertyName("itemHoverBackground")]
public string ItemHoverBackground { get; set; } = "#22233A";
[JsonPropertyName("primaryText")]
public string PrimaryText { get; set; } = "#F0F0FF";
[JsonPropertyName("secondaryText")]
public string SecondaryText { get; set; } = "#7A7D9C";
[JsonPropertyName("placeholderText")]
public string PlaceholderText { get; set; } = "#464868";
[JsonPropertyName("accentColor")]
public string AccentColor { get; set; } = "#4B5EFC";
[JsonPropertyName("separatorColor")]
public string SeparatorColor { get; set; } = "#252637";
[JsonPropertyName("hintBackground")]
public string HintBackground { get; set; } = "#252637";
[JsonPropertyName("hintText")]
public string HintText { get; set; } = "#4B5070";
[JsonPropertyName("borderColor")]
public string BorderColor { get; set; } = "#2E2F4A";
[JsonPropertyName("scrollbarThumb")]
public string ScrollbarThumb { get; set; } = "#3A3B5A";
[JsonPropertyName("shadowColor")]
public string ShadowColor { get; set; } = "#000000";
/// <summary>창 전체 모서리 라운딩 (0~30). 기본값 20.</summary>
[JsonPropertyName("windowCornerRadius")]
public int WindowCornerRadius { get; set; } = 20;
/// <summary>결과 항목 모서리 라운딩 (0~20). 기본값 10.</summary>
[JsonPropertyName("itemCornerRadius")]
public int ItemCornerRadius { get; set; } = 10;
}