AX Agent transcript 호스트를 컬렉션 기반으로 재구성해 코워크·코드 스트리밍 중 UI 부하를 줄임
Some checks failed
Release Gate / gate (push) Has been cancelled
Some checks failed
Release Gate / gate (push) Has been cancelled
- 메시지 영역을 ScrollViewer+StackPanel 직접 조작 구조에서 ListBox+ObservableCollection 기반 transcript 호스트로 전환 - ChatWindow.TranscriptHost 도입으로 transcript 요소 추가·교체·삭제·스크롤 접근을 공용 helper로 정리 - 코워크/코드 실행 중 RenderMessages와 라이브 카드가 MessagePanel.Children 직접 조작에 덜 의존하도록 정리 - MessageBubble, AgentEventRendering, Timeline, UserAsk, ConversationManagement 등 transcript 관련 partial을 새 호스트 구조에 맞게 전환 - 향후 claw-code의 VirtualMessageList 수준 가상화를 적용할 수 있는 기반을 마련 - README와 DEVELOPMENT 문서를 2026-04-08 12:52 (KST) 기준으로 갱신 - 검증: dotnet build src/AxCopilot/AxCopilot.csproj -c Release -v minimal -p:OutputPath=bin\\verify\\ -p:IntermediateOutputPath=obj\\verify\\ (경고 0, 오류 0)
This commit is contained in:
101
src/AxCopilot/Views/ChatWindow.TranscriptHost.cs
Normal file
101
src/AxCopilot/Views/ChatWindow.TranscriptHost.cs
Normal file
@@ -0,0 +1,101 @@
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace AxCopilot.Views;
|
||||
|
||||
public partial class ChatWindow
|
||||
{
|
||||
private readonly ObservableCollection<UIElement> _transcriptElements = [];
|
||||
private ScrollViewer? _transcriptScrollViewer;
|
||||
private bool _transcriptScrollHooked;
|
||||
|
||||
private void InitializeTranscriptHost()
|
||||
{
|
||||
MessageList.ItemsSource = _transcriptElements;
|
||||
AttachTranscriptScrollChanged();
|
||||
MessageList.Loaded += (_, _) => AttachTranscriptScrollChanged();
|
||||
}
|
||||
|
||||
private void AttachTranscriptScrollChanged()
|
||||
{
|
||||
var scrollViewer = FindVisualChild<ScrollViewer>(MessageList);
|
||||
if (scrollViewer == null || ReferenceEquals(scrollViewer, _transcriptScrollViewer))
|
||||
return;
|
||||
|
||||
if (_transcriptScrollViewer != null && _transcriptScrollHooked)
|
||||
{
|
||||
_transcriptScrollViewer.ScrollChanged -= MessageScroll_ScrollChanged;
|
||||
}
|
||||
|
||||
_transcriptScrollViewer = scrollViewer;
|
||||
_transcriptScrollViewer.ScrollChanged += MessageScroll_ScrollChanged;
|
||||
_transcriptScrollHooked = true;
|
||||
}
|
||||
|
||||
private static T? FindVisualChild<T>(DependencyObject? parent)
|
||||
where T : DependencyObject
|
||||
{
|
||||
if (parent == null)
|
||||
return null;
|
||||
|
||||
var childCount = VisualTreeHelper.GetChildrenCount(parent);
|
||||
for (var i = 0; i < childCount; i++)
|
||||
{
|
||||
var child = VisualTreeHelper.GetChild(parent, i);
|
||||
if (child is T match)
|
||||
return match;
|
||||
|
||||
var descendant = FindVisualChild<T>(child);
|
||||
if (descendant != null)
|
||||
return descendant;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private int GetTranscriptElementCount() => _transcriptElements.Count;
|
||||
|
||||
private UIElement? GetTranscriptElementAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= _transcriptElements.Count)
|
||||
return null;
|
||||
|
||||
return _transcriptElements[index];
|
||||
}
|
||||
|
||||
private int GetTranscriptElementIndex(UIElement element) => _transcriptElements.IndexOf(element);
|
||||
|
||||
private bool ContainsTranscriptElement(UIElement element) => _transcriptElements.Contains(element);
|
||||
|
||||
private void AddTranscriptElement(UIElement element) => _transcriptElements.Add(element);
|
||||
|
||||
private void ClearTranscriptElements() => _transcriptElements.Clear();
|
||||
|
||||
private void RemoveTranscriptElement(UIElement element) => _transcriptElements.Remove(element);
|
||||
|
||||
private void RemoveTranscriptElementAt(int index)
|
||||
{
|
||||
if (index < 0 || index >= _transcriptElements.Count)
|
||||
return;
|
||||
|
||||
_transcriptElements.RemoveAt(index);
|
||||
}
|
||||
|
||||
private void ReplaceTranscriptElement(int index, UIElement element)
|
||||
{
|
||||
if (index < 0 || index >= _transcriptElements.Count)
|
||||
return;
|
||||
|
||||
_transcriptElements[index] = element;
|
||||
}
|
||||
|
||||
private double GetTranscriptScrollableHeight() => _transcriptScrollViewer?.ScrollableHeight ?? 0;
|
||||
|
||||
private double GetTranscriptVerticalOffset() => _transcriptScrollViewer?.VerticalOffset ?? 0;
|
||||
|
||||
private void ScrollTranscriptToEnd() => _transcriptScrollViewer?.ScrollToEnd();
|
||||
|
||||
private void ScrollTranscriptToVerticalOffset(double offset) => _transcriptScrollViewer?.ScrollToVerticalOffset(offset);
|
||||
}
|
||||
Reference in New Issue
Block a user