diff --git a/README.md b/README.md index 389ac3d..d632e66 100644 --- a/README.md +++ b/README.md @@ -1059,3 +1059,5 @@ MIT License - AX Agent 빈 상태 상단 심볼과 작업 유형/대화 주제 프리셋 카드 아이콘 비율을 다시 맞췄다. 프리셋 카드 내부 아이콘과 `프리셋 추가` 심볼은 한 단계 줄이고, 상단 중앙 심볼과 제목도 같은 밀도로 재조정해 화면 균형을 정리했다. - 업데이트: 2026-04-05 23:38 (KST) - 하단 컨텍스트 토큰 hover 라벨이 마우스를 떼어도 남아 있던 문제를 보정했다. 닫힘 판정을 단순 `IsMouseOver` 대신 실제 마우스 좌표 기준으로 바꾸고, 팝업 내용도 `현재 사용량 + 자동 압축 기준`만 남기도록 단순화했다. +- 업데이트: 2026-04-05 23:44 (KST) + - 권한 모드 팝업에서 불필요한 `상세 정보` 섹션을 제거하고, 선택 가능한 모드 행만 남기는 단순 리스트형 UI로 정리했다. `계획 모드`는 제외하고 실제 사용하는 권한 요청/편집 자동 승인/권한 건너뛰기 중심으로 재정렬했다. diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 7c17faa..3342549 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4810,3 +4810,6 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - 업데이트: 2026-04-05 23:38 (KST) - [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 의 하단 컨텍스트 토큰 hover 팝업을 더 단순하게 정리했다. 모델명/오늘 사용량 줄은 제거하고 `현재 사용량`과 `자동 압축 시작 기준`만 남겼다. - 같은 파일의 토큰 팝업 닫힘 판정도 `IsMouseOver`만 보던 방식에서 실제 마우스 좌표 기반으로 바꿔, 마우스를 떼었는데도 라벨이 남아 있는 경우를 줄였다. +- 업데이트: 2026-04-05 23:44 (KST) + - [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 의 권한 모드 팝업 폭, padding, 그림자를 줄여 더 단순한 드롭다운 패널처럼 보이게 정리했다. + - [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 에서 권한 모드 팝업의 `상세 정보` 섹션을 제거하고, `계획 모드`를 제외한 핵심 권한 모드 행만 남기도록 재구성했다. 각 행도 왼쪽 accent bar 방식 대신 라운드 row 리스트형으로 바꿔 레퍼런스처럼 더 가벼운 선택 UI로 맞췄다. diff --git a/src/AxCopilot/Views/ChatWindow.xaml b/src/AxCopilot/Views/ChatWindow.xaml index 447d35d..059d256 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml +++ b/src/AxCopilot/Views/ChatWindow.xaml @@ -1352,9 +1352,9 @@ + Padding="12" MinWidth="308" MaxWidth="324"> - + diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index 889da23..700c1b7 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -1873,260 +1873,9 @@ public partial class ChatWindow : Window ChatConversation? currentConversation; lock (_convLock) currentConversation = _currentConversation; - var summary = _appState.GetPermissionSummary(currentConversation); - var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White; - var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray; - - Border CreateCollapsibleSection(string sectionKey, string icon, string title, UIElement content, bool expanded, string accentHex = "#334155") - { - var body = new Border - { - Margin = new Thickness(0, 5, 0, 0), - Visibility = expanded ? Visibility.Visible : Visibility.Collapsed, - Child = content, - }; - var caret = new TextBlock - { - Text = expanded ? "\uE70D" : "\uE76C", - FontFamily = new FontFamily("Segoe MDL2 Assets"), - FontSize = 10.5, - Foreground = secondaryText, - VerticalAlignment = VerticalAlignment.Center, - }; - - var headerGrid = new Grid(); - headerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); - headerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) }); - headerGrid.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto }); - headerGrid.Children.Add(new TextBlock - { - Text = icon, - FontFamily = new FontFamily("Segoe MDL2 Assets"), - FontSize = 10.5, - Foreground = BrushFromHex(accentHex), - Margin = new Thickness(0, 0, 6, 0), - VerticalAlignment = VerticalAlignment.Center, - }); - var titleBlock = new TextBlock - { - Text = title, - FontSize = 9.5, - FontWeight = FontWeights.SemiBold, - Foreground = primaryText, - VerticalAlignment = VerticalAlignment.Center, - }; - Grid.SetColumn(titleBlock, 1); - headerGrid.Children.Add(titleBlock); - Grid.SetColumn(caret, 2); - headerGrid.Children.Add(caret); - - var headerBorder = new Border - { - Background = Brushes.Transparent, - CornerRadius = new CornerRadius(6), - Padding = new Thickness(8, 5, 8, 5), - Cursor = Cursors.Hand, - Focusable = true, - Child = headerGrid, - }; - KeyboardNavigation.SetIsTabStop(headerBorder, true); - headerBorder.MouseEnter += (_, _) => headerBorder.Background = BrushFromHex("#F8FAFC"); - headerBorder.MouseLeave += (_, _) => headerBorder.Background = Brushes.Transparent; - void ToggleSection() - { - var show = body.Visibility != Visibility.Visible; - body.Visibility = show ? Visibility.Visible : Visibility.Collapsed; - caret.Text = show ? "\uE70D" : "\uE76C"; - SetPermissionPopupSectionExpanded(sectionKey, show); - } - headerBorder.MouseLeftButtonUp += (_, _) => ToggleSection(); - headerBorder.KeyDown += (_, ke) => - { - if (ke.Key is Key.Enter or Key.Space) - { - ke.Handled = true; - ToggleSection(); - } - }; - - return new Border - { - Background = Brushes.Transparent, - BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.Gray, - BorderThickness = new Thickness(0, 0, 0, 1), - CornerRadius = new CornerRadius(0), - Padding = new Thickness(0, 2, 0, 2), - Margin = new Thickness(0, 0, 0, 2), - Child = new StackPanel - { - Children = - { - headerBorder, - body, - } - } - }; - } - - var summaryCard = new StackPanel - { - Margin = new Thickness(0, 0, 0, 4), - Children = - { - CreateFlatPopupRow( - "\uE946", - $"현재 모드 · {PermissionModeCatalog.ToDisplayLabel(summary.EffectiveMode)}", - summary.Description, - string.Equals(summary.RiskLevel, "high", StringComparison.OrdinalIgnoreCase) ? "#C2410C" : - string.Equals(summary.RiskLevel, "locked", StringComparison.OrdinalIgnoreCase) ? "#475569" : "#4338CA", - false, - null), - CreateFlatPopupRow( - "\uE8D7", - $"기본값 · {PermissionModeCatalog.ToDisplayLabel(summary.DefaultMode)}", - $"예외 {summary.OverrideCount}개", - "#64748B", - false, - null) - } - }; - - StackPanel? overrideSection = null; - if (summary.TopOverrides.Count > 0) - { - var overrideWrap = new StackPanel - { - Margin = new Thickness(0, 0, 0, 5), - }; - - foreach (var overrideEntry in summary.TopOverrides) - { - overrideWrap.Children.Add(CreateFlatPopupRow( - "\uE72E", - overrideEntry.Key, - PermissionModeCatalog.ToDisplayLabel(overrideEntry.Value), - "#2563EB", - false, - null)); - } - - overrideSection = new StackPanel - { - Margin = new Thickness(0, 0, 0, 8), - Children = - { - new TextBlock - { - Text = "도구별 예외", - FontSize = 10, - FontWeight = FontWeights.SemiBold, - Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, - Margin = new Thickness(2, 0, 0, 3), - }, - overrideWrap - } - }; - } - - var latestDenied = _appState.GetLatestDeniedPermission(); - Border? deniedCard = null; - if (latestDenied != null) - { - var deniedStack = new StackPanel(); - deniedStack.Children.Add(new StackPanel - { - Orientation = Orientation.Horizontal, - Margin = new Thickness(0, 0, 0, 2), - Children = - { - new TextBlock - { - Text = "\uEA39", - FontFamily = new FontFamily("Segoe MDL2 Assets"), - FontSize = 10.5, - Foreground = BrushFromHex("#991B1B"), - Margin = new Thickness(0, 0, 6, 0), - VerticalAlignment = VerticalAlignment.Center, - }, - new TextBlock - { - Text = "최근 권한 거부", - FontSize = 10.5, - FontWeight = FontWeights.SemiBold, - Foreground = BrushFromHex("#991B1B"), - } - } - }); - deniedStack.Children.Add(new TextBlock - { - Text = _appState.FormatPermissionEventLine(latestDenied), - FontSize = 10, - Foreground = BrushFromHex("#991B1B"), - Margin = new Thickness(0, 0, 0, 0), - TextWrapping = TextWrapping.Wrap, - LineHeight = 14, - MaxWidth = 250, - }); - - if (!string.IsNullOrWhiteSpace(latestDenied.ToolName)) - { - deniedStack.Children.Add(new TextBlock - { - Text = $"도구 {latestDenied.ToolName}에 바로 적용", - FontSize = 9.5, - Margin = new Thickness(0, 4, 0, 0), - Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, - }); - - var actionRow = new StackPanel - { - Margin = new Thickness(0, 6, 0, 0), - }; - - actionRow.Children.Add(CreateFlatPopupRow( - "\uE711", - "읽기 전용", - "이 도구의 쓰기 작업을 차단합니다", - "#991B1B", - true, - () => { SetToolPermissionOverride(latestDenied.ToolName!, PermissionModeCatalog.Deny); RefreshPermissionPopup(); })); - actionRow.Children.Add(CreateFlatPopupRow( - "\uE8D7", - "권한 요청", - "실행 전 항상 확인받도록 되돌립니다", - "#1D4ED8", - true, - () => { SetToolPermissionOverride(latestDenied.ToolName!, PermissionModeCatalog.Default); RefreshPermissionPopup(); })); - actionRow.Children.Add(CreateFlatPopupRow( - "\uE73E", - "편집 자동 승인", - "이 도구의 편집 작업을 자동 허용합니다", - "#166534", - true, - () => { SetToolPermissionOverride(latestDenied.ToolName!, PermissionModeCatalog.AcceptEdits); RefreshPermissionPopup(); })); - actionRow.Children.Add(CreateFlatPopupRow( - "\uE74D", - "예외 해제", - "도구별 예외를 제거하고 기본값을 사용합니다", - "#374151", - true, - () => { SetToolPermissionOverride(latestDenied.ToolName!, null); RefreshPermissionPopup(); })); - deniedStack.Children.Add(actionRow); - } - - deniedCard = new Border - { - Background = Brushes.Transparent, - BorderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.Gray, - BorderThickness = new Thickness(0, 0, 0, 1), - CornerRadius = new CornerRadius(0), - Padding = new Thickness(8, 8, 8, 8), - Margin = new Thickness(0, 0, 0, 4), - Child = deniedStack, - }; - } - - var coreLevels = PermissionModePresentationCatalog.Ordered.ToList(); + var coreLevels = PermissionModePresentationCatalog.Ordered + .Where(item => !string.Equals(item.Mode, PermissionModeCatalog.Plan, StringComparison.OrdinalIgnoreCase)) + .ToList(); var current = PermissionModeCatalog.NormalizeGlobalMode(_settings.Settings.Llm.FilePermission); void AddPermissionRows(Panel container, IEnumerable levels) { @@ -2137,11 +1886,11 @@ public partial class ChatWindow : Window var rowBorder = new Border { Background = isActive ? BrushFromHex("#F8FAFC") : Brushes.Transparent, - BorderBrush = isActive ? BrushFromHex("#C7D2FE") : BrushFromHex("#E5E7EB"), - BorderThickness = new Thickness(isActive ? 2 : 0, 0, 0, 1), - CornerRadius = new CornerRadius(0), - Padding = new Thickness(8, 8, 8, 8), - Margin = new Thickness(0, 0, 0, 0), + BorderBrush = Brushes.Transparent, + BorderThickness = new Thickness(1), + CornerRadius = new CornerRadius(12), + Padding = new Thickness(10, 10, 10, 10), + Margin = new Thickness(0, 0, 0, 4), Cursor = Cursors.Hand, Focusable = true, }; @@ -2156,9 +1905,9 @@ public partial class ChatWindow : Window { Text = item.Icon, FontFamily = new FontFamily("Segoe MDL2 Assets"), - FontSize = 12, + FontSize = 15, Foreground = BrushFromHex(item.ColorHex), - Margin = new Thickness(1, 0, 8, 0), + Margin = new Thickness(0, 0, 10, 0), VerticalAlignment = VerticalAlignment.Center, }); @@ -2166,19 +1915,19 @@ public partial class ChatWindow : Window textStack.Children.Add(new TextBlock { Text = item.Title, - FontSize = 11.5, + FontSize = 13.5, FontWeight = FontWeights.SemiBold, Foreground = TryFindResource("PrimaryText") as Brush ?? Brushes.White, }); textStack.Children.Add(new TextBlock { Text = item.Description, - FontSize = 10.5, - Margin = new Thickness(0, 1, 0, 0), + FontSize = 11.5, + Margin = new Thickness(0, 2, 0, 0), Foreground = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray, TextWrapping = TextWrapping.Wrap, - LineHeight = 15, - MaxWidth = 240, + LineHeight = 16, + MaxWidth = 220, }); Grid.SetColumn(textStack, 1); row.Children.Add(textStack); @@ -2187,11 +1936,11 @@ public partial class ChatWindow : Window { Text = isActive ? "\uE73E" : "", FontFamily = new FontFamily("Segoe MDL2 Assets"), - FontSize = 11, + FontSize = 12, FontWeight = FontWeights.Bold, Foreground = BrushFromHex("#2563EB"), VerticalAlignment = VerticalAlignment.Center, - Margin = new Thickness(8, 0, 1, 0), + Margin = new Thickness(12, 0, 0, 0), }; Grid.SetColumn(check, 2); row.Children.Add(check); @@ -2200,12 +1949,10 @@ public partial class ChatWindow : Window rowBorder.MouseEnter += (_, _) => { rowBorder.Background = BrushFromHex("#F8FAFC"); - rowBorder.BorderBrush = isActive ? BrushFromHex("#C7D2FE") : BrushFromHex("#E2E8F0"); }; rowBorder.MouseLeave += (_, _) => { rowBorder.Background = isActive ? BrushFromHex("#F8FAFC") : Brushes.Transparent; - rowBorder.BorderBrush = isActive ? BrushFromHex("#C7D2FE") : BrushFromHex("#E5E7EB"); }; var capturedLevel = level; @@ -2234,24 +1981,8 @@ public partial class ChatWindow : Window } } - PermissionItems.Children.Add(CreatePopupSectionLabel("핵심 권한 모드")); AddPermissionRows(PermissionItems, coreLevels); - // claw-code 기준 UX 정렬: 기본 화면은 핵심 모드 중심, 부가 정보는 단일 상세 섹션으로 제공. - var detailsPanel = new StackPanel(); - detailsPanel.Children.Add(summaryCard); - if (overrideSection != null) - detailsPanel.Children.Add(overrideSection); - if (deniedCard != null) - detailsPanel.Children.Add(deniedCard); - - PermissionItems.Children.Add(CreateCollapsibleSection( - "permission_details", - "\uE946", - "상세 정보", - detailsPanel, - expanded: GetPermissionPopupSectionExpanded("permission_details", false))); - PermissionPopup.IsOpen = true; Dispatcher.BeginInvoke(() => {