채팅 본문 폭과 진행 로그 줄바꿈 레이아웃 개선
채팅 본문과 process feed가 큰 창의 오른쪽 여백을 더 활용하도록 반응형 폭 계산을 조정했습니다. 본문 최대폭을 1040, 입력창 폭을 980 기준까지 확장하고 MessageList 최대폭을 함께 늘려 조기 말줄임이 덜 발생하도록 정리했습니다. process feed 헤더, 실행 이력 요약, 라이브 thinking 줄은 줄바꿈 우선으로 바꾸고 필요한 미리보기 카드에만 ellipsis를 남겼습니다. 입력창 위 StreamMetricsLabel과 PulseDotBar 간격도 다시 맞춰 우측 시간·토큰 표시가 좌측 진행 문구 폭을 과하게 잠식하지 않도록 보정했습니다. 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\verify_chat_width_wrap\ -p:IntermediateOutputPath=obj\verify_chat_width_wrap\ (경고 0 / 오류 0), dotnet test src/AxCopilot.Tests/AxCopilot.Tests.csproj -c Release -v minimal --filter ChatStreamingUiPolicyTests^|ChatWindowSlashPolicyTests -p:OutputPath=bin\verify_chat_width_wrap_tests\ -p:IntermediateOutputPath=obj\verify_chat_width_wrap_tests\ (통과 74)
This commit is contained in:
@@ -287,6 +287,7 @@ public partial class ChatWindow
|
||||
MaxWidth = msgMaxWidth,
|
||||
Margin = new Thickness(62, 1, 12, 1),
|
||||
};
|
||||
var headerTextMaxWidth = Math.Max(180, msgMaxWidth - 28);
|
||||
|
||||
if (liveWaitingStyle)
|
||||
{
|
||||
@@ -324,6 +325,8 @@ public partial class ChatWindow
|
||||
FontSize = 12,
|
||||
Foreground = secondaryText,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = headerTextMaxWidth,
|
||||
});
|
||||
stack.Children.Add(waitRow);
|
||||
}
|
||||
@@ -360,7 +363,8 @@ public partial class ChatWindow
|
||||
FontSize = 12,
|
||||
Foreground = headerColor,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
TextTrimming = TextTrimming.CharacterEllipsis,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = headerTextMaxWidth,
|
||||
});
|
||||
|
||||
stack.Children.Add(headerRow);
|
||||
@@ -543,7 +547,8 @@ public partial class ChatWindow
|
||||
FontSize = 12,
|
||||
Foreground = secondaryText,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
TextTrimming = TextTrimming.CharacterEllipsis,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = Math.Max(180, msgMaxWidth - 28),
|
||||
});
|
||||
container.Children.Add(headerRow);
|
||||
|
||||
@@ -568,7 +573,8 @@ public partial class ChatWindow
|
||||
FontSize = 11,
|
||||
Foreground = secondaryText,
|
||||
Opacity = 0.75,
|
||||
TextTrimming = TextTrimming.CharacterEllipsis,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = Math.Max(180, msgMaxWidth - 16),
|
||||
Margin = new Thickness(0, 1, 0, 0),
|
||||
};
|
||||
if (!string.IsNullOrWhiteSpace(evt.FilePath))
|
||||
@@ -1842,6 +1848,7 @@ public partial class ChatWindow
|
||||
MaxWidth = msgMaxWidth2,
|
||||
Margin = new Thickness(62, 1, 12, 1),
|
||||
};
|
||||
var headerTextMaxWidth2 = Math.Max(180, msgMaxWidth2 - 28);
|
||||
if (!string.IsNullOrWhiteSpace(evt.RunId))
|
||||
_runBannerAnchors[evt.RunId] = stack2;
|
||||
|
||||
@@ -1874,7 +1881,8 @@ public partial class ChatWindow
|
||||
FontSize = 12,
|
||||
Foreground = headerColor2,
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
TextTrimming = TextTrimming.CharacterEllipsis,
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = headerTextMaxWidth2,
|
||||
});
|
||||
|
||||
stack2.Children.Add(headerRow2);
|
||||
|
||||
@@ -212,16 +212,19 @@ public partial class ChatWindow
|
||||
/// <summary>채팅 본문 폭을 세 탭에서 동일한 기준으로 맞춥니다.</summary>
|
||||
private double GetMessageMaxWidth()
|
||||
{
|
||||
if (_lastResponsiveMessageWidth >= 100)
|
||||
return Math.Clamp(_lastResponsiveMessageWidth, 320, 1040);
|
||||
|
||||
var hostWidth = _lastResponsiveComposerWidth;
|
||||
if (hostWidth < 100)
|
||||
hostWidth = ComposerShell?.ActualWidth ?? 0;
|
||||
if (hostWidth < 100)
|
||||
hostWidth = MessageList?.ActualWidth ?? 0;
|
||||
if (hostWidth < 100)
|
||||
hostWidth = 1120;
|
||||
hostWidth = 1280;
|
||||
|
||||
var maxW = hostWidth - 44;
|
||||
return Math.Clamp(maxW, 320, 760);
|
||||
var maxW = hostWidth - 24;
|
||||
return Math.Clamp(maxW, 320, 1040);
|
||||
}
|
||||
|
||||
private bool UpdateResponsiveChatLayout()
|
||||
@@ -234,17 +237,17 @@ public partial class ChatWindow
|
||||
|
||||
// 메시지 축과 입력축이 같은 중심선을 공유하도록
|
||||
// 본문 폭 상한을 조금 더 낮추고 창 폭 변화에 더 부드럽게 반응시킵니다.
|
||||
var contentWidth = Math.Max(360, viewportWidth - 24);
|
||||
// 고정 최대폭 — 큰 창에서 안정적, 작은 창에서만 축소
|
||||
var messageWidth = Math.Min(contentWidth - 10, 800);
|
||||
var composerWidth = Math.Min(contentWidth - 24, 760);
|
||||
var contentWidth = Math.Max(360, viewportWidth - 12);
|
||||
// 큰 창에서는 본문을 더 넓게 쓰고, 입력창은 약간만 좁게 유지합니다.
|
||||
var messageWidth = Math.Min(contentWidth - 8, 1040);
|
||||
var composerWidth = Math.Min(contentWidth - 12, 980);
|
||||
|
||||
var changed = false;
|
||||
if (Math.Abs(_lastResponsiveMessageWidth - messageWidth) > 8)
|
||||
{
|
||||
_lastResponsiveMessageWidth = messageWidth;
|
||||
if (MessageList != null)
|
||||
MessageList.MaxWidth = messageWidth + 48;
|
||||
MessageList.MaxWidth = messageWidth + 64;
|
||||
if (EmptyState != null)
|
||||
EmptyState.MaxWidth = messageWidth;
|
||||
changed = true;
|
||||
|
||||
@@ -338,18 +338,21 @@ public partial class ChatWindow
|
||||
|
||||
case AgentEventType.Thinking:
|
||||
{
|
||||
var thinkingSummaryMaxLength = msgMaxWidth > 900 ? 220 : 140;
|
||||
var thinkText = AgentProgressSummarySanitizer.NormalizeThinkingSummary(
|
||||
agentEvent.Summary,
|
||||
agentEvent.ToolName,
|
||||
maxLength: 100);
|
||||
maxLength: thinkingSummaryMaxLength);
|
||||
if (string.IsNullOrWhiteSpace(thinkText)) break;
|
||||
|
||||
var thinkRow = new StackPanel
|
||||
var thinkRow = new Grid
|
||||
{
|
||||
Orientation = Orientation.Horizontal,
|
||||
Margin = new Thickness(22, 2, 0, 2),
|
||||
};
|
||||
thinkRow.Children.Add(new TextBlock
|
||||
thinkRow.ColumnDefinitions.Add(new ColumnDefinition { Width = GridLength.Auto });
|
||||
thinkRow.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
|
||||
|
||||
var thinkIcon = new TextBlock
|
||||
{
|
||||
Text = "\uE915",
|
||||
FontFamily = s_segoeIconFont,
|
||||
@@ -357,17 +360,23 @@ public partial class ChatWindow
|
||||
Foreground = new SolidColorBrush(Color.FromRgb(0x59, 0xA5, 0xF5)),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
Margin = new Thickness(0, 0, 4, 0),
|
||||
});
|
||||
thinkRow.Children.Add(new TextBlock
|
||||
};
|
||||
Grid.SetColumn(thinkIcon, 0);
|
||||
thinkRow.Children.Add(thinkIcon);
|
||||
|
||||
var thinkLabel = new TextBlock
|
||||
{
|
||||
Text = thinkText,
|
||||
FontSize = 10.5,
|
||||
FontStyle = FontStyles.Italic,
|
||||
Foreground = secondaryText,
|
||||
Opacity = 0.82,
|
||||
TextTrimming = TextTrimming.CharacterEllipsis,
|
||||
MaxWidth = msgMaxWidth - 60,
|
||||
});
|
||||
TextWrapping = TextWrapping.Wrap,
|
||||
MaxWidth = Math.Max(180, msgMaxWidth - 52),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
Grid.SetColumn(thinkLabel, 1);
|
||||
thinkRow.Children.Add(thinkLabel);
|
||||
_v2LiveContainer.Children.Add(thinkRow);
|
||||
AutoScrollIfNeeded();
|
||||
break;
|
||||
@@ -432,11 +441,12 @@ public partial class ChatWindow
|
||||
return;
|
||||
|
||||
var narrative = AgentStatusNarrativeCatalog.BuildFromEvent(agentEvent, _activeTab);
|
||||
var statusSummaryMaxLength = GetMessageMaxWidth() > 900 ? 260 : 180;
|
||||
var normalizedThinking = agentEvent.Type == AgentEventType.Thinking
|
||||
? AgentProgressSummarySanitizer.NormalizeThinkingSummary(
|
||||
agentEvent.Summary,
|
||||
agentEvent.ToolName,
|
||||
maxLength: 160)
|
||||
maxLength: statusSummaryMaxLength)
|
||||
: string.Empty;
|
||||
var message = string.IsNullOrWhiteSpace(normalizedThinking)
|
||||
? narrative.Message
|
||||
|
||||
@@ -2166,7 +2166,7 @@
|
||||
<Border x:Name="ComposerShell" Grid.Row="4"
|
||||
Margin="24,0,24,12"
|
||||
Width="Auto"
|
||||
MaxWidth="900"
|
||||
MaxWidth="980"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalAlignment="Bottom">
|
||||
<StackPanel HorizontalAlignment="Stretch">
|
||||
@@ -2181,9 +2181,9 @@
|
||||
<Border x:Name="PulseDotBar"
|
||||
Grid.Column="0"
|
||||
Visibility="Collapsed"
|
||||
HorizontalAlignment="Left"
|
||||
HorizontalAlignment="Stretch"
|
||||
VerticalAlignment="Center"
|
||||
Margin="6,0,0,0">
|
||||
Margin="6,0,18,0">
|
||||
<StackPanel>
|
||||
<!-- 레거시 펄스 점 (코드비하인드 참조용, 화면에 표시 안 함) -->
|
||||
<Ellipse x:Name="PulseDot1" Width="7" Height="7" Fill="{DynamicResource AccentColor}" Opacity="0.3" Visibility="Collapsed"/>
|
||||
@@ -2262,7 +2262,7 @@
|
||||
Visibility="Collapsed"
|
||||
HorizontalAlignment="Right"
|
||||
VerticalAlignment="Bottom"
|
||||
Margin="12,0,6,2"
|
||||
Margin="18,0,0,2"
|
||||
FontSize="11"
|
||||
Foreground="{DynamicResource SecondaryText}"
|
||||
Opacity="0.7"
|
||||
|
||||
Reference in New Issue
Block a user