diff --git a/README.md b/README.md index 2f150fa..dff65ca 100644 --- a/README.md +++ b/README.md @@ -1191,3 +1191,6 @@ MIT License - 업데이트: 2026-04-06 10:56 (KST) - 대화 목록 관리 interaction을 [ChatWindow.ConversationManagementPresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.ConversationManagementPresentation.cs) 로 분리했다. 제목 인라인 편집 `EnterTitleEditMode(...)` 와 대화 메뉴 `ShowConversationMenu(...)`가 메인 [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 밖으로 이동해, 고정/이름 변경/카테고리 변경/삭제 같은 목록 관리 UI 책임도 별도 presentation surface에서 다루게 정리했다. - 이 단계까지 완료된 구조 개선은 상태선/권한/도구 결과 카탈로그화, inline ask/plan 분리, footer/Git/preset/list/message/timeline 분리, 그리고 conversation management 분리까지다. 이제 남은 건 큰 구조 개선이 아니라 개별 surface polish와 후속 UX 고도화 수준이다. +- 업데이트: 2026-04-06 11:03 (KST) + - 좌측 sidebar의 검색/새 대화 interaction을 [ChatWindow.SidebarInteractionPresentation.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.SidebarInteractionPresentation.cs) 로 분리했다. 검색 트리거 hover, 새 대화 hover, 검색 열기/닫기 애니메이션이 메인 [ChatWindow.xaml.cs](/E:/AX%20Copilot%20-%20Codex/src/AxCopilot/Views/ChatWindow.xaml.cs) 밖으로 이동해, 메인 창은 runtime/transcript orchestration에 더 집중하고 sidebar UX는 별도 presentation surface에서 다루게 정리했다. + - 큰 구조 개선 계획 기준으로는 이제 sidebar interaction까지 분리 완료 상태이며, 이후 남는 작업은 공통 시각 언어 polish나 실제 사용 흐름 기반 미세 UX 튜닝 같은 후속 개선 영역이다. diff --git a/docs/DEVELOPMENT.md b/docs/DEVELOPMENT.md index 7e087cd..ca05bdb 100644 --- a/docs/DEVELOPMENT.md +++ b/docs/DEVELOPMENT.md @@ -4931,3 +4931,5 @@ ow + toggle ?쒓컖 ?몄뼱濡??ㅼ떆 ?뺣젹?덈떎. - Document update: 2026-04-06 10:44 (KST) - This consolidates timeline-related helpers in one place and leaves the main chat window file with less transcript-specific rendering logic around `RenderMessages()`. - Document update: 2026-04-06 10:56 (KST) - Split conversation-management interactions out of `ChatWindow.xaml.cs` into `ChatWindow.ConversationManagementPresentation.cs`. Inline title editing and the conversation action popup (pin/unpin, rename, category change, delete) now live in a dedicated presentation partial. - Document update: 2026-04-06 10:56 (KST) - With this pass, the remaining large structure-improvement track is effectively complete; follow-up work is now mostly UX polish and surface-level tuning rather than further decomposition of the main chat window orchestration file. +- Document update: 2026-04-06 11:03 (KST) - Split sidebar search/new-chat interactions out of `ChatWindow.xaml.cs` into `ChatWindow.SidebarInteractionPresentation.cs`. Hover state changes, sidebar search open/close transitions, and new-chat trigger behavior now live in a dedicated presentation partial. +- Document update: 2026-04-06 11:03 (KST) - This leaves the main chat window even more orchestration-focused and effectively closes the last obvious sidebar interaction block from the large structure-improvement plan. Remaining work is now follow-up UX polish rather than major decomposition. diff --git a/src/AxCopilot/Views/ChatWindow.SidebarInteractionPresentation.cs b/src/AxCopilot/Views/ChatWindow.SidebarInteractionPresentation.cs new file mode 100644 index 0000000..6eece17 --- /dev/null +++ b/src/AxCopilot/Views/ChatWindow.SidebarInteractionPresentation.cs @@ -0,0 +1,107 @@ +using System; +using System.Windows; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Animation; +using System.Windows.Threading; + +namespace AxCopilot.Views; + +public partial class ChatWindow +{ + private void SidebarSearchTrigger_MouseEnter(object sender, MouseEventArgs e) + { + if (SidebarSearchTrigger != null) + SidebarSearchTrigger.Background = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; + if (SidebarSearchShortcutHint != null) + SidebarSearchShortcutHint.Visibility = Visibility.Visible; + } + + private void SidebarSearchTrigger_MouseLeave(object sender, MouseEventArgs e) + { + if (SidebarSearchTrigger != null) + SidebarSearchTrigger.Background = Brushes.Transparent; + if (SidebarSearchShortcutHint != null) + SidebarSearchShortcutHint.Visibility = Visibility.Collapsed; + } + + private void SidebarSearchTrigger_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + OpenSidebarSearch(); + } + + private void SidebarNewChatTrigger_MouseEnter(object sender, MouseEventArgs e) + { + if (SidebarNewChatTrigger != null) + SidebarNewChatTrigger.Background = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; + if (SidebarNewChatShortcutHint != null) + SidebarNewChatShortcutHint.Visibility = Visibility.Visible; + } + + private void SidebarNewChatTrigger_MouseLeave(object sender, MouseEventArgs e) + { + if (SidebarNewChatTrigger != null) + SidebarNewChatTrigger.Background = Brushes.Transparent; + if (SidebarNewChatShortcutHint != null) + SidebarNewChatShortcutHint.Visibility = Visibility.Collapsed; + } + + private void SidebarNewChatTrigger_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) + { + BtnNewChat_Click(sender, new RoutedEventArgs()); + } + + private void BtnSidebarSearchClose_Click(object sender, RoutedEventArgs e) + { + CloseSidebarSearch(clearText: true); + } + + private void OpenSidebarSearch() + { + if (SidebarSearchEditor == null || SidebarSearchTrigger == null || SidebarSearchEditorScale == null) + return; + + SidebarSearchTrigger.Visibility = Visibility.Collapsed; + SidebarSearchEditor.Visibility = Visibility.Visible; + SidebarSearchEditor.Opacity = 0; + SidebarSearchEditorScale.ScaleX = 0.85; + + var duration = TimeSpan.FromMilliseconds(160); + SidebarSearchEditor.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, duration)); + SidebarSearchEditorScale.BeginAnimation(System.Windows.Media.ScaleTransform.ScaleXProperty, new DoubleAnimation(0.85, 1, duration) + { + EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } + }); + + Dispatcher.BeginInvoke(new Action(() => + { + SearchBox?.Focus(); + SearchBox?.SelectAll(); + }), DispatcherPriority.Background); + } + + private void CloseSidebarSearch(bool clearText) + { + if (SidebarSearchEditor == null || SidebarSearchTrigger == null || SidebarSearchEditorScale == null) + return; + + if (clearText && SearchBox != null && !string.IsNullOrEmpty(SearchBox.Text)) + SearchBox.Text = ""; + + var duration = TimeSpan.FromMilliseconds(140); + var opacityAnim = new DoubleAnimation(1, 0, duration); + opacityAnim.Completed += (_, _) => + { + SidebarSearchEditor.Visibility = Visibility.Collapsed; + SidebarSearchTrigger.Visibility = Visibility.Visible; + SidebarSearchTrigger.Background = Brushes.Transparent; + if (SidebarSearchShortcutHint != null) + SidebarSearchShortcutHint.Visibility = Visibility.Collapsed; + }; + SidebarSearchEditor.BeginAnimation(OpacityProperty, opacityAnim); + SidebarSearchEditorScale.BeginAnimation(System.Windows.Media.ScaleTransform.ScaleXProperty, new DoubleAnimation(1, 0.85, duration) + { + EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn } + }); + } +} diff --git a/src/AxCopilot/Views/ChatWindow.xaml.cs b/src/AxCopilot/Views/ChatWindow.xaml.cs index a71222a..4cfa2fc 100644 --- a/src/AxCopilot/Views/ChatWindow.xaml.cs +++ b/src/AxCopilot/Views/ChatWindow.xaml.cs @@ -2087,102 +2087,6 @@ public partial class ChatWindow : Window // ─── 검색 ──────────────────────────────────────────────────────────── - private void SidebarSearchTrigger_MouseEnter(object sender, MouseEventArgs e) - { - if (SidebarSearchTrigger != null) - SidebarSearchTrigger.Background = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; - if (SidebarSearchShortcutHint != null) - SidebarSearchShortcutHint.Visibility = Visibility.Visible; - } - - private void SidebarSearchTrigger_MouseLeave(object sender, MouseEventArgs e) - { - if (SidebarSearchTrigger != null) - SidebarSearchTrigger.Background = Brushes.Transparent; - if (SidebarSearchShortcutHint != null) - SidebarSearchShortcutHint.Visibility = Visibility.Collapsed; - } - - private void SidebarSearchTrigger_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) - { - OpenSidebarSearch(); - } - - private void SidebarNewChatTrigger_MouseEnter(object sender, MouseEventArgs e) - { - if (SidebarNewChatTrigger != null) - SidebarNewChatTrigger.Background = TryFindResource("ItemHoverBackground") as Brush ?? Brushes.Transparent; - if (SidebarNewChatShortcutHint != null) - SidebarNewChatShortcutHint.Visibility = Visibility.Visible; - } - - private void SidebarNewChatTrigger_MouseLeave(object sender, MouseEventArgs e) - { - if (SidebarNewChatTrigger != null) - SidebarNewChatTrigger.Background = Brushes.Transparent; - if (SidebarNewChatShortcutHint != null) - SidebarNewChatShortcutHint.Visibility = Visibility.Collapsed; - } - - private void SidebarNewChatTrigger_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) - { - BtnNewChat_Click(sender, new RoutedEventArgs()); - } - - private void BtnSidebarSearchClose_Click(object sender, RoutedEventArgs e) - { - CloseSidebarSearch(clearText: true); - } - - private void OpenSidebarSearch() - { - if (SidebarSearchEditor == null || SidebarSearchTrigger == null || SidebarSearchEditorScale == null) - return; - - SidebarSearchTrigger.Visibility = Visibility.Collapsed; - SidebarSearchEditor.Visibility = Visibility.Visible; - SidebarSearchEditor.Opacity = 0; - SidebarSearchEditorScale.ScaleX = 0.85; - - var duration = TimeSpan.FromMilliseconds(160); - SidebarSearchEditor.BeginAnimation(OpacityProperty, new DoubleAnimation(0, 1, duration)); - SidebarSearchEditorScale.BeginAnimation(System.Windows.Media.ScaleTransform.ScaleXProperty, new DoubleAnimation(0.85, 1, duration) - { - EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } - }); - - Dispatcher.BeginInvoke(new Action(() => - { - SearchBox?.Focus(); - SearchBox?.SelectAll(); - }), DispatcherPriority.Background); - } - - private void CloseSidebarSearch(bool clearText) - { - if (SidebarSearchEditor == null || SidebarSearchTrigger == null || SidebarSearchEditorScale == null) - return; - - if (clearText && SearchBox != null && !string.IsNullOrEmpty(SearchBox.Text)) - SearchBox.Text = ""; - - var duration = TimeSpan.FromMilliseconds(140); - var opacityAnim = new DoubleAnimation(1, 0, duration); - opacityAnim.Completed += (_, _) => - { - SidebarSearchEditor.Visibility = Visibility.Collapsed; - SidebarSearchTrigger.Visibility = Visibility.Visible; - SidebarSearchTrigger.Background = Brushes.Transparent; - if (SidebarSearchShortcutHint != null) - SidebarSearchShortcutHint.Visibility = Visibility.Collapsed; - }; - SidebarSearchEditor.BeginAnimation(OpacityProperty, opacityAnim); - SidebarSearchEditorScale.BeginAnimation(System.Windows.Media.ScaleTransform.ScaleXProperty, new DoubleAnimation(1, 0.85, duration) - { - EasingFunction = new CubicEase { EasingMode = EasingMode.EaseIn } - }); - } - private void SearchBox_TextChanged(object sender, TextChangedEventArgs e) { _conversationSearchTimer.Stop();