From b24afba2d8634431f08700984e87e4444671202e Mon Sep 17 00:00:00 2001 From: lacvet Date: Sun, 5 Apr 2026 13:13:15 +0900 Subject: [PATCH] =?UTF-8?q?AX=20Agent=20=EC=B1=84=ED=8C=85=EC=B0=BD=20?= =?UTF-8?q?=EB=B0=98=EC=9D=91=ED=98=95=20=ED=8F=AD=20=EA=B3=84=EC=82=B0=20?= =?UTF-8?q?=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ChatWindow의 ComposerShell 고정폭을 제거하고 실제 본문 영역 폭 기준으로 MessagePanel, EmptyState, ComposerShell을 함께 재계산하도록 정리함 - 창 크기 변경 시 메시지 축과 입력창이 자연스럽게 함께 줄고 늘어나도록 Loaded와 SizeChanged에 반응형 레이아웃 갱신을 연결함 - README와 DEVELOPMENT 문서에 2026-04-05 14:16 (KST) 기준 작업 이력을 반영하고 Release 빌드 경고 0 오류 0을 확인함 --- README.md | 4 +- docs/DEVELOPMENT.md | 4 +- src/AxCopilot/Views/ChatWindow.xaml | 4 +- src/AxCopilot/Views/ChatWindow.xaml.cs | 65 ++++++++++++++++++++++++-- 4 files changed, 68 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index a94cfb9..bf53020 100644 --- a/README.md +++ b/README.md @@ -773,8 +773,10 @@ ow + toggle 시각 언어로 통일했습니다. - 업데이트: 2026-04-05 14:00 (KST) - 메시지 행 UI도 `claw-code` 기준으로 한 단계 더 눌렀습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml) 의 `MessagePanel` 하단 여백을 더 줄여 본문 축이 컴포저와 가깝게 이어지도록 했고, [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 에서 사용자/assistant 메시지 카드의 좌우 마진, 코너 라운드, 패딩, 폰트 크기, 타임스탬프 크기를 전반적으로 낮췄습니다. - assistant 헤더는 아이콘과 이름을 더 작고 옅게 줄였고, 액션 바 버튼도 패딩과 간격을 축소해 메시지 본문보다 덜 튀게 만들었습니다. 같은 방향으로 실행 로그 배너(`AddAgentEventBanner`)도 좌우 마진, 아이콘/라벨 크기, 토큰 배지와 요약 텍스트 밀도를 낮춰, Cowork/Code에서 로그가 메시지보다 먼저 보이던 느낌을 줄였습니다. +- 폭 계산도 `claw-code`처럼 반응형으로 다시 맞췄습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml)의 `ComposerShell` 고정폭을 걷어내고, [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `UpdateResponsiveChatLayout()`가 실제 본문 폭 기준으로 `MessagePanel`, `EmptyState`, `ComposerShell` 폭을 함께 다시 계산하도록 연결했습니다. +- 이제 창이 작아질 때 메시지 축과 입력창이 따로 놀지 않고 같은 축으로 같이 줄어들며, 창이 넓을 때는 적당한 상한을 유지한 채 자연스럽게 넓어집니다. 초기 로드와 `SizeChanged` 모두 같은 반응형 계산을 타도록 붙였습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\` 경고 0 / 오류 0 -- 업데이트: 2026-04-05 14:09 (KST) +- 업데이트: 2026-04-05 14:16 (KST) --- diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 2caa48e..7e2bfce 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4536,5 +4536,7 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - 빈 상태는 부유 애니메이션이 있는 그라디언트 아이콘을 제거하고, 작은 정적 카드형 아이콘 + 짧은 문구로 바꿨습니다. 상단 `AgentProgressBar`는 패딩과 프로그레스 바 높이를 줄였고, 컴포저는 `800px` 축으로 넓히면서 `DraftPreviewCard`, `InputGlowBorder`, `InputBorder`의 라운드/그림자 강도를 낮춰 장식량을 줄였습니다. - 메시지 행 자체도 `claw-code` 방향으로 더 눌렀습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml)의 `MessagePanel` 하단 여백을 줄였고, [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)의 `AddMessageBubble(...)`에서 사용자/assistant 카드의 좌우 마진, 코너 라운드, 패딩, 폰트 크기, 타임스탬프 크기를 전반적으로 축소했습니다. - assistant 헤더는 아이콘/이름을 더 작고 옅게 조정해 메시지 본문이 먼저 읽히도록 바꿨고, 액션 바 버튼도 패딩과 간격을 줄여 hover 시에도 과하게 튀지 않게 맞췄습니다. `AddAgentEventBanner(...)` 역시 좌우 마진, 아이콘/라벨, 토큰 배지, 요약 텍스트 밀도를 함께 낮춰 실행 로그가 본문보다 먼저 보이던 시각적 압박을 줄였습니다. +- 폭 계산도 `claw-code`식 반응형 축으로 다시 맞췄습니다. [ChatWindow.xaml](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml)의 `ComposerShell` 고정폭을 제거하고, [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs)에 `UpdateResponsiveChatLayout()`를 추가해 `MessageScroll.ActualWidth` 기준으로 `MessagePanel`, `EmptyState`, `ComposerShell` 폭을 함께 다시 계산합니다. +- 이 변경으로 창이 줄어들 때 메시지 축과 컴포저가 함께 자연스럽게 줄고, 넓어질 때는 적절한 상한만 유지한 채 부드럽게 넓어집니다. 초기 `Loaded`와 창 `SizeChanged` 둘 다 같은 계산 경로를 타게 연결했습니다. - 검증: `dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify\ -p:IntermediateOutputPath=obj\verify\` 경고 0 / 오류 0 -- 업데이트: 2026-04-05 14:09 (KST) +- 업데이트: 2026-04-05 14:16 (KST) diff --git a/src/AxCopilot/Views/ChatWindow.xaml b/src/AxCopilot/Views/ChatWindow.xaml index 8febb16..78323ae 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml +++ b/src/AxCopilot/Views/ChatWindow.xaml @@ -1552,8 +1552,8 @@ diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index a996b8e..d231a6f 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -124,6 +124,8 @@ public partial class ChatWindow : Window private readonly Dictionary _pendingConversationPersists = new(StringComparer.OrdinalIgnoreCase); private readonly HashSet _expandedDraftQueueTabs = new(StringComparer.OrdinalIgnoreCase); private AgentEvent? _pendingAgentUiEvent; + private double _lastResponsiveComposerWidth; + private double _lastResponsiveMessageWidth; private void ApplyQuickActionVisual(Button button, bool active, string activeBg, string activeFg) { if (button?.Content is not string text) @@ -288,6 +290,7 @@ public partial class ChatWindow : Window UpdateSidebarModeMenu(); RefreshContextUsageVisual(); UpdateTopicPresetScrollMode(); + UpdateResponsiveChatLayout(); UpdateInputBoxHeight(); InputBox.Focus(); MessageScroll.ScrollChanged += MessageScroll_ScrollChanged; @@ -299,6 +302,7 @@ public partial class ChatWindow : Window BuildTopicButtons(); RestoreLastConversations(); RefreshConversationList(); + UpdateResponsiveChatLayout(); UpdateTaskSummaryIndicators(); ScheduleGitBranchRefresh(); @@ -369,7 +373,12 @@ public partial class ChatWindow : Window ApplyHoverScaleAnimation(BtnSend, 1.12); ApplyHoverScaleAnimation(BtnStop, 1.12); }; - SizeChanged += (_, _) => UpdateTopicPresetScrollMode(); + SizeChanged += (_, _) => + { + UpdateTopicPresetScrollMode(); + if (UpdateResponsiveChatLayout()) + RenderMessages(preserveViewport: true); + }; Closed += (_, _) => { _settings.SettingsChanged -= Settings_SettingsChanged; @@ -11045,15 +11054,61 @@ public partial class ChatWindow : Window /// 채팅 본문 폭을 세 탭에서 동일한 기준으로 맞춥니다. private double GetMessageMaxWidth() { - var hostWidth = ComposerShell?.ActualWidth ?? 0; + var hostWidth = _lastResponsiveComposerWidth; + if (hostWidth < 100) + hostWidth = ComposerShell?.ActualWidth ?? 0; if (hostWidth < 100) hostWidth = MessageScroll?.ActualWidth ?? 0; if (hostWidth < 100) - hostWidth = 1120; // 초기화 전 기준 폭 + hostWidth = 1120; - // 컴포저와 메시지 버블이 같은 레이아웃 축을 쓰도록 여백만 제외한 폭을 공통 적용 var maxW = hostWidth - 44; - return Math.Clamp(maxW, 320, 720); + return Math.Clamp(maxW, 320, 760); + } + + private bool UpdateResponsiveChatLayout() + { + var viewportWidth = MessageScroll?.ActualWidth ?? 0; + if (viewportWidth < 200) + viewportWidth = ActualWidth; + if (viewportWidth < 200) + return false; + + // claw-code처럼 창이 줄어들면 메시지 축과 컴포저가 함께 자연스럽게 줄어들도록, + // 남는 본문 폭을 기준으로 상한만 두고 반응형 폭을 다시 계산합니다. + var contentWidth = Math.Max(360, viewportWidth - 48); + var messageWidth = Math.Clamp(contentWidth * 0.9, 360, 920); + var composerWidth = Math.Clamp(contentWidth * 0.82, 360, 820); + + if (contentWidth < 760) + { + messageWidth = Math.Clamp(contentWidth - 8, 340, 820); + composerWidth = Math.Clamp(contentWidth - 28, 332, 760); + } + + var changed = false; + if (Math.Abs(_lastResponsiveMessageWidth - messageWidth) > 1) + { + _lastResponsiveMessageWidth = messageWidth; + if (MessagePanel != null) + MessagePanel.MaxWidth = messageWidth; + if (EmptyState != null) + EmptyState.MaxWidth = messageWidth; + changed = true; + } + + if (Math.Abs(_lastResponsiveComposerWidth - composerWidth) > 1) + { + _lastResponsiveComposerWidth = composerWidth; + if (ComposerShell != null) + { + ComposerShell.Width = composerWidth; + ComposerShell.MaxWidth = composerWidth; + } + changed = true; + } + + return changed; } private StackPanel CreateStreamingContainer(out TextBlock streamText)