206 lines
6.8 KiB
C#
206 lines
6.8 KiB
C#
using System;
|
|
using System.CodeDom.Compiler;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using System.Linq;
|
|
using System.Windows;
|
|
using System.Windows.Controls;
|
|
using System.Windows.Input;
|
|
using System.Windows.Markup;
|
|
using System.Windows.Media;
|
|
using AxCopilot.Core;
|
|
|
|
namespace AxCopilot.Views;
|
|
|
|
public class CommandPaletteWindow : Window, IComponentConnector
|
|
{
|
|
private record CommandEntry(string Label, string Category, string Icon, string CommandId);
|
|
|
|
private readonly Action<string>? _onExecute;
|
|
|
|
private readonly List<CommandEntry> _commands = new List<CommandEntry>();
|
|
|
|
internal TextBox SearchBox;
|
|
|
|
internal StackPanel ResultPanel;
|
|
|
|
private bool _contentLoaded;
|
|
|
|
public string? SelectedCommand { get; private set; }
|
|
|
|
public CommandPaletteWindow(Action<string>? onExecute = null)
|
|
{
|
|
InitializeComponent();
|
|
_onExecute = onExecute;
|
|
RegisterCommands();
|
|
RenderItems("");
|
|
base.Loaded += delegate
|
|
{
|
|
SearchBox.Focus();
|
|
};
|
|
}
|
|
|
|
private void RegisterCommands()
|
|
{
|
|
_commands.Add(new CommandEntry("Chat 탭으로 전환", "탭 전환", "\ue8bd", "tab:chat"));
|
|
_commands.Add(new CommandEntry("Cowork 탭으로 전환", "탭 전환", "\ue8bd", "tab:cowork"));
|
|
_commands.Add(new CommandEntry("Code 탭으로 전환", "탭 전환", "\ue8bd", "tab:code"));
|
|
_commands.Add(new CommandEntry("새 대화 시작", "대화", "\ue710", "new_conversation"));
|
|
_commands.Add(new CommandEntry("대화 검색", "대화", "\ue721", "search_conversation"));
|
|
_commands.Add(new CommandEntry("모델 변경", "설정", "\uea86", "change_model"));
|
|
_commands.Add(new CommandEntry("프리셋 선택", "프리셋", "\ue71d", "select_preset"));
|
|
_commands.Add(new CommandEntry("설정 열기", "앱", "\ue713", "open_settings"));
|
|
_commands.Add(new CommandEntry("테마 변경", "앱", "\ue790", "change_theme"));
|
|
_commands.Add(new CommandEntry("통계 보기", "앱", "\ue9f9", "open_statistics"));
|
|
_commands.Add(new CommandEntry("작업 폴더 변경", "파일", "\ued25", "change_folder"));
|
|
_commands.Add(new CommandEntry("파일 탐색기 열기", "파일", "\ue8b7", "open_file_explorer"));
|
|
_commands.Add(new CommandEntry("개발자 모드 토글", "에이전트", "\ue71c", "toggle_devmode"));
|
|
_commands.Add(new CommandEntry("감사 로그 보기", "에이전트", "\ue9d9", "open_audit_log"));
|
|
_commands.Add(new CommandEntry("클립보드에서 붙여넣기", "도구", "\ue77f", "paste_clipboard"));
|
|
_commands.Add(new CommandEntry("대화 내보내기", "도구", "\ue78c", "export_conversation"));
|
|
}
|
|
|
|
private void RenderItems(string query)
|
|
{
|
|
ResultPanel.Children.Clear();
|
|
List<CommandEntry> list = (string.IsNullOrWhiteSpace(query) ? _commands : _commands.Where((CommandEntry c) => c.Label.Contains(query, StringComparison.OrdinalIgnoreCase) || c.Category.Contains(query, StringComparison.OrdinalIgnoreCase) || (FuzzyEngine.IsChosung(query) && FuzzyEngine.ContainsChosung(c.Label, query))).ToList());
|
|
for (int num = 0; num < list.Count; num++)
|
|
{
|
|
CommandEntry cmd = list[num];
|
|
int num2 = num;
|
|
StackPanel stackPanel = new StackPanel
|
|
{
|
|
Orientation = Orientation.Horizontal
|
|
};
|
|
stackPanel.Children.Add(new TextBlock
|
|
{
|
|
Text = cmd.Icon,
|
|
FontFamily = new FontFamily("Segoe MDL2 Assets"),
|
|
FontSize = 14.0,
|
|
Foreground = ((FindResource("AccentColor") as Brush) ?? Brushes.CornflowerBlue),
|
|
VerticalAlignment = VerticalAlignment.Center,
|
|
Margin = new Thickness(0.0, 0.0, 10.0, 0.0)
|
|
});
|
|
StackPanel stackPanel2 = new StackPanel();
|
|
stackPanel2.Children.Add(new TextBlock
|
|
{
|
|
Text = cmd.Label,
|
|
FontSize = 13.0,
|
|
Foreground = ((FindResource("PrimaryText") as Brush) ?? Brushes.White)
|
|
});
|
|
stackPanel2.Children.Add(new TextBlock
|
|
{
|
|
Text = cmd.Category,
|
|
FontSize = 10.5,
|
|
Foreground = ((FindResource("SecondaryText") as Brush) ?? Brushes.Gray)
|
|
});
|
|
stackPanel.Children.Add(stackPanel2);
|
|
Border border = new Border
|
|
{
|
|
Child = stackPanel,
|
|
Background = Brushes.Transparent,
|
|
CornerRadius = new CornerRadius(8.0),
|
|
Cursor = Cursors.Hand,
|
|
Padding = new Thickness(10.0, 8.0, 14.0, 8.0),
|
|
Margin = new Thickness(0.0, 1.0, 0.0, 1.0)
|
|
};
|
|
Brush hoverBg = (FindResource("HintBackground") as Brush) ?? new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
|
|
border.MouseEnter += delegate(object s, MouseEventArgs _)
|
|
{
|
|
if (s is Border border2)
|
|
{
|
|
border2.Background = hoverBg;
|
|
}
|
|
};
|
|
border.MouseLeave += delegate(object s, MouseEventArgs _)
|
|
{
|
|
if (s is Border border2)
|
|
{
|
|
border2.Background = Brushes.Transparent;
|
|
}
|
|
};
|
|
border.MouseLeftButtonUp += delegate
|
|
{
|
|
ExecuteCommand(cmd.CommandId);
|
|
};
|
|
ResultPanel.Children.Add(border);
|
|
}
|
|
}
|
|
|
|
private void ExecuteCommand(string commandId)
|
|
{
|
|
SelectedCommand = commandId;
|
|
_onExecute?.Invoke(commandId);
|
|
Close();
|
|
}
|
|
|
|
private void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
|
|
{
|
|
RenderItems(SearchBox.Text);
|
|
}
|
|
|
|
private void Window_PreviewKeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0009: Invalid comparison between Unknown and I4
|
|
//IL_0026: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002c: Invalid comparison between Unknown and I4
|
|
if ((int)e.Key == 13)
|
|
{
|
|
Close();
|
|
e.Handled = true;
|
|
}
|
|
else if ((int)e.Key == 6 && ResultPanel.Children.Count > 0)
|
|
{
|
|
List<CommandEntry> list = (string.IsNullOrWhiteSpace(SearchBox.Text) ? _commands : _commands.Where((CommandEntry c) => c.Label.Contains(SearchBox.Text, StringComparison.OrdinalIgnoreCase) || c.Category.Contains(SearchBox.Text, StringComparison.OrdinalIgnoreCase)).ToList());
|
|
if (list.Count > 0)
|
|
{
|
|
ExecuteCommand(list[0].CommandId);
|
|
}
|
|
e.Handled = true;
|
|
}
|
|
}
|
|
|
|
private void Window_Deactivated(object sender, EventArgs e)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
[DebuggerNonUserCode]
|
|
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
|
|
public void InitializeComponent()
|
|
{
|
|
if (!_contentLoaded)
|
|
{
|
|
_contentLoaded = true;
|
|
Uri resourceLocator = new Uri("/AxCopilot;component/views/commandpalettewindow.xaml", UriKind.Relative);
|
|
Application.LoadComponent(this, resourceLocator);
|
|
}
|
|
}
|
|
|
|
[DebuggerNonUserCode]
|
|
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
|
|
[EditorBrowsable(EditorBrowsableState.Never)]
|
|
void IComponentConnector.Connect(int connectionId, object target)
|
|
{
|
|
switch (connectionId)
|
|
{
|
|
case 1:
|
|
((CommandPaletteWindow)target).PreviewKeyDown += Window_PreviewKeyDown;
|
|
((CommandPaletteWindow)target).Deactivated += Window_Deactivated;
|
|
break;
|
|
case 2:
|
|
SearchBox = (TextBox)target;
|
|
SearchBox.TextChanged += SearchBox_TextChanged;
|
|
break;
|
|
case 3:
|
|
ResultPanel = (StackPanel)target;
|
|
break;
|
|
default:
|
|
_contentLoaded = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|