diff --git a/README.md b/README.md index 6393f62..0c88988 100644 --- a/README.md +++ b/README.md @@ -790,8 +790,10 @@ ow + toggle 시각 언어로 통일했습니다. - [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml)의 축소 아이콘 바는 상하 행 높이, 버튼 패딩, 아이콘 크기, 사용자 배지 크기를 한 단계 더 줄여 현재 사이드바와 같은 밀도로 묶었습니다. 이제 축소 상태에서도 검색/필터/새 대화 아이콘이 더 균일한 간격으로 정리되고, 하단 사용자 배지도 과하게 튀지 않는 중립형으로 유지됩니다. - AX Agent 내부 설정 탭도 다시 정리했습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml), [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 에서 사라졌던 `테마 스타일`, `테마 모드`를 `공통` 탭에 실제 선택 카드로 복구했고, 기존 `스킬/차단` 탭은 `도구 / 스킬 / 차단`으로 나눠 각 항목이 맞는 탭에서만 보이게 재배치했습니다. - 이제 `도구` 탭에서는 훅과 도구/커넥터 목록을, `스킬` 탭에서는 스킬 폴더, 슬래시 설정, 드래그 앤 드롭, 로드된 스킬, 폴백 모델, MCP 서버를, `차단` 탭에서는 차단 경로/확장자만 관리합니다. 같이 [SettingsWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/SettingsWindow.xaml.cs) 에서 메인 설정의 `AX Agent` 바로가기 탭을 좌측 사이드바 맨 아래로 재배치했습니다. +- 런처 하단 바도 요소별로 제어할 수 있게 바꿨습니다. [AppSettings.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Models/AppSettings.cs), [SettingsViewModel.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/ViewModels/SettingsViewModel.cs), [SettingsWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/SettingsWindow.xaml) 에 `성능 / 포모도로 / 메모 / 날씨 / 일정 / 배터리` 하단 위젯 표시 토글을 추가해서 일반 설정에서 항목별로 바로 켜고 끌 수 있게 했습니다. +- [LauncherWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/LauncherWindow.xaml), [LauncherWindow.Widgets.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/LauncherWindow.Widgets.cs) 에서는 `Ollama / API / MCP` 서버 상태 위젯을 런처 하단 기능에서 완전히 제거했고, 남은 위젯들만 설정값에 따라 실제 표시되도록 연결했습니다. 배터리 위젯도 노트북 상태와 사용자 토글을 함께 반영해 보이게 정리했습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 -- 업데이트: 2026-04-05 15:06 (KST) +- 업데이트: 2026-04-05 15:16 (KST) --- diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index be94289..8c2467c 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4558,5 +4558,8 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - AX Agent 내부 설정 탭 구조도 다시 나눴습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 의 좌측 네비에서 기존 `스킬/차단`을 `도구 / 스킬 / 차단`으로 분리했고, [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `SetOverlaySection(...)` 가시성 로직도 각 탭에 맞는 패널만 보이도록 재구성했습니다. - `공통` 탭에는 숨겨져 있던 `테마 스타일`, `테마 모드`를 실제 선택 카드로 복구했고, `도구` 탭에는 훅/도구 커넥터 목록, `스킬` 탭에는 스킬 폴더/슬래시/로드된 스킬/폴백 모델/MCP 서버, `차단` 탭에는 차단 경로와 확장자만 남도록 분리했습니다. - 메인 설정 쪽은 [SettingsWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/SettingsWindow.xaml.cs) 에서 `AgentShortcutTabItem`을 `MainSettingsTab` 맨 끝으로 다시 추가해, AX Agent 이동 항목이 좌측 사이드바 맨 아래에 오도록 정리했습니다. +- 런처 하단 위젯도 일반 설정에서 요소별로 제어할 수 있게 확장했습니다. [AppSettings.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Models/AppSettings.cs), [SettingsViewModel.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/ViewModels/SettingsViewModel.cs), [SettingsWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/SettingsWindow.xaml)에 `성능 / 포모도로 / 메모 / 날씨 / 일정 / 배터리` 위젯 표시 토글을 추가했습니다. +- [LauncherWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/LauncherWindow.xaml) 에서는 하단 `Ollama / API / MCP` 서버 상태 위젯을 제거했고, [LauncherWindow.Widgets.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/LauncherWindow.Widgets.cs) 에서는 서버 상태 polling과 dot 갱신 경로를 제거한 뒤 위젯 표시/숨김을 설정값 기준으로 통합했습니다. +- 배터리 위젯은 사용자 토글과 실제 배터리 가용 상태를 함께 반영하도록 `UpdateWidgetVisibility()`에서 최종 가시성을 결정하게 바꿨고, 모든 위젯이 꺼져 있으면 하단 위젯 바 전체도 자동으로 숨깁니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0 -- 업데이트: 2026-04-05 15:06 (KST) +- 업데이트: 2026-04-05 15:16 (KST) diff --git a/src/AxCopilot/Models/AppSettings.cs b/src/AxCopilot/Models/AppSettings.cs index c482563..f8383b4 100644 --- a/src/AxCopilot/Models/AppSettings.cs +++ b/src/AxCopilot/Models/AppSettings.cs @@ -201,6 +201,24 @@ public class LauncherSettings [JsonPropertyName("showLauncherBorder")] public bool ShowLauncherBorder { get; set; } = true; + [JsonPropertyName("showWidgetPerf")] + public bool ShowWidgetPerf { get; set; } = true; + + [JsonPropertyName("showWidgetPomo")] + public bool ShowWidgetPomo { get; set; } = true; + + [JsonPropertyName("showWidgetNote")] + public bool ShowWidgetNote { get; set; } = true; + + [JsonPropertyName("showWidgetWeather")] + public bool ShowWidgetWeather { get; set; } = true; + + [JsonPropertyName("showWidgetCalendar")] + public bool ShowWidgetCalendar { get; set; } = true; + + [JsonPropertyName("showWidgetBattery")] + public bool ShowWidgetBattery { get; set; } = true; + /// 단축키 헬프 창에서 아이콘 색상을 테마 AccentColor 기준으로 표시. 기본 true(테마색). [JsonPropertyName("shortcutHelpUseThemeColor")] public bool ShortcutHelpUseThemeColor { get; set; } = true; diff --git a/src/AxCopilot/ViewModels/SettingsViewModel.cs b/src/AxCopilot/ViewModels/SettingsViewModel.cs index b0e93ae..0af6500 100644 --- a/src/AxCopilot/ViewModels/SettingsViewModel.cs +++ b/src/AxCopilot/ViewModels/SettingsViewModel.cs @@ -160,12 +160,19 @@ public class SettingsViewModel : INotifyPropertyChanged private bool _enableRecent; private bool _enableActionMode; private bool _closeOnFocusLost; + private bool _rememberPosition; private bool _showPrefixBadge; private bool _enableIconAnimation; private bool _enableRainbowGlow; private bool _enableSelectionGlow; private bool _enableRandomPlaceholder; private bool _showLauncherBorder; + private bool _showWidgetPerf; + private bool _showWidgetPomo; + private bool _showWidgetNote; + private bool _showWidgetWeather; + private bool _showWidgetCalendar; + private bool _showWidgetBattery; private bool _shortcutHelpUseThemeColor; // LLM 공통 설정 @@ -755,12 +762,54 @@ public class SettingsViewModel : INotifyPropertyChanged set { _closeOnFocusLost = value; OnPropertyChanged(); } } + public bool RememberPosition + { + get => _rememberPosition; + set { _rememberPosition = value; OnPropertyChanged(); } + } + public bool ShowPrefixBadge { get => _showPrefixBadge; set { _showPrefixBadge = value; OnPropertyChanged(); } } + public bool ShowWidgetPerf + { + get => _showWidgetPerf; + set { _showWidgetPerf = value; OnPropertyChanged(); } + } + + public bool ShowWidgetPomo + { + get => _showWidgetPomo; + set { _showWidgetPomo = value; OnPropertyChanged(); } + } + + public bool ShowWidgetNote + { + get => _showWidgetNote; + set { _showWidgetNote = value; OnPropertyChanged(); } + } + + public bool ShowWidgetWeather + { + get => _showWidgetWeather; + set { _showWidgetWeather = value; OnPropertyChanged(); } + } + + public bool ShowWidgetCalendar + { + get => _showWidgetCalendar; + set { _showWidgetCalendar = value; OnPropertyChanged(); } + } + + public bool ShowWidgetBattery + { + get => _showWidgetBattery; + set { _showWidgetBattery = value; OnPropertyChanged(); } + } + public bool EnableIconAnimation { get => _enableIconAnimation; @@ -1030,12 +1079,19 @@ public class SettingsViewModel : INotifyPropertyChanged _enableRecent = s.Launcher.EnableRecent; _enableActionMode = s.Launcher.EnableActionMode; _closeOnFocusLost = s.Launcher.CloseOnFocusLost; + _rememberPosition = s.Launcher.RememberPosition; _showPrefixBadge = s.Launcher.ShowPrefixBadge; _enableIconAnimation = s.Launcher.EnableIconAnimation; _enableRainbowGlow = s.Launcher.EnableRainbowGlow; _enableSelectionGlow = s.Launcher.EnableSelectionGlow; _enableRandomPlaceholder = s.Launcher.EnableRandomPlaceholder; _showLauncherBorder = s.Launcher.ShowLauncherBorder; + _showWidgetPerf = s.Launcher.ShowWidgetPerf; + _showWidgetPomo = s.Launcher.ShowWidgetPomo; + _showWidgetNote = s.Launcher.ShowWidgetNote; + _showWidgetWeather = s.Launcher.ShowWidgetWeather; + _showWidgetCalendar = s.Launcher.ShowWidgetCalendar; + _showWidgetBattery = s.Launcher.ShowWidgetBattery; _shortcutHelpUseThemeColor = s.Launcher.ShortcutHelpUseThemeColor; _enableTextAction = s.Launcher.EnableTextAction; // v1.7.1: 파일 대화상자 통합 기본값을 false로 변경 (브라우저 업로드 오작동 방지) @@ -1476,12 +1532,19 @@ public class SettingsViewModel : INotifyPropertyChanged s.Launcher.EnableRecent = _enableRecent; s.Launcher.EnableActionMode = _enableActionMode; s.Launcher.CloseOnFocusLost = _closeOnFocusLost; + s.Launcher.RememberPosition = _rememberPosition; s.Launcher.ShowPrefixBadge = _showPrefixBadge; s.Launcher.EnableIconAnimation = _enableIconAnimation; s.Launcher.EnableRainbowGlow = _enableRainbowGlow; s.Launcher.EnableSelectionGlow = _enableSelectionGlow; s.Launcher.EnableRandomPlaceholder = _enableRandomPlaceholder; s.Launcher.ShowLauncherBorder = _showLauncherBorder; + s.Launcher.ShowWidgetPerf = _showWidgetPerf; + s.Launcher.ShowWidgetPomo = _showWidgetPomo; + s.Launcher.ShowWidgetNote = _showWidgetNote; + s.Launcher.ShowWidgetWeather = _showWidgetWeather; + s.Launcher.ShowWidgetCalendar = _showWidgetCalendar; + s.Launcher.ShowWidgetBattery = _showWidgetBattery; s.Launcher.ShortcutHelpUseThemeColor = _shortcutHelpUseThemeColor; s.Launcher.EnableTextAction = _enableTextAction; s.Launcher.EnableFileDialogIntegration = _enableFileDialogIntegration; diff --git a/src/AxCopilot/Views/LauncherWindow.Widgets.cs b/src/AxCopilot/Views/LauncherWindow.Widgets.cs index 097c67b..57d5bdb 100644 --- a/src/AxCopilot/Views/LauncherWindow.Widgets.cs +++ b/src/AxCopilot/Views/LauncherWindow.Widgets.cs @@ -8,24 +8,17 @@ namespace AxCopilot.Views; public partial class LauncherWindow { private DispatcherTimer? _widgetTimer; - private static readonly SolidColorBrush DotOnline = new(Color.FromRgb(0x10, 0xB9, 0x81)); - private static readonly SolidColorBrush DotOffline = new(Color.FromRgb(0x9E, 0x9E, 0x9E)); private int _widgetBatteryTick; private int _widgetWeatherTick; internal void StartWidgetUpdates() { - var settings = CurrentApp?.SettingsService?.Settings; - PerformanceMonitorService.Instance.StartPolling(); - ServerStatusService.Instance.Start(settings); PomodoroService.Instance.StateChanged -= OnPomoStateChanged; PomodoroService.Instance.StateChanged += OnPomoStateChanged; - ServerStatusService.Instance.StatusChanged -= OnServerStatusChanged; - ServerStatusService.Instance.StatusChanged += OnServerStatusChanged; _vm.UpdateWidgets(); - UpdateServerDots(); + UpdateWidgetVisibility(); UpdateBatteryWidget(); _ = RefreshWeatherAsync(); @@ -38,7 +31,7 @@ public partial class LauncherWindow _widgetTimer.Tick += (_, _) => { _vm.UpdateWidgets(); - UpdateServerDots(); + UpdateWidgetVisibility(); if (_vm.Widget_PerfText.Length > 0 && _widgetBatteryTick++ % 30 == 0) UpdateBatteryWidget(); if (_widgetWeatherTick++ % 120 == 0) @@ -55,7 +48,6 @@ public partial class LauncherWindow _widgetTimer?.Stop(); PerformanceMonitorService.Instance.StopPolling(); PomodoroService.Instance.StateChanged -= OnPomoStateChanged; - ServerStatusService.Instance.StatusChanged -= OnServerStatusChanged; } private void OnPomoStateChanged(object? sender, EventArgs e) @@ -64,23 +56,10 @@ public partial class LauncherWindow { _vm.UpdateWidgets(); UpdatePomoWidgetStyle(); + UpdateWidgetVisibility(); }); } - private void OnServerStatusChanged(object? sender, EventArgs e) - => Dispatcher.InvokeAsync(UpdateServerDots); - - private void UpdateServerDots() - { - var server = ServerStatusService.Instance; - if (OllamaStatusDot != null) - OllamaStatusDot.Fill = server.OllamaOnline ? DotOnline : DotOffline; - if (LlmStatusDot != null) - LlmStatusDot.Fill = server.LlmOnline ? DotOnline : DotOffline; - if (McpStatusDot != null) - McpStatusDot.Fill = server.McpOnline ? DotOnline : DotOffline; - } - private void UpdatePomoWidgetStyle() { if (WgtPomo == null) @@ -92,6 +71,37 @@ public partial class LauncherWindow : new SolidColorBrush(Color.FromArgb(0x0D, 0xF5, 0x9E, 0x0B)); } + private void UpdateWidgetVisibility() + { + var launcher = CurrentApp?.SettingsService?.Settings?.Launcher; + if (launcher == null) + return; + + if (WgtPerf != null) + WgtPerf.Visibility = launcher.ShowWidgetPerf ? Visibility.Visible : Visibility.Collapsed; + if (WgtPomo != null) + WgtPomo.Visibility = launcher.ShowWidgetPomo ? Visibility.Visible : Visibility.Collapsed; + if (WgtNote != null) + WgtNote.Visibility = launcher.ShowWidgetNote ? Visibility.Visible : Visibility.Collapsed; + if (WgtWeather != null) + WgtWeather.Visibility = launcher.ShowWidgetWeather ? Visibility.Visible : Visibility.Collapsed; + if (WgtCal != null) + WgtCal.Visibility = launcher.ShowWidgetCalendar ? Visibility.Visible : Visibility.Collapsed; + if (WgtBattery != null) + WgtBattery.Visibility = launcher.ShowWidgetBattery && _vm.Widget_BatteryVisible ? Visibility.Visible : Visibility.Collapsed; + + var hasAny = + launcher.ShowWidgetPerf || + launcher.ShowWidgetPomo || + launcher.ShowWidgetNote || + launcher.ShowWidgetWeather || + launcher.ShowWidgetCalendar || + (launcher.ShowWidgetBattery && _vm.Widget_BatteryVisible); + + if (WidgetBar != null) + WidgetBar.Visibility = hasAny ? Visibility.Visible : Visibility.Collapsed; + } + private void WgtPerf_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { _vm.InputText = "info "; @@ -110,14 +120,6 @@ public partial class LauncherWindow InputBox?.Focus(); } - private void WgtServer_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) - { - var settings = CurrentApp?.SettingsService?.Settings; - ServerStatusService.Instance.Refresh(settings); - _vm.InputText = "port"; - InputBox?.Focus(); - } - private void WgtWeather_Click(object sender, System.Windows.Input.MouseButtonEventArgs e) { var internalMode = CurrentApp?.SettingsService?.Settings.InternalModeEnabled ?? true; @@ -153,7 +155,7 @@ public partial class LauncherWindow } catch (Exception ex) { - LogService.Warn($"달력 열기 실패: {ex.Message}"); + LogService.Warn($"일정 열기 실패: {ex.Message}"); } } } @@ -179,6 +181,7 @@ public partial class LauncherWindow if (pct > 1.0f || pct < 0f) { _vm.Widget_BatteryVisible = false; + UpdateWidgetVisibility(); return; } @@ -192,11 +195,13 @@ public partial class LauncherWindow : pctInt >= 50 ? "\uEBA3" : pctInt >= 25 ? "\uEBA1" : "\uEBA0"; + UpdateWidgetVisibility(); } catch (Exception ex) { - LogService.Warn($"배터리 위젯 갱신 실패: {ex.Message}"); + LogService.Warn($"배터리 상태 갱신 실패: {ex.Message}"); _vm.Widget_BatteryVisible = false; + UpdateWidgetVisibility(); } } @@ -204,6 +209,10 @@ public partial class LauncherWindow { var internalMode = CurrentApp?.SettingsService?.Settings.InternalModeEnabled ?? true; await WeatherWidgetService.RefreshAsync(internalMode); - await Dispatcher.InvokeAsync(() => { _vm.Widget_WeatherText = WeatherWidgetService.CachedText; }); + await Dispatcher.InvokeAsync(() => + { + _vm.Widget_WeatherText = WeatherWidgetService.CachedText; + UpdateWidgetVisibility(); + }); } } diff --git a/src/AxCopilot/Views/LauncherWindow.xaml b/src/AxCopilot/Views/LauncherWindow.xaml index 6d71c95..e1d9669 100644 --- a/src/AxCopilot/Views/LauncherWindow.xaml +++ b/src/AxCopilot/Views/LauncherWindow.xaml @@ -793,14 +793,13 @@ - - - - - - - - - - - - @@ -897,6 +865,7 @@ CornerRadius="5" Padding="8,5" Background="#0D3B82F6" Cursor="Hand" + Visibility="{Binding ShowWidgetWeather, Converter={StaticResource BoolToVisibilityConverter}}" MouseLeftButtonUp="WgtWeather_Click"> + Visibility="Collapsed"> + + + - @@ -546,6 +549,7 @@ @@ -656,58 +660,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1155,6 +1107,20 @@ + + + + + + + + + + + + + @@ -3020,6 +2986,19 @@ + + + + + + + + + + @@ -3065,6 +3044,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3365,7 +3412,7 @@ - + @@ -3384,7 +3431,7 @@ Unchecked="AiEnabled_Changed"/> - + @@ -3409,7 +3456,7 @@ - + @@ -5669,17 +5716,6 @@