AX Agent 좌측 패널과 컨텍스트 사용량 UI를 Codex 기준으로 재정렬\n\n- 좌측 사이드바 폭과 새 대화/검색/필터/탭 메뉴 타이포를 키워 레퍼런스와 더 비슷한 밀도로 조정\n- Cowork 작업 유형 카드 크기와 제목/hover 설명 라벨 폰트를 확대해 가독성 보정\n- 하단 컨텍스트 사용량 카드를 작은 원형 심볼로 축소하고 hover 전용 커스텀 팝업으로 상세 정보 분리\n- README와 DEVELOPMENT 문서에 변경 이력 및 검증 결과 즉시 반영\n\n검증 결과\n- dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\\n- 경고 0 / 오류 0
Some checks failed
Release Gate / gate (push) Has been cancelled

This commit is contained in:
2026-04-05 16:39:32 +09:00
parent b53af39358
commit 500c8ffb06
4 changed files with 209 additions and 96 deletions

View File

@@ -87,6 +87,7 @@ public partial class ChatWindow : Window
private readonly DispatcherTimer _taskSummaryRefreshTimer;
private readonly DispatcherTimer _conversationPersistTimer;
private readonly DispatcherTimer _agentUiEventTimer;
private readonly DispatcherTimer _tokenUsagePopupCloseTimer;
private CancellationTokenSource? _gitStatusRefreshCts;
private int _displayedLength; // 현재 화면에 표시된 글자 수
private ResourceDictionary? _agentThemeDictionary;
@@ -270,6 +271,13 @@ public partial class ChatWindow : Window
_agentUiEventTimer.Stop();
FlushPendingAgentUiEvent();
};
_tokenUsagePopupCloseTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(140) };
_tokenUsagePopupCloseTimer.Tick += (_, _) =>
{
_tokenUsagePopupCloseTimer.Stop();
if (TokenUsagePopup != null)
TokenUsagePopup.IsOpen = false;
};
KeyDown += ChatWindow_KeyDown;
UpdateConversationFailureFilterUi();
@@ -12113,8 +12121,8 @@ public partial class ChatWindow : Window
Padding = new Thickness(14, 14, 14, 12),
Margin = new Thickness(6, 6, 6, 8),
Cursor = Cursors.Hand,
Width = 132,
Height = 110,
Width = 148,
Height = 124,
ClipToBounds = true,
};
@@ -12127,17 +12135,17 @@ public partial class ChatWindow : Window
var iconCircle = new Border
{
Width = 42, Height = 42,
CornerRadius = new CornerRadius(21),
Width = 46, Height = 46,
CornerRadius = new CornerRadius(23),
Background = new SolidColorBrush(((SolidColorBrush)btnColor).Color) { Opacity = 0.15 },
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness(0, 0, 0, 10),
Margin = new Thickness(0, 0, 0, 12),
};
var iconTb = new TextBlock
{
Text = preset.Symbol,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 18.5,
FontSize = 20,
Foreground = btnColor,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
@@ -12148,13 +12156,13 @@ public partial class ChatWindow : Window
stack.Children.Add(new TextBlock
{
Text = preset.Label,
FontSize = 14,
FontSize = 15.5,
FontWeight = FontWeights.SemiBold,
Foreground = primaryText,
HorizontalAlignment = HorizontalAlignment.Center,
TextAlignment = TextAlignment.Center,
TextWrapping = TextWrapping.Wrap,
MaxWidth = 98,
MaxWidth = 112,
});
var hoverLabel = new Border
@@ -12172,10 +12180,10 @@ public partial class ChatWindow : Window
Child = new TextBlock
{
Text = preset.Description,
FontSize = 10.5,
FontSize = 11.5,
TextWrapping = TextWrapping.Wrap,
TextTrimming = TextTrimming.CharacterEllipsis,
MaxHeight = 30,
MaxHeight = 34,
Foreground = secondaryText,
TextAlignment = TextAlignment.Center,
}
@@ -12244,8 +12252,8 @@ public partial class ChatWindow : Window
Padding = new Thickness(14, 14, 14, 12),
Margin = new Thickness(6, 6, 6, 8),
Cursor = Cursors.Hand,
Width = 132,
Height = 110,
Width = 148,
Height = 124,
ClipToBounds = true,
};
@@ -12258,17 +12266,17 @@ public partial class ChatWindow : Window
var etcIconCircle = new Border
{
Width = 42, Height = 42,
CornerRadius = new CornerRadius(21),
Width = 46, Height = 46,
CornerRadius = new CornerRadius(23),
Background = new SolidColorBrush(((SolidColorBrush)etcColor).Color) { Opacity = 0.15 },
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness(0, 0, 0, 10),
Margin = new Thickness(0, 0, 0, 12),
};
etcIconCircle.Child = new TextBlock
{
Text = "\uE70F", // Edit 아이콘
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 18.5,
FontSize = 20,
Foreground = etcColor,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
@@ -12278,7 +12286,7 @@ public partial class ChatWindow : Window
etcStack.Children.Add(new TextBlock
{
Text = "기타",
FontSize = 14,
FontSize = 15.5,
FontWeight = FontWeights.SemiBold,
Foreground = primaryText,
HorizontalAlignment = HorizontalAlignment.Center,
@@ -12299,10 +12307,10 @@ public partial class ChatWindow : Window
Child = new TextBlock
{
Text = "프리셋 없이 자유롭게 대화합니다",
FontSize = 10.5,
FontSize = 11.5,
TextWrapping = TextWrapping.Wrap,
TextTrimming = TextTrimming.CharacterEllipsis,
MaxHeight = 30,
MaxHeight = 34,
Foreground = secondaryText,
TextAlignment = TextAlignment.Center,
}
@@ -12334,8 +12342,8 @@ public partial class ChatWindow : Window
Padding = new Thickness(14, 14, 14, 12),
Margin = new Thickness(6, 6, 6, 8),
Cursor = Cursors.Hand,
Width = 132,
Height = 110,
Width = 148,
Height = 124,
ClipToBounds = true,
};
@@ -12347,17 +12355,17 @@ public partial class ChatWindow : Window
{
Text = "\uE710",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 24,
FontSize = 26,
Foreground = secondaryText,
HorizontalAlignment = HorizontalAlignment.Center,
Margin = new Thickness(0, 10, 0, 8),
Margin = new Thickness(0, 12, 0, 10),
};
addStack.Children.Add(plusIcon);
addStack.Children.Add(new TextBlock
{
Text = "프리셋 추가",
FontSize = 13,
FontSize = 14.5,
FontWeight = FontWeights.SemiBold,
Foreground = secondaryText,
HorizontalAlignment = HorizontalAlignment.Center,
@@ -12378,10 +12386,10 @@ public partial class ChatWindow : Window
Child = new TextBlock
{
Text = "새 작업 유형 카드를 직접 추가합니다",
FontSize = 10.5,
FontSize = 11.5,
TextWrapping = TextWrapping.Wrap,
TextTrimming = TextTrimming.CharacterEllipsis,
MaxHeight = 30,
MaxHeight = 34,
Foreground = secondaryText,
TextAlignment = TextAlignment.Center,
}
@@ -18702,10 +18710,59 @@ private static (string icon, string label, string bgHex, string fgHex) GetDecisi
postCompactionUsage +
pendingPostCompaction;
if (TokenUsagePopupTitle != null)
TokenUsagePopupTitle.Text = $"컨텍스트 창 {percentText}";
if (TokenUsagePopupUsage != null)
TokenUsagePopupUsage.Text = $"{Services.TokenEstimator.Format(currentTokens)}/{Services.TokenEstimator.Format(maxContextTokens)}";
if (TokenUsagePopupDetail != null)
{
TokenUsagePopupDetail.Text = currentModelTotalTokens > 0
? $"오늘 {currentService} · {currentModel} 사용량 {FormatTokenCount(currentModelTotalTokens)}"
: $"{summary} · 자동 압축 시작 {triggerPercent}%";
}
if (TokenUsagePopupCompact != null)
{
var compactText = compactLabel switch
{
"지금 압축" => "지금 압축이 필요합니다",
"압축 권장" => "곧 자동 압축이 시작됩니다",
"미리 압축" => "여유가 있을 때 먼저 압축할 수 있습니다",
_ => "AX Agent가 컨텍스트를 자동으로 관리합니다",
};
TokenUsagePopupCompact.Text = compactText;
}
TokenUsageCard.ToolTip = null;
UpdateCircularUsageArc(TokenUsageArc, usageRatio, 18, 18, 14);
PositionThresholdMarker(TokenUsageThresholdMarker, triggerRatio, 18, 18, 14, 3);
}
private void TokenUsageCard_MouseEnter(object sender, MouseEventArgs e)
{
_tokenUsagePopupCloseTimer.Stop();
if (TokenUsagePopup != null && TokenUsageCard?.Visibility == Visibility.Visible)
TokenUsagePopup.IsOpen = true;
}
private void TokenUsageCard_MouseLeave(object sender, MouseEventArgs e)
{
_tokenUsagePopupCloseTimer.Stop();
_tokenUsagePopupCloseTimer.Start();
}
private void TokenUsagePopup_MouseEnter(object sender, MouseEventArgs e)
{
_tokenUsagePopupCloseTimer.Stop();
if (TokenUsagePopup != null)
TokenUsagePopup.IsOpen = true;
}
private void TokenUsagePopup_MouseLeave(object sender, MouseEventArgs e)
{
_tokenUsagePopupCloseTimer.Stop();
_tokenUsagePopupCloseTimer.Start();
}
private static string BuildUsageModelKey(string? service, string? model)
{
var normalizedService = (service ?? "").Trim().ToLowerInvariant();