Initial commit to new repository

This commit is contained in:
2026-04-03 18:22:19 +09:00
commit 4458bb0f52
7672 changed files with 452440 additions and 0 deletions

View File

@@ -0,0 +1,337 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Text.Json;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media.Imaging;
using System.Windows.Resources;
using System.Windows.Shapes;
namespace AxCopilot.Views;
public class AboutWindow : Window, IComponentConnector
{
internal Canvas DiamondIconCanvas;
internal Image AppIconImage;
internal TextBlock FallbackIcon;
internal Image MascotImage;
internal TextBlock AppNameText;
internal TextBlock VersionText;
internal Grid MascotOverlay;
internal Image MascotOverlayImage;
internal TextBlock PurposeText;
internal TextBlock CompanyNameText;
internal Button BlogLinkBtn;
internal Grid ContributorsGrid;
internal TextBlock ContributorsText;
internal TextBlock BuildInfoText;
private bool _contentLoaded;
public AboutWindow()
{
InitializeComponent();
base.Loaded += OnLoaded;
base.KeyDown += delegate(object _, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)e.Key == 13)
{
Close();
}
};
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
Version version = Assembly.GetExecutingAssembly().GetName().Version;
VersionText.Text = ((version != null) ? $"v{version.Major}.{version.Minor}.{version.Build}" : "v1.0");
BuildInfoText.Text = "AX Copilot · Commander + Agent · © 2026";
TryLoadBranding(version);
TryLoadAppIcon();
TryLoadMascot();
}
private void TryLoadBranding(Version? version)
{
try
{
Uri uriResource = new Uri("pack://application:,,,/Assets/about.json");
StreamResourceInfo resourceStream = Application.GetResourceStream(uriResource);
if (resourceStream == null)
{
return;
}
using StreamReader streamReader = new StreamReader(resourceStream.Stream);
using JsonDocument jsonDocument = JsonDocument.Parse(streamReader.ReadToEnd());
JsonElement root = jsonDocument.RootElement;
string text = Get("appName");
string text2 = Get("companyName");
string text3 = Get("authorName");
string text4 = Get("authorTitle");
string text5 = Get("purpose");
string value = Get("copyright");
string text6 = Get("blogUrl");
if (!string.IsNullOrWhiteSpace(text))
{
AppNameText.Text = text;
}
if (!string.IsNullOrWhiteSpace(text2))
{
CompanyNameText.Text = text2;
}
if (!string.IsNullOrWhiteSpace(text5))
{
PurposeText.Text = text5;
}
if (!string.IsNullOrWhiteSpace(value))
{
string value2 = ((version != null) ? $"v{version.Major}.{version.Minor}.{version.Build}" : "v1.0");
BuildInfoText.Text = $"{text} · {value2} · Commander + Agent · {value}";
}
if (!string.IsNullOrWhiteSpace(text6) && BlogLinkBtn != null)
{
BlogLinkBtn.Content = text6;
}
string text7 = Get("contributors");
if (!string.IsNullOrWhiteSpace(text7))
{
ContributorsText.Text = text7;
ContributorsGrid.Visibility = Visibility.Visible;
}
string Get(string key)
{
JsonElement value3;
return root.TryGetProperty(key, out value3) ? (value3.GetString() ?? "") : "";
}
}
catch
{
}
}
private void TryLoadAppIcon()
{
try
{
Uri uriResource = new Uri("pack://application:,,,/Assets/icon.ico");
Stream stream = Application.GetResourceStream(uriResource)?.Stream;
if (stream != null)
{
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = stream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.DecodePixelWidth = 176;
bitmapImage.EndInit();
((Freezable)bitmapImage).Freeze();
AppIconImage.Source = bitmapImage;
FallbackIcon.Visibility = Visibility.Collapsed;
}
}
catch
{
}
}
private void TryLoadMascot()
{
string[] array = new string[3] { "mascot.png", "mascot.jpg", "mascot.webp" };
foreach (string text in array)
{
try
{
Uri uriResource = new Uri("pack://application:,,,/Assets/" + text);
Stream stream = Application.GetResourceStream(uriResource)?.Stream;
if (stream == null)
{
continue;
}
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = stream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.DecodePixelWidth = 400;
bitmapImage.EndInit();
((Freezable)bitmapImage).Freeze();
MascotImage.Source = bitmapImage;
return;
}
catch
{
}
}
string path = System.IO.Path.GetDirectoryName(Environment.ProcessPath) ?? AppContext.BaseDirectory;
string[] array2 = new string[3] { "mascot.png", "mascot.jpg", "mascot.webp" };
foreach (string path2 in array2)
{
string text2 = System.IO.Path.Combine(path, "Assets", path2);
if (File.Exists(text2))
{
try
{
BitmapImage bitmapImage2 = new BitmapImage();
bitmapImage2.BeginInit();
bitmapImage2.UriSource = new Uri(text2, UriKind.Absolute);
bitmapImage2.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage2.DecodePixelWidth = 400;
bitmapImage2.EndInit();
MascotImage.Source = bitmapImage2;
break;
}
catch
{
}
}
}
}
private void ShowMascot_Click(object sender, MouseButtonEventArgs e)
{
if (MascotImage.Source != null)
{
MascotOverlayImage.Source = MascotImage.Source;
MascotOverlay.Visibility = Visibility.Visible;
e.Handled = true;
}
}
private void HideMascot_Click(object sender, MouseButtonEventArgs e)
{
MascotOverlay.Visibility = Visibility.Collapsed;
e.Handled = true;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void Blog_Click(object sender, RoutedEventArgs e)
{
try
{
Process.Start(new ProcessStartInfo("https://www.swarchitect.net")
{
UseShellExecute = true
});
}
catch
{
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/aboutwindow.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:
((AboutWindow)target).MouseDown += Window_MouseDown;
break;
case 2:
((Button)target).Click += Close_Click;
break;
case 3:
DiamondIconCanvas = (Canvas)target;
break;
case 4:
AppIconImage = (Image)target;
break;
case 5:
FallbackIcon = (TextBlock)target;
break;
case 6:
MascotImage = (Image)target;
break;
case 7:
AppNameText = (TextBlock)target;
break;
case 8:
VersionText = (TextBlock)target;
break;
case 9:
MascotOverlay = (Grid)target;
break;
case 10:
((Rectangle)target).MouseDown += HideMascot_Click;
break;
case 11:
MascotOverlayImage = (Image)target;
break;
case 12:
PurposeText = (TextBlock)target;
break;
case 13:
((Grid)target).MouseDown += ShowMascot_Click;
break;
case 14:
CompanyNameText = (TextBlock)target;
break;
case 15:
BlogLinkBtn = (Button)target;
BlogLinkBtn.Click += Blog_Click;
break;
case 16:
ContributorsGrid = (Grid)target;
break;
case 17:
ContributorsText = (TextBlock)target;
break;
case 18:
BuildInfoText = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,507 @@
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.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Shapes;
using AxCopilot.Services;
namespace AxCopilot.Views;
public class AgentStatsDashboardWindow : Window, IComponentConnector
{
private int _currentDays = 1;
internal Border BtnClose;
internal Border FilterToday;
internal Border Filter7d;
internal Border Filter30d;
internal Border FilterAll;
internal UniformGrid SummaryCards;
internal TextBlock DailyChartTitle;
internal Canvas DailyBarChart;
internal Canvas DailyBarLabels;
internal StackPanel ToolFreqPanel;
internal StackPanel TabBreakPanel;
internal StackPanel ModelBreakPanel;
internal TextBlock StatusText;
private bool _contentLoaded;
public AgentStatsDashboardWindow()
{
InitializeComponent();
base.Loaded += delegate
{
LoadStats(_currentDays);
};
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
Point position = e.GetPosition(this);
if (!(((Point)(ref position)).X > base.ActualWidth - 50.0))
{
if (e.ClickCount == 2)
{
base.WindowState = ((base.WindowState != WindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
}
else
{
DragMove();
}
}
}
private void BtnClose_Click(object sender, MouseButtonEventArgs e)
{
Close();
}
private void Filter_Click(object sender, MouseButtonEventArgs e)
{
if (sender is Border { Tag: string tag } border && int.TryParse(tag, out var result))
{
_currentDays = result;
UpdateFilterButtons(border);
LoadStats(result);
}
}
private void BtnClearStats_Click(object sender, MouseButtonEventArgs e)
{
MessageBoxResult messageBoxResult = CustomMessageBox.Show("모든 통계 데이터를 삭제하시겠습니까?\n이 작업은 되돌릴 수 없습니다.", "통계 초기화", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (messageBoxResult == MessageBoxResult.Yes)
{
AgentStatsService.Clear();
LoadStats(_currentDays);
}
}
private void LoadStats(int days)
{
AgentStatsService.AgentStatsSummary s = AgentStatsService.Aggregate(days);
RenderSummaryCards(s);
RenderDailyChart(s, days);
RenderToolFreq(s);
RenderBreakdowns(s);
UpdateStatus(s, days);
}
private void RenderSummaryCards(AgentStatsService.AgentStatsSummary s)
{
SummaryCards.Children.Clear();
SummaryCards.Children.Add(MakeSummaryCard("\ue9d9", "총 실행", s.TotalSessions.ToString("N0"), "#A78BFA"));
SummaryCards.Children.Add(MakeSummaryCard("\ue8a7", "도구 호출", s.TotalToolCalls.ToString("N0"), "#3B82F6"));
SummaryCards.Children.Add(MakeSummaryCard("\ue7c8", "총 토큰", FormatTokens(s.TotalTokens), "#10B981"));
SummaryCards.Children.Add(MakeSummaryCard("\ue916", "평균 시간", (s.TotalSessions > 0) ? $"{TimeSpan.FromMilliseconds((double)s.TotalDurationMs / (double)s.TotalSessions):mm\\:ss}" : "—", "#F59E0B"));
}
private Border MakeSummaryCard(string icon, string label, string value, string colorHex)
{
Brush background = (TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 42, 64));
Brush foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Color color = (Color)ColorConverter.ConvertFromString(colorHex);
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(10.0),
Padding = new Thickness(14.0, 12.0, 14.0, 12.0),
Margin = new Thickness(0.0, 0.0, 8.0, 0.0)
};
StackPanel stackPanel = new StackPanel();
stackPanel.Children.Add(new TextBlock
{
Text = icon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 16.0,
Foreground = new SolidColorBrush(color),
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = value,
FontSize = 20.0,
FontWeight = FontWeights.Bold,
Foreground = foreground
});
stackPanel.Children.Add(new TextBlock
{
Text = label,
FontSize = 11.0,
Foreground = foreground2,
Margin = new Thickness(0.0, 2.0, 0.0, 0.0)
});
border.Child = stackPanel;
return border;
}
private void RenderDailyChart(AgentStatsService.AgentStatsSummary s, int days)
{
DailyBarChart.Children.Clear();
DailyBarLabels.Children.Clear();
DateTime endDate = DateTime.Today;
int chartDays = days switch
{
0 => 30,
1 => 1,
_ => days,
};
List<DateTime> list = (from i in Enumerable.Range(0, chartDays)
select endDate.AddDays(-(chartDays - 1 - i))).ToList();
int num = list.Select((DateTime d) => s.DailySessions.GetValueOrDefault(d.ToString("yyyy-MM-dd"), 0)).DefaultIfEmpty(0).Max();
if (num == 0)
{
num = 1;
}
Color color = (Color)ColorConverter.ConvertFromString("#4B5EFC");
double num2 = 748.0;
double num3 = 2.0;
double num4 = Math.Max(4.0, (num2 - num3 * (double)list.Count) / (double)list.Count);
double num5 = 100.0;
for (int num6 = 0; num6 < list.Count; num6++)
{
string text = list[num6].ToString("yyyy-MM-dd");
int valueOrDefault = s.DailySessions.GetValueOrDefault(text, 0);
double num7 = Math.Max(2.0, (double)valueOrDefault / (double)num * (num5 - 4.0));
double length = (double)num6 * (num4 + num3);
Rectangle element = new Rectangle
{
Width = num4,
Height = num7,
Fill = new SolidColorBrush(Color.FromArgb(204, color.R, color.G, color.B)),
RadiusX = 3.0,
RadiusY = 3.0,
ToolTip = $"{text}: {valueOrDefault}회"
};
Canvas.SetLeft(element, length);
Canvas.SetTop(element, num5 - num7);
DailyBarChart.Children.Add(element);
if (list.Count <= 7 || list[num6].DayOfWeek == DayOfWeek.Monday)
{
TextBlock textBlock = new TextBlock();
textBlock.Text = list[num6].ToString("MM/dd");
textBlock.FontSize = 9.0;
textBlock.Foreground = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
TextBlock element2 = textBlock;
Canvas.SetLeft(element2, length);
DailyBarLabels.Children.Add(element2);
}
}
}
private void RenderToolFreq(AgentStatsService.AgentStatsSummary s)
{
ToolFreqPanel.Children.Clear();
if (s.ToolFrequency.Count == 0)
{
ToolFreqPanel.Children.Add(new TextBlock
{
Text = "데이터 없음",
FontSize = 12.0,
Foreground = ((TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray)
});
return;
}
int num = s.ToolFrequency.Values.Max();
Color color = (Color)ColorConverter.ConvertFromString("#3B82F6");
foreach (KeyValuePair<string, int> item in s.ToolFrequency)
{
item.Deconstruct(out var key, out var value);
string text = key;
int num2 = value;
double num3 = (double)num2 / (double)num;
Grid grid = new Grid
{
Margin = new Thickness(0.0, 2.0, 0.0, 2.0)
};
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(120.0)
});
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(36.0)
});
TextBlock textBlock = new TextBlock();
textBlock.Text = text;
textBlock.FontSize = 11.0;
textBlock.FontFamily = new FontFamily("Consolas");
textBlock.Foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
textBlock.TextTrimming = TextTrimming.CharacterEllipsis;
textBlock.VerticalAlignment = VerticalAlignment.Center;
TextBlock element = textBlock;
Grid.SetColumn(element, 0);
Border border = new Border
{
Background = new SolidColorBrush(Color.FromArgb(32, 59, 130, 246)),
CornerRadius = new CornerRadius(3.0),
Height = 10.0,
Margin = new Thickness(6.0, 0.0, 4.0, 0.0),
VerticalAlignment = VerticalAlignment.Center
};
Border border2 = new Border
{
Background = new SolidColorBrush(Color.FromArgb(204, color.R, color.G, color.B)),
CornerRadius = new CornerRadius(3.0),
Height = 10.0,
HorizontalAlignment = HorizontalAlignment.Left
};
border2.Width = num3 * 150.0;
border.Child = border2;
Grid.SetColumn(border, 1);
textBlock = new TextBlock();
textBlock.Text = num2.ToString();
textBlock.FontSize = 11.0;
textBlock.FontWeight = FontWeights.SemiBold;
textBlock.Foreground = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
textBlock.HorizontalAlignment = HorizontalAlignment.Right;
textBlock.VerticalAlignment = VerticalAlignment.Center;
TextBlock element2 = textBlock;
Grid.SetColumn(element2, 2);
grid.Children.Add(element);
grid.Children.Add(border);
grid.Children.Add(element2);
ToolFreqPanel.Children.Add(grid);
}
}
private void RenderBreakdowns(AgentStatsService.AgentStatsSummary s)
{
TabBreakPanel.Children.Clear();
Dictionary<string, string> dictionary = new Dictionary<string, string>
{
["Cowork"] = "#A78BFA",
["Code"] = "#34D399",
["Chat"] = "#3B82F6"
};
string key;
int value;
foreach (KeyValuePair<string, int> item in s.TabBreakdown.OrderByDescending<KeyValuePair<string, int>, int>((KeyValuePair<string, int> kv) => kv.Value))
{
item.Deconstruct(out key, out value);
string text = key;
int count = value;
string valueOrDefault = dictionary.GetValueOrDefault(text, "#9CA3AF");
TabBreakPanel.Children.Add(MakeBreakRow(text, count, valueOrDefault, s.TabBreakdown.Values.DefaultIfEmpty(1).Max()));
}
if (s.TabBreakdown.Count == 0)
{
TabBreakPanel.Children.Add(MakeEmptyText());
}
ModelBreakPanel.Children.Clear();
foreach (KeyValuePair<string, int> item2 in s.ModelBreakdown.OrderByDescending<KeyValuePair<string, int>, int>((KeyValuePair<string, int> kv) => kv.Value))
{
item2.Deconstruct(out key, out value);
string text2 = key;
int count2 = value;
string label = ((text2.Length > 18) ? (text2.Substring(0, 18) + "…") : text2);
ModelBreakPanel.Children.Add(MakeBreakRow(label, count2, "#F59E0B", s.ModelBreakdown.Values.DefaultIfEmpty(1).Max()));
}
if (s.ModelBreakdown.Count == 0)
{
ModelBreakPanel.Children.Add(MakeEmptyText());
}
}
private UIElement MakeBreakRow(string label, int count, string colorHex, int maxVal)
{
double num = ((maxVal > 0) ? ((double)count / (double)maxVal) : 0.0);
Color color = (Color)ColorConverter.ConvertFromString(colorHex);
StackPanel stackPanel = new StackPanel
{
Margin = new Thickness(0.0, 2.0, 0.0, 2.0)
};
Grid grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1.0, GridUnitType.Auto)
});
TextBlock textBlock = new TextBlock();
textBlock.Text = label;
textBlock.FontSize = 11.0;
textBlock.Foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
TextBlock element = textBlock;
Grid.SetColumn(element, 0);
textBlock = new TextBlock();
textBlock.Text = count.ToString();
textBlock.FontSize = 11.0;
textBlock.FontWeight = FontWeights.SemiBold;
textBlock.Foreground = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
TextBlock element2 = textBlock;
Grid.SetColumn(element2, 1);
grid.Children.Add(element);
grid.Children.Add(element2);
stackPanel.Children.Add(grid);
Border border = new Border
{
Background = new SolidColorBrush(Color.FromArgb(32, color.R, color.G, color.B)),
CornerRadius = new CornerRadius(3.0),
Height = 6.0,
Margin = new Thickness(0.0, 3.0, 0.0, 0.0)
};
Border border2 = new Border
{
Background = new SolidColorBrush(Color.FromArgb(204, color.R, color.G, color.B)),
CornerRadius = new CornerRadius(3.0),
Height = 6.0,
HorizontalAlignment = HorizontalAlignment.Left
};
border2.Width = num * 160.0;
border.Child = border2;
stackPanel.Children.Add(border);
return stackPanel;
}
private TextBlock MakeEmptyText()
{
TextBlock textBlock = new TextBlock();
textBlock.Text = "데이터 없음";
textBlock.FontSize = 11.0;
textBlock.Foreground = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
return textBlock;
}
private void UpdateFilterButtons(Border active)
{
Border[] array = new Border[4] { FilterToday, Filter7d, Filter30d, FilterAll };
foreach (Border border in array)
{
bool flag = border == active;
border.Background = (flag ? new SolidColorBrush(Color.FromRgb(75, 94, 252)) : ((TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(48, 48, 69))));
if (border.Child is TextBlock textBlock)
{
textBlock.Foreground = (flag ? Brushes.White : ((TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray));
}
}
}
private void UpdateStatus(AgentStatsService.AgentStatsSummary s, int days)
{
if (1 == 0)
{
}
string text = days switch
{
1 => "오늘",
7 => "최근 7일",
30 => "최근 30일",
_ => "전체 기간",
};
if (1 == 0)
{
}
string value = text;
long fileSize = AgentStatsService.GetFileSize();
StatusText.Text = $"{value} 기준 | 세션 {s.TotalSessions}회, 도구 호출 {s.TotalToolCalls}회, 토큰 {FormatTokens(s.TotalTokens)} | 저장 파일 {FormatFileSize(fileSize)}";
}
private static string FormatTokens(int t)
{
return (t >= 1000000) ? $"{(double)t / 1000000.0:F1}M" : ((t >= 1000) ? $"{(double)t / 1000.0:F1}K" : t.ToString());
}
private static string FormatFileSize(long bytes)
{
return (bytes >= 1048576) ? $"{(double)bytes / 1048576.0:F1}MB" : ((bytes >= 1024) ? $"{(double)bytes / 1024.0:F1}KB" : $"{bytes}B");
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/agentstatsdashboardwindow.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:
((Border)target).MouseLeftButtonDown += TitleBar_MouseLeftButtonDown;
break;
case 2:
BtnClose = (Border)target;
BtnClose.MouseLeftButtonUp += BtnClose_Click;
break;
case 3:
FilterToday = (Border)target;
FilterToday.MouseLeftButtonUp += Filter_Click;
break;
case 4:
Filter7d = (Border)target;
Filter7d.MouseLeftButtonUp += Filter_Click;
break;
case 5:
Filter30d = (Border)target;
Filter30d.MouseLeftButtonUp += Filter_Click;
break;
case 6:
FilterAll = (Border)target;
FilterAll.MouseLeftButtonUp += Filter_Click;
break;
case 7:
((Border)target).MouseLeftButtonUp += BtnClearStats_Click;
break;
case 8:
SummaryCards = (UniformGrid)target;
break;
case 9:
DailyChartTitle = (TextBlock)target;
break;
case 10:
DailyBarChart = (Canvas)target;
break;
case 11:
DailyBarLabels = (Canvas)target;
break;
case 12:
ToolFreqPanel = (StackPanel)target;
break;
case 13:
TabBreakPanel = (StackPanel)target;
break;
case 14:
ModelBreakPanel = (StackPanel)target;
break;
case 15:
StatusText = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,110 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Threading;
namespace AxCopilot.Views;
public class ColorPickResultWindow : Window, IComponentConnector
{
private readonly DispatcherTimer _timer;
internal Ellipse ColorPreview;
internal TextBlock HexText;
internal TextBlock RgbText;
private bool _contentLoaded;
public ColorPickResultWindow(System.Drawing.Color color, double screenX, double screenY)
{
//IL_0139: Unknown result type (might be due to invalid IL or missing references)
//IL_013e: Unknown result type (might be due to invalid IL or missing references)
//IL_0190: Unknown result type (might be due to invalid IL or missing references)
//IL_0195: Unknown result type (might be due to invalid IL or missing references)
//IL_01af: Expected O, but got Unknown
InitializeComponent();
System.Windows.Media.Color color2 = System.Windows.Media.Color.FromRgb(color.R, color.G, color.B);
ColorPreview.Fill = new SolidColorBrush(color2);
HexText.Text = $"#{color.R:X2}{color.G:X2}{color.B:X2}";
RgbText.Text = $"RGB({color.R}, {color.G}, {color.B})";
try
{
Clipboard.SetText(HexText.Text);
}
catch
{
}
Rect workArea = SystemParameters.WorkArea;
base.Left = Math.Min(screenX + 20.0, ((Rect)(ref workArea)).Right - 200.0);
base.Top = Math.Min(screenY + 20.0, ((Rect)(ref workArea)).Bottom - 160.0);
_timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(5.0)
};
_timer.Tick += delegate
{
Close();
};
_timer.Start();
base.MouseDown += delegate
{
Close();
};
base.Opacity = 0.0;
base.Loaded += delegate
{
DoubleAnimation animation = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(200.0));
BeginAnimation(UIElement.OpacityProperty, animation);
};
}
protected override void OnClosed(EventArgs e)
{
_timer.Stop();
base.OnClosed(e);
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/colorpickresultwindow.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:
ColorPreview = (Ellipse)target;
break;
case 2:
HexText = (TextBlock)target;
break;
case 3:
RgbText = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,205 @@
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;
}
}
}

View File

@@ -0,0 +1,366 @@
using System;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
namespace AxCopilot.Views;
internal sealed class CustomMessageBox : Window
{
private MessageBoxResult _result = MessageBoxResult.None;
private CustomMessageBox(string message, string title, MessageBoxButton buttons, MessageBoxImage icon)
{
CustomMessageBox customMessageBox = this;
base.Title = title;
base.Width = 400.0;
base.MinWidth = 320.0;
base.MaxWidth = 520.0;
base.SizeToContent = SizeToContent.Height;
base.WindowStartupLocation = WindowStartupLocation.CenterScreen;
base.ResizeMode = ResizeMode.NoResize;
base.WindowStyle = WindowStyle.None;
base.AllowsTransparency = true;
base.Background = Brushes.Transparent;
base.Topmost = true;
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush foreground = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush bg = (Application.Current.TryFindResource("AccentColor") as Brush) ?? new SolidColorBrush(Color.FromRgb(75, 94, 252));
Brush borderBrush = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Brush bg2 = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 43, 64));
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(16.0),
BorderBrush = borderBrush,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(28.0, 24.0, 28.0, 20.0),
Effect = new DropShadowEffect
{
BlurRadius = 24.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = Colors.Black
}
};
StackPanel stackPanel = new StackPanel();
Grid grid = new Grid
{
Margin = new Thickness(0.0, 0.0, 0.0, 16.0)
};
grid.MouseLeftButtonDown += delegate
{
try
{
customMessageBox.DragMove();
}
catch
{
}
};
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal
};
var (text, foreground3) = GetIconInfo(icon);
if (!string.IsNullOrEmpty(text))
{
stackPanel2.Children.Add(new TextBlock
{
Text = text,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 18.0,
Foreground = foreground3,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 10.0, 0.0)
});
}
stackPanel2.Children.Add(new TextBlock
{
Text = title,
FontSize = 15.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center
});
grid.Children.Add(stackPanel2);
Button button = new Button
{
Content = "\ue8bb",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 10.0,
Foreground = foreground2,
Background = Brushes.Transparent,
BorderThickness = new Thickness(0.0),
Padding = new Thickness(6.0),
Cursor = Cursors.Hand,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Center
};
button.Click += delegate
{
customMessageBox._result = MessageBoxResult.Cancel;
customMessageBox.Close();
};
grid.Children.Add(button);
stackPanel.Children.Add(grid);
stackPanel.Children.Add(new TextBlock
{
Text = message,
FontSize = 13.0,
Foreground = foreground,
TextWrapping = TextWrapping.Wrap,
LineHeight = 20.0,
Margin = new Thickness(0.0, 0.0, 0.0, 24.0)
});
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right
};
switch (buttons)
{
case MessageBoxButton.OK:
stackPanel3.Children.Add(CreateButton("확인", bg, isPrimary: true, MessageBoxResult.OK));
break;
case MessageBoxButton.OKCancel:
stackPanel3.Children.Add(CreateButton("취소", bg2, isPrimary: false, MessageBoxResult.Cancel));
stackPanel3.Children.Add(CreateButton("확인", bg, isPrimary: true, MessageBoxResult.OK));
break;
case MessageBoxButton.YesNo:
stackPanel3.Children.Add(CreateButton("아니오", bg2, isPrimary: false, MessageBoxResult.No));
stackPanel3.Children.Add(CreateButton("예", bg, isPrimary: true, MessageBoxResult.Yes));
break;
case MessageBoxButton.YesNoCancel:
stackPanel3.Children.Add(CreateButton("취소", bg2, isPrimary: false, MessageBoxResult.Cancel));
stackPanel3.Children.Add(CreateButton("아니오", bg2, isPrimary: false, MessageBoxResult.No));
stackPanel3.Children.Add(CreateButton("예", bg, isPrimary: true, MessageBoxResult.Yes));
break;
}
stackPanel.Children.Add(stackPanel3);
border.Child = stackPanel;
base.Content = border;
base.KeyDown += delegate(object _, 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_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Invalid comparison between Unknown and I4
if ((int)e.Key == 13)
{
customMessageBox._result = ((buttons == MessageBoxButton.YesNo) ? MessageBoxResult.No : MessageBoxResult.Cancel);
customMessageBox.Close();
}
else if ((int)e.Key == 6)
{
if (1 == 0)
{
}
MessageBoxButton messageBoxButton = buttons;
MessageBoxResult result = (((uint)(messageBoxButton - 3) > 1u) ? MessageBoxResult.OK : MessageBoxResult.Yes);
if (1 == 0)
{
}
customMessageBox._result = result;
customMessageBox.Close();
}
};
}
private Button CreateButton(string text, Brush bg, bool isPrimary, MessageBoxResult result)
{
Button button = new Button();
button.Content = text;
button.FontSize = 12.5;
button.FontWeight = (isPrimary ? FontWeights.SemiBold : FontWeights.Normal);
button.Foreground = (isPrimary ? Brushes.White : ((Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White));
button.Background = bg;
button.BorderThickness = new Thickness(0.0);
button.Padding = new Thickness(20.0, 8.0, 20.0, 8.0);
button.Margin = new Thickness(6.0, 0.0, 0.0, 0.0);
button.Cursor = Cursors.Hand;
button.MinWidth = 80.0;
Button button2 = button;
ControlTemplate controlTemplate = new ControlTemplate(typeof(Button));
FrameworkElementFactory frameworkElementFactory = new FrameworkElementFactory(typeof(Border));
frameworkElementFactory.SetValue(Border.BackgroundProperty, bg);
frameworkElementFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(10.0));
frameworkElementFactory.SetValue(Border.PaddingProperty, new Thickness(20.0, 8.0, 20.0, 8.0));
FrameworkElementFactory frameworkElementFactory2 = new FrameworkElementFactory(typeof(ContentPresenter));
frameworkElementFactory2.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Center);
frameworkElementFactory2.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center);
frameworkElementFactory.AppendChild(frameworkElementFactory2);
controlTemplate.VisualTree = frameworkElementFactory;
button2.Template = controlTemplate;
button2.Click += delegate
{
_result = result;
Close();
};
return button2;
}
private static (string icon, Brush color) GetIconInfo(MessageBoxImage image)
{
if (1 == 0)
{
}
(string, SolidColorBrush) tuple = image switch
{
MessageBoxImage.Hand => ("\uea39", new SolidColorBrush(Color.FromRgb(229, 62, 62))),
MessageBoxImage.Exclamation => ("\ue7ba", new SolidColorBrush(Color.FromRgb(221, 107, 32))),
MessageBoxImage.Asterisk => ("\ue946", new SolidColorBrush(Color.FromRgb(75, 94, 252))),
MessageBoxImage.Question => ("\ue9ce", new SolidColorBrush(Color.FromRgb(75, 94, 252))),
_ => ("", Brushes.Transparent),
};
if (1 == 0)
{
}
(string, SolidColorBrush) tuple2 = tuple;
return (icon: tuple2.Item1, color: tuple2.Item2);
}
public static MessageBoxResult Show(string message)
{
return Show(message, "AX Copilot", MessageBoxButton.OK, MessageBoxImage.None);
}
public static MessageBoxResult Show(string message, string title)
{
return Show(message, title, MessageBoxButton.OK, MessageBoxImage.None);
}
public static MessageBoxResult Show(string message, string title, MessageBoxButton buttons)
{
return Show(message, title, buttons, MessageBoxImage.None);
}
public static MessageBoxResult Show(string message, string title, MessageBoxButton buttons, MessageBoxImage icon)
{
CustomMessageBox dlg = new CustomMessageBox(message, title, buttons, icon);
dlg.Opacity = 0.0;
dlg.Loaded += delegate
{
DoubleAnimation animation = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(150.0));
dlg.BeginAnimation(UIElement.OpacityProperty, animation);
};
Window window = Application.Current.Windows.OfType<Window>().FirstOrDefault((Window w) => w.IsActive && !(w is CustomMessageBox)) ?? Application.Current.MainWindow;
Border toast = null;
Grid rootGrid = null;
if (window?.Content is Border { Child: Grid child })
{
rootGrid = child;
toast = CreateToastBanner(title, icon);
rootGrid.Children.Add(toast);
}
else if (window?.Content is Grid grid)
{
rootGrid = grid;
toast = CreateToastBanner(title, icon);
rootGrid.Children.Add(toast);
}
dlg.ShowDialog();
if (toast != null && rootGrid != null)
{
DoubleAnimation doubleAnimation = new DoubleAnimation(1.0, 0.0, TimeSpan.FromMilliseconds(400.0))
{
EasingFunction = new QuadraticEase
{
EasingMode = EasingMode.EaseIn
}
};
doubleAnimation.Completed += delegate
{
rootGrid.Children.Remove(toast);
};
toast.BeginAnimation(UIElement.OpacityProperty, doubleAnimation);
}
return dlg._result;
}
private static Border CreateToastBanner(string title, MessageBoxImage icon)
{
var (text, foreground) = GetIconInfo(icon);
if (string.IsNullOrEmpty(text))
{
text = "\ue946";
foreground = new SolidColorBrush(Color.FromRgb(75, 94, 252));
}
StackPanel stackPanel = new StackPanel
{
Orientation = Orientation.Horizontal
};
stackPanel.Children.Add(new TextBlock
{
Text = text,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 12.0,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 8.0, 0.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = title,
FontSize = 11.5,
FontWeight = FontWeights.SemiBold,
Foreground = Brushes.White,
VerticalAlignment = VerticalAlignment.Center
});
Border toast = new Border
{
Background = new SolidColorBrush(Color.FromArgb(232, 42, 43, 64)),
CornerRadius = new CornerRadius(10.0),
Padding = new Thickness(16.0, 8.0, 16.0, 8.0),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Bottom,
Margin = new Thickness(0.0, 0.0, 0.0, 12.0),
Effect = new DropShadowEffect
{
BlurRadius = 12.0,
ShadowDepth = 2.0,
Opacity = 0.3,
Color = Colors.Black
},
Opacity = 0.0,
Child = stackPanel
};
Grid.SetColumnSpan(toast, 10);
Grid.SetRowSpan(toast, 10);
TranslateTransform translate = new TranslateTransform(0.0, 20.0);
toast.RenderTransform = translate;
toast.Loaded += delegate
{
DoubleAnimation animation = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(250.0))
{
EasingFunction = new QuadraticEase
{
EasingMode = EasingMode.EaseOut
}
};
DoubleAnimation animation2 = new DoubleAnimation(20.0, 0.0, TimeSpan.FromMilliseconds(300.0))
{
EasingFunction = new BackEase
{
EasingMode = EasingMode.EaseOut,
Amplitude = 0.3
}
};
toast.BeginAnimation(UIElement.OpacityProperty, animation);
translate.BeginAnimation(TranslateTransform.YProperty, animation2);
};
return toast;
}
public static MessageBoxResult ShowStandalone(string message, string title, MessageBoxButton buttons = MessageBoxButton.OK, MessageBoxImage icon = MessageBoxImage.None)
{
CustomMessageBox customMessageBox = new CustomMessageBox(message, title, buttons, icon);
customMessageBox.ShowDialog();
return customMessageBox._result;
}
}

View File

@@ -0,0 +1,345 @@
using System.Linq;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shapes;
namespace AxCopilot.Views;
internal sealed class CustomMoodDialog : Window
{
private readonly TextBox _keyBox;
private readonly TextBox _labelBox;
private readonly TextBox _iconBox;
private readonly TextBox _descBox;
private readonly TextBox _cssBox;
private readonly bool _isEdit;
private const string CssExample = "body {\n font-family: 'Pretendard', 'Noto Sans KR', sans-serif;\n max-width: 900px;\n margin: 0 auto;\n padding: 40px;\n color: #1a1a2e;\n background: #f8f9fc;\n line-height: 1.8;\n}\nh1 { color: #2d3748; border-bottom: 2px solid #4a90d9; padding-bottom: 8px; }\nh2 { color: #4a5568; margin-top: 2em; }\ntable { width: 100%; border-collapse: collapse; margin: 1.5em 0; }\nth { background: #4a90d9; color: white; padding: 10px; text-align: left; }\ntd { padding: 8px 10px; border-bottom: 1px solid #e2e8f0; }\ntr:nth-child(even) { background: #f0f4f8; }\n";
public string MoodKey => _keyBox.Text.Trim().ToLowerInvariant();
public string MoodLabel => _labelBox.Text.Trim();
public string MoodIcon => _iconBox.Text.Trim();
public string MoodDescription => _descBox.Text.Trim();
public string MoodCss => _cssBox.Text;
public CustomMoodDialog(string existingKey = "", string existingLabel = "", string existingIcon = "\ud83c\udfaf", string existingDesc = "", string existingCss = "")
{
_isEdit = !string.IsNullOrEmpty(existingKey);
base.Title = (_isEdit ? "무드 편집" : "무드 추가");
base.Width = 560.0;
base.SizeToContent = SizeToContent.Height;
base.WindowStartupLocation = WindowStartupLocation.CenterOwner;
base.ResizeMode = ResizeMode.NoResize;
base.WindowStyle = WindowStyle.None;
base.AllowsTransparency = true;
base.Background = Brushes.Transparent;
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush brush = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush brush2 = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush brush3 = (Application.Current.TryFindResource("AccentColor") as Brush) ?? Brushes.Blue;
Brush bg = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 43, 64));
Brush brush4 = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(16.0),
BorderBrush = brush4,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(28.0, 24.0, 28.0, 24.0),
Effect = new DropShadowEffect
{
BlurRadius = 24.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = Colors.Black
}
};
StackPanel stackPanel = new StackPanel();
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 20.0)
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\ue771",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 18.0,
Foreground = brush3,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 10.0, 0.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = (_isEdit ? "디자인 무드 편집" : "새 커스텀 디자인 무드"),
FontSize = 17.0,
FontWeight = FontWeights.Bold,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center
});
stackPanel.Children.Add(stackPanel2);
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
};
StackPanel stackPanel4 = new StackPanel
{
Margin = new Thickness(0.0, 0.0, 12.0, 0.0)
};
AddLabel(stackPanel4, "키 (영문)", brush);
_keyBox = CreateTextBox(existingKey, brush, bg, brush3, brush4);
_keyBox.Width = 140.0;
_keyBox.IsEnabled = !_isEdit;
stackPanel4.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _keyBox
});
stackPanel3.Children.Add(stackPanel4);
StackPanel stackPanel5 = new StackPanel
{
Margin = new Thickness(0.0, 0.0, 12.0, 0.0)
};
AddLabel(stackPanel5, "이름", brush);
_labelBox = CreateTextBox(existingLabel, brush, bg, brush3, brush4);
_labelBox.Width = 180.0;
stackPanel5.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _labelBox
});
stackPanel3.Children.Add(stackPanel5);
StackPanel stackPanel6 = new StackPanel();
AddLabel(stackPanel6, "아이콘", brush);
_iconBox = CreateTextBox(existingIcon, brush, bg, brush3, brush4);
_iconBox.Width = 60.0;
_iconBox.TextAlignment = TextAlignment.Center;
stackPanel6.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _iconBox
});
stackPanel3.Children.Add(stackPanel6);
stackPanel.Children.Add(stackPanel3);
AddLabel(stackPanel, "설명", brush);
_descBox = CreateTextBox(existingDesc, brush, bg, brush3, brush4);
stackPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _descBox,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
AddSeparator(stackPanel, brush4);
AddLabel(stackPanel, "CSS 스타일", brush);
AddHint(stackPanel, "문서에 적용될 CSS입니다. body, h1~h6, table, .callout 등의 스타일을 정의하세요.", brush2);
_cssBox = CreateTextBox(existingCss, brush, bg, brush3, brush4, multiline: true, 200);
_cssBox.FontFamily = new FontFamily("Consolas, Courier New, monospace");
_cssBox.FontSize = 12.0;
stackPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _cssBox
});
TextBlock textBlock = new TextBlock
{
Text = "CSS 예시 보기",
FontSize = 11.0,
Foreground = brush3,
Cursor = Cursors.Hand,
Margin = new Thickness(0.0, 6.0, 0.0, 0.0),
TextDecorations = TextDecorations.Underline
};
textBlock.MouseLeftButtonDown += delegate
{
if (string.IsNullOrWhiteSpace(_cssBox.Text))
{
_cssBox.Text = "body {\n font-family: 'Pretendard', 'Noto Sans KR', sans-serif;\n max-width: 900px;\n margin: 0 auto;\n padding: 40px;\n color: #1a1a2e;\n background: #f8f9fc;\n line-height: 1.8;\n}\nh1 { color: #2d3748; border-bottom: 2px solid #4a90d9; padding-bottom: 8px; }\nh2 { color: #4a5568; margin-top: 2em; }\ntable { width: 100%; border-collapse: collapse; margin: 1.5em 0; }\nth { background: #4a90d9; color: white; padding: 10px; text-align: left; }\ntd { padding: 8px 10px; border-bottom: 1px solid #e2e8f0; }\ntr:nth-child(even) { background: #f0f4f8; }\n";
}
};
stackPanel.Children.Add(textBlock);
StackPanel stackPanel7 = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 20.0, 0.0, 0.0)
};
Button button = new Button
{
Content = "취소",
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Margin = new Thickness(0.0, 0.0, 10.0, 0.0),
Background = Brushes.Transparent,
Foreground = brush2,
BorderBrush = brush4,
BorderThickness = new Thickness(1.0),
Cursor = Cursors.Hand,
FontSize = 13.0
};
button.Click += delegate
{
base.DialogResult = false;
Close();
};
stackPanel7.Children.Add(button);
Button button2 = new Button
{
Content = (_isEdit ? "저장" : "추가"),
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Background = brush3,
Foreground = Brushes.White,
BorderThickness = new Thickness(0.0),
Cursor = Cursors.Hand,
FontSize = 13.0,
FontWeight = FontWeights.SemiBold
};
button2.Click += delegate
{
Validate();
};
stackPanel7.Children.Add(button2);
stackPanel.Children.Add(stackPanel7);
border.Child = stackPanel;
base.Content = border;
base.KeyDown += delegate(object _, KeyEventArgs ke)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)ke.Key == 13)
{
base.DialogResult = false;
Close();
}
};
base.Loaded += delegate
{
(_isEdit ? _labelBox : _keyBox).Focus();
};
border.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs me)
{
if (me.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
};
}
private void Validate()
{
if (string.IsNullOrWhiteSpace(_keyBox.Text))
{
CustomMessageBox.Show("키를 입력하세요 (영문 소문자).", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_keyBox.Focus();
return;
}
if (!Regex.IsMatch(_keyBox.Text.Trim(), "^[a-z][a-z0-9_]{1,20}$"))
{
CustomMessageBox.Show("키는 영문 소문자로 시작하며, 소문자/숫자/밑줄만 허용됩니다 (2~21자).", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_keyBox.Focus();
return;
}
if (string.IsNullOrWhiteSpace(_labelBox.Text))
{
CustomMessageBox.Show("이름을 입력하세요.", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_labelBox.Focus();
return;
}
if (!_isEdit)
{
string[] source = new string[10] { "modern", "professional", "creative", "minimal", "elegant", "dark", "colorful", "corporate", "magazine", "dashboard" };
if (source.Contains(_keyBox.Text.Trim().ToLowerInvariant()))
{
CustomMessageBox.Show("내장 무드와 동일한 키는 사용할 수 없습니다.", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_keyBox.Focus();
return;
}
}
base.DialogResult = true;
Close();
}
private static void AddLabel(StackPanel parent, string text, Brush fg)
{
parent.Children.Add(new TextBlock
{
Text = text,
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = fg,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
}
private static void AddHint(StackPanel parent, string text, Brush fg)
{
parent.Children.Add(new TextBlock
{
Text = text,
FontSize = 11.0,
Foreground = fg,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
}
private static void AddSeparator(StackPanel parent, Brush color)
{
parent.Children.Add(new Rectangle
{
Height = 1.0,
Fill = color,
Margin = new Thickness(0.0, 8.0, 0.0, 12.0),
Opacity = 0.5
});
}
private static TextBox CreateTextBox(string text, Brush fg, Brush bg, Brush caret, Brush border, bool multiline = false, int height = 100)
{
TextBox textBox = new TextBox
{
Text = text,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = fg,
Background = bg,
CaretBrush = caret,
BorderBrush = border,
BorderThickness = new Thickness(1.0)
};
if (multiline)
{
textBox.AcceptsReturn = true;
textBox.AcceptsTab = true;
textBox.TextWrapping = TextWrapping.Wrap;
textBox.MinHeight = height;
textBox.MaxHeight = height + 100;
textBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
}
return textBox;
}
}

View File

@@ -0,0 +1,664 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shapes;
namespace AxCopilot.Views;
internal sealed class CustomPresetDialog : Window
{
private readonly TextBox _nameBox;
private readonly TextBox _descBox;
private readonly TextBox _promptBox;
private readonly ComboBox _tabCombo;
private string _selectedColor;
private string _selectedSymbol;
private Border? _iconPreview;
private TextBlock? _iconPreviewText;
private static readonly (string Label, string Hex)[] Colors = new(string, string)[10]
{
("인디고", "#6366F1"),
("블루", "#3B82F6"),
("티일", "#14B8A6"),
("그린", "#22C55E"),
("옐로우", "#EAB308"),
("오렌지", "#F97316"),
("레드", "#EF4444"),
("핑크", "#EC4899"),
("퍼플", "#A855F7"),
("슬레이트", "#64748B")
};
private static readonly (string Category, (string Label, string Symbol)[] Icons)[] IconSets = new(string, (string, string)[])[5]
{
("업무", new(string, string)[8]
{
("일반", "\ue771"),
("문서", "\ue8a5"),
("메일", "\ue715"),
("캘린더", "\ue787"),
("차트", "\ue9d9"),
("발표", "\ue7f4"),
("계산기", "\ue8ef"),
("메모", "\ue70b")
}),
("기술", new(string, string)[8]
{
("코드", "\ue943"),
("설정", "\ue713"),
("데이터", "\uea86"),
("검색", "\ue721"),
("보안", "\ue72e"),
("서버", "\ue839"),
("버그", "\uebe8"),
("배포", "\ue7f8")
}),
("커뮤니케이션", new(string, string)[8]
{
("대화", "\ue8bd"),
("사람", "\ue77b"),
("팀", "\ue716"),
("전화", "\ue717"),
("알림", "\uea8f"),
("공유", "\ue72d"),
("피드백", "\ue939"),
("질문", "\ue897")
}),
("콘텐츠", new(string, string)[8]
{
("사진", "\ue722"),
("동영상", "\ue714"),
("음악", "\ue8d6"),
("글쓰기", "\ue70f"),
("책", "\ue82d"),
("웹", "\ue774"),
("디자인", "\ue790"),
("다운로드", "\ue896")
}),
("분석", new(string, string)[8]
{
("인사이트", "\ue9d9"),
("대시보드", "\ue809"),
("리포트", "\ue9f9"),
("트렌드", "\ue8a1"),
("필터", "\ue71c"),
("목표", "\ue7c1"),
("비교", "\ue8fd"),
("측정", "\ue7c8")
})
};
public string PresetName => _nameBox.Text.Trim();
public string PresetDescription => _descBox.Text.Trim();
public string PresetSystemPrompt => _promptBox.Text.Trim();
public string PresetTab => (_tabCombo.SelectedItem as ComboBoxItem)?.Tag?.ToString() ?? "Chat";
public string PresetColor => _selectedColor;
public string PresetSymbol => _selectedSymbol;
public CustomPresetDialog(string existingName = "", string existingDesc = "", string existingPrompt = "", string existingColor = "#6366F1", string existingSymbol = "\ue713", string existingTab = "Chat")
{
bool flag = !string.IsNullOrEmpty(existingName);
base.Title = (flag ? "프리셋 편집" : "프리셋 추가");
base.Width = 520.0;
base.SizeToContent = SizeToContent.Height;
base.WindowStartupLocation = WindowStartupLocation.CenterOwner;
base.ResizeMode = ResizeMode.NoResize;
base.WindowStyle = WindowStyle.None;
base.AllowsTransparency = true;
base.Background = Brushes.Transparent;
_selectedColor = existingColor;
_selectedSymbol = existingSymbol;
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush primaryText = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush brush = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush brush2 = (Application.Current.TryFindResource("AccentColor") as Brush) ?? Brushes.Blue;
Brush brush3 = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 43, 64));
Brush brush4 = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(16.0),
BorderBrush = brush4,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(28.0, 24.0, 28.0, 24.0),
Effect = new DropShadowEffect
{
BlurRadius = 24.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = System.Windows.Media.Colors.Black
}
};
StackPanel stackPanel = new StackPanel();
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 20.0)
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\ue710",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 18.0,
Foreground = brush2,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 10.0, 0.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = (flag ? "프리셋 편집" : "새 커스텀 프리셋"),
FontSize = 17.0,
FontWeight = FontWeights.Bold,
Foreground = primaryText,
VerticalAlignment = VerticalAlignment.Center
});
stackPanel.Children.Add(stackPanel2);
AddLabel(stackPanel, "프리셋 이름", primaryText);
AddHint(stackPanel, "대화 주제 버튼에 표시될 이름입니다", brush);
_nameBox = CreateTextBox(existingName, primaryText, brush3, brush2, brush4);
stackPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _nameBox
});
AddSeparator(stackPanel, brush4);
AddLabel(stackPanel, "설명", primaryText);
AddHint(stackPanel, "프리셋 카드 하단에 표시될 짧은 설명입니다", brush);
_descBox = CreateTextBox(existingDesc, primaryText, brush3, brush2, brush4);
stackPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _descBox
});
AddSeparator(stackPanel, brush4);
AddLabel(stackPanel, "아이콘 & 배경색", primaryText);
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
};
_iconPreview = new Border
{
Width = 48.0,
Height = 48.0,
CornerRadius = new CornerRadius(24.0),
Background = new SolidColorBrush(ParseColor(_selectedColor))
{
Opacity = 0.2
},
Cursor = Cursors.Hand,
Margin = new Thickness(0.0, 0.0, 16.0, 0.0),
ToolTip = "아이콘 선택"
};
_iconPreviewText = new TextBlock
{
Text = _selectedSymbol,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 20.0,
Foreground = BrushFromHex(_selectedColor),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
_iconPreview.Child = _iconPreviewText;
_iconPreview.MouseLeftButtonDown += delegate
{
ShowIconPickerPopup();
};
stackPanel3.Children.Add(_iconPreview);
StackPanel stackPanel4 = new StackPanel
{
Margin = new Thickness(0.0, 0.0, 16.0, 0.0)
};
stackPanel4.Children.Add(new TextBlock
{
Text = "탭",
FontSize = 11.0,
Foreground = brush,
Margin = new Thickness(0.0, 0.0, 0.0, 4.0)
});
_tabCombo = new ComboBox
{
Width = 100.0,
FontSize = 12.0,
Foreground = primaryText,
Background = brush3,
BorderBrush = brush4,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(6.0, 4.0, 6.0, 4.0)
};
_tabCombo.Items.Add(new ComboBoxItem
{
Content = "Chat",
Tag = "Chat",
IsSelected = (existingTab == "Chat")
});
_tabCombo.Items.Add(new ComboBoxItem
{
Content = "Cowork",
Tag = "Cowork",
IsSelected = (existingTab == "Cowork")
});
stackPanel4.Children.Add(_tabCombo);
stackPanel3.Children.Add(stackPanel4);
StackPanel stackPanel5 = new StackPanel
{
Children = { (UIElement)new TextBlock
{
Text = "배경색",
FontSize = 11.0,
Foreground = brush,
Margin = new Thickness(0.0, 0.0, 0.0, 4.0)
} }
};
WrapPanel colorPanel = new WrapPanel();
(string, string)[] colors = Colors;
for (int num = 0; num < colors.Length; num++)
{
(string, string) tuple = colors[num];
string item = tuple.Item1;
string item2 = tuple.Item2;
string colorHex = item2;
Border border2 = new Border
{
Width = 22.0,
Height = 22.0,
CornerRadius = new CornerRadius(11.0),
Background = BrushFromHex(item2),
Margin = new Thickness(0.0, 0.0, 5.0, 4.0),
Cursor = Cursors.Hand,
BorderThickness = new Thickness(2.0),
BorderBrush = ((item2 == _selectedColor) ? primaryText : Brushes.Transparent),
ToolTip = item
};
border2.MouseLeftButtonDown += delegate(object s, MouseButtonEventArgs _)
{
_selectedColor = colorHex;
foreach (object child in colorPanel.Children)
{
if (child is Border border3)
{
border3.BorderBrush = Brushes.Transparent;
}
}
if (s is Border border4)
{
border4.BorderBrush = primaryText;
}
UpdateIconPreview();
};
colorPanel.Children.Add(border2);
}
stackPanel5.Children.Add(colorPanel);
stackPanel3.Children.Add(stackPanel5);
stackPanel.Children.Add(stackPanel3);
AddSeparator(stackPanel, brush4);
AddLabel(stackPanel, "시스템 프롬프트", primaryText);
AddHint(stackPanel, "AI가 이 프리셋에서 따를 지침입니다. 비워두면 기본 프롬프트가 사용됩니다.", brush);
_promptBox = CreateTextBox(existingPrompt, primaryText, brush3, brush2, brush4, multiline: true);
stackPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _promptBox
});
TextBlock charCount = new TextBlock
{
FontSize = 10.5,
Foreground = brush,
Margin = new Thickness(0.0, 6.0, 0.0, 0.0),
HorizontalAlignment = HorizontalAlignment.Right
};
UpdateCharCount(charCount);
_promptBox.TextChanged += delegate
{
UpdateCharCount(charCount);
};
stackPanel.Children.Add(charCount);
StackPanel stackPanel6 = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 20.0, 0.0, 0.0)
};
Button button = new Button
{
Content = "취소",
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Margin = new Thickness(0.0, 0.0, 10.0, 0.0),
Background = Brushes.Transparent,
Foreground = brush,
BorderBrush = brush4,
BorderThickness = new Thickness(1.0),
Cursor = Cursors.Hand,
FontSize = 13.0
};
button.Click += delegate
{
base.DialogResult = false;
Close();
};
stackPanel6.Children.Add(button);
Button button2 = new Button
{
Content = (flag ? "저장" : "추가"),
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Background = brush2,
Foreground = Brushes.White,
BorderThickness = new Thickness(0.0),
Cursor = Cursors.Hand,
FontSize = 13.0,
FontWeight = FontWeights.SemiBold
};
button2.Click += delegate
{
if (string.IsNullOrWhiteSpace(_nameBox.Text))
{
CustomMessageBox.Show("프리셋 이름을 입력하세요.", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_nameBox.Focus();
}
else
{
base.DialogResult = true;
Close();
}
};
stackPanel6.Children.Add(button2);
stackPanel.Children.Add(stackPanel6);
border.Child = stackPanel;
base.Content = border;
base.KeyDown += delegate(object _, KeyEventArgs ke)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)ke.Key == 13)
{
base.DialogResult = false;
Close();
}
};
base.Loaded += delegate
{
_nameBox.Focus();
_nameBox.SelectAll();
};
border.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs me)
{
if (me.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
};
}
private void UpdateIconPreview()
{
if (_iconPreview != null && _iconPreviewText != null)
{
_iconPreview.Background = new SolidColorBrush(ParseColor(_selectedColor))
{
Opacity = 0.2
};
_iconPreviewText.Text = _selectedSymbol;
_iconPreviewText.Foreground = BrushFromHex(_selectedColor);
}
}
private void ShowIconPickerPopup()
{
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush brush = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush borderBrush = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Brush hoverBg = (Application.Current.TryFindResource("ItemHoverBackground") as Brush) ?? Brushes.Transparent;
Brush brush2 = (Application.Current.TryFindResource("AccentColor") as Brush) ?? Brushes.Blue;
Window pickerWin = new Window
{
Title = "아이콘 선택",
Width = 340.0,
SizeToContent = SizeToContent.Height,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Owner = this,
ResizeMode = ResizeMode.NoResize,
WindowStyle = WindowStyle.None,
AllowsTransparency = true,
Background = Brushes.Transparent
};
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(12.0),
BorderBrush = borderBrush,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(12.0),
Effect = new DropShadowEffect
{
BlurRadius = 16.0,
ShadowDepth = 3.0,
Opacity = 0.3,
Color = System.Windows.Media.Colors.Black
}
};
StackPanel stackPanel = new StackPanel();
Grid grid = new Grid();
grid.Children.Add(new TextBlock
{
Text = "아이콘 선택",
FontSize = 14.0,
FontWeight = FontWeights.SemiBold,
Foreground = brush,
Margin = new Thickness(0.0, 0.0, 0.0, 10.0),
HorizontalAlignment = HorizontalAlignment.Left
});
TextBlock textBlock = new TextBlock
{
Text = "\ue711",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 12.0,
Foreground = foreground,
Cursor = Cursors.Hand,
HorizontalAlignment = HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Top
};
textBlock.MouseLeftButtonDown += delegate
{
pickerWin.Close();
};
grid.Children.Add(textBlock);
stackPanel.Children.Add(grid);
border.MouseLeftButtonDown += delegate
{
try
{
pickerWin.DragMove();
}
catch
{
}
};
(string, (string, string)[])[] iconSets = IconSets;
for (int num = 0; num < iconSets.Length; num++)
{
var (text, array) = iconSets[num];
stackPanel.Children.Add(new TextBlock
{
Text = text,
FontSize = 11.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 6.0, 0.0, 4.0)
});
WrapPanel wrapPanel = new WrapPanel();
(string, string)[] array2 = array;
for (int num2 = 0; num2 < array2.Length; num2++)
{
(string, string) tuple2 = array2[num2];
string item = tuple2.Item1;
string item2 = tuple2.Item2;
string capturedSymbol = item2;
bool flag = _selectedSymbol == item2;
Border border2 = new Border
{
Width = 36.0,
Height = 36.0,
CornerRadius = new CornerRadius(8.0),
Background = (flag ? new SolidColorBrush(ParseColor(_selectedColor))
{
Opacity = 0.2
} : Brushes.Transparent),
BorderBrush = (flag ? brush2 : Brushes.Transparent),
BorderThickness = new Thickness(flag ? 1.5 : 0.0),
Cursor = Cursors.Hand,
Margin = new Thickness(0.0, 0.0, 4.0, 4.0),
ToolTip = item
};
border2.Child = new TextBlock
{
Text = item2,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 16.0,
Foreground = (flag ? BrushFromHex(_selectedColor) : brush),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
border2.MouseEnter += delegate(object s, MouseEventArgs _)
{
if (s is Border border3 && !(_selectedSymbol == capturedSymbol))
{
border3.Background = hoverBg;
}
};
border2.MouseLeave += delegate(object s, MouseEventArgs _)
{
if (s is Border border3 && !(_selectedSymbol == capturedSymbol))
{
border3.Background = Brushes.Transparent;
}
};
border2.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs e)
{
e.Handled = true;
_selectedSymbol = capturedSymbol;
UpdateIconPreview();
pickerWin.Close();
};
wrapPanel.Children.Add(border2);
}
stackPanel.Children.Add(wrapPanel);
}
border.Child = stackPanel;
pickerWin.Content = border;
pickerWin.ShowDialog();
}
private static void AddLabel(StackPanel parent, string text, Brush fg)
{
parent.Children.Add(new TextBlock
{
Text = text,
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = fg,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
}
private static void AddHint(StackPanel parent, string text, Brush fg)
{
parent.Children.Add(new TextBlock
{
Text = text,
FontSize = 11.0,
Foreground = fg,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
}
private static void AddSeparator(StackPanel parent, Brush color)
{
parent.Children.Add(new Rectangle
{
Height = 1.0,
Fill = color,
Margin = new Thickness(0.0, 12.0, 0.0, 12.0),
Opacity = 0.5
});
}
private static TextBox CreateTextBox(string text, Brush fg, Brush bg, Brush caret, Brush border, bool multiline = false)
{
TextBox textBox = new TextBox
{
Text = text,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = fg,
Background = bg,
CaretBrush = caret,
BorderBrush = border,
BorderThickness = new Thickness(1.0)
};
if (multiline)
{
textBox.AcceptsReturn = true;
textBox.TextWrapping = TextWrapping.Wrap;
textBox.MinHeight = 100.0;
textBox.MaxHeight = 200.0;
textBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
}
return textBox;
}
private void UpdateCharCount(TextBlock tb)
{
tb.Text = $"{_promptBox.Text.Length}자";
}
private static Brush BrushFromHex(string hex)
{
try
{
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(hex));
}
catch
{
return Brushes.Gray;
}
}
private static Color ParseColor(string hex)
{
try
{
return (Color)ColorConverter.ConvertFromString(hex);
}
catch
{
return System.Windows.Media.Colors.Gray;
}
}
}

View File

@@ -0,0 +1,244 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using AxCopilot.Services;
namespace AxCopilot.Views;
public class DiffViewerPanel : Border
{
private readonly string _filePath;
private readonly string _oldContent;
private readonly string _newContent;
private readonly List<DiffService.DiffLine> _diffLines;
public event EventHandler? Accepted;
public event EventHandler? Rejected;
public DiffViewerPanel(string filePath, string oldContent, string newContent)
{
_filePath = filePath;
_oldContent = oldContent;
_newContent = newContent;
_diffLines = DiffService.ComputeDiff(oldContent, newContent);
base.CornerRadius = new CornerRadius(10.0);
base.Background = new SolidColorBrush(Color.FromRgb(250, 250, byte.MaxValue));
base.BorderBrush = new SolidColorBrush(Color.FromRgb(224, 224, 236));
base.BorderThickness = new Thickness(1.0);
base.Padding = new Thickness(0.0);
base.Margin = new Thickness(0.0, 8.0, 0.0, 8.0);
Child = BuildContent();
}
private UIElement BuildContent()
{
StackPanel stackPanel = new StackPanel();
Border border = new Border
{
Background = new SolidColorBrush(Color.FromRgb(240, 242, byte.MaxValue)),
CornerRadius = new CornerRadius(10.0, 10.0, 0.0, 0.0),
Padding = new Thickness(14.0, 10.0, 14.0, 10.0)
};
Grid grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1.0, GridUnitType.Star)
});
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = GridLength.Auto
});
string summary = DiffService.GetSummary(_diffLines);
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\ue89a",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 13.0,
Foreground = new SolidColorBrush(Color.FromRgb(75, 94, 252)),
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 8.0, 0.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = Path.GetFileName(_filePath),
FontSize = 13.0,
FontWeight = FontWeights.SemiBold,
Foreground = new SolidColorBrush(Color.FromRgb(26, 27, 46)),
VerticalAlignment = VerticalAlignment.Center
});
stackPanel2.Children.Add(new TextBlock
{
Text = " · " + summary,
FontSize = 11.0,
Foreground = new SolidColorBrush(Color.FromRgb(136, 136, 170)),
VerticalAlignment = VerticalAlignment.Center
});
Grid.SetColumn(stackPanel2, 0);
grid.Children.Add(stackPanel2);
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal
};
Button button = CreateButton("적용", Color.FromRgb(16, 124, 16), Colors.White);
button.Click += delegate
{
this.Accepted?.Invoke(this, EventArgs.Empty);
};
stackPanel3.Children.Add(button);
Button button2 = CreateButton("취소", Colors.Transparent, Color.FromRgb(197, 15, 31));
button2.Click += delegate
{
this.Rejected?.Invoke(this, EventArgs.Empty);
};
stackPanel3.Children.Add(button2);
Grid.SetColumn(stackPanel3, 1);
grid.Children.Add(stackPanel3);
border.Child = grid;
stackPanel.Children.Add(border);
ScrollViewer scrollViewer = new ScrollViewer
{
MaxHeight = 300.0,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
HorizontalScrollBarVisibility = ScrollBarVisibility.Auto
};
StackPanel stackPanel4 = new StackPanel
{
Margin = new Thickness(0.0)
};
foreach (DiffService.DiffLine diffLine in _diffLines)
{
DiffService.DiffType type = diffLine.Type;
if (1 == 0)
{
}
(Color, Color, string) tuple = type switch
{
DiffService.DiffType.Added => (Color.FromRgb(230, byte.MaxValue, 237), Color.FromRgb(22, 108, 52), "+"),
DiffService.DiffType.Removed => (Color.FromRgb(byte.MaxValue, 235, 233), Color.FromRgb(207, 34, 46), "-"),
_ => (Color.FromRgb(byte.MaxValue, byte.MaxValue, byte.MaxValue), Color.FromRgb(102, 102, 136), " "),
};
if (1 == 0)
{
}
(Color, Color, string) tuple2 = tuple;
Color item = tuple2.Item1;
Color item2 = tuple2.Item2;
string item3 = tuple2.Item3;
string text = diffLine.OldLineNo?.ToString() ?? "";
string text2 = diffLine.NewLineNo?.ToString() ?? "";
Border border2 = new Border
{
Background = new SolidColorBrush(item),
Padding = new Thickness(8.0, 1.0, 8.0, 1.0)
};
Grid grid2 = new Grid();
grid2.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(36.0)
});
grid2.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(36.0)
});
grid2.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(16.0)
});
grid2.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1.0, GridUnitType.Star)
});
TextBlock element = new TextBlock
{
Text = text,
FontSize = 10.0,
FontFamily = new FontFamily("Consolas"),
Foreground = new SolidColorBrush(Color.FromRgb(170, 170, 204)),
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 0.0, 4.0, 0.0)
};
Grid.SetColumn(element, 0);
grid2.Children.Add(element);
TextBlock element2 = new TextBlock
{
Text = text2,
FontSize = 10.0,
FontFamily = new FontFamily("Consolas"),
Foreground = new SolidColorBrush(Color.FromRgb(170, 170, 204)),
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 0.0, 4.0, 0.0)
};
Grid.SetColumn(element2, 1);
grid2.Children.Add(element2);
TextBlock element3 = new TextBlock
{
Text = item3,
FontSize = 11.0,
FontFamily = new FontFamily("Consolas"),
Foreground = new SolidColorBrush(item2),
FontWeight = FontWeights.Bold
};
Grid.SetColumn(element3, 2);
grid2.Children.Add(element3);
TextBlock element4 = new TextBlock
{
Text = diffLine.Content,
FontSize = 11.0,
FontFamily = new FontFamily("Consolas"),
Foreground = new SolidColorBrush(item2),
TextWrapping = TextWrapping.NoWrap
};
Grid.SetColumn(element4, 3);
grid2.Children.Add(element4);
border2.Child = grid2;
stackPanel4.Children.Add(border2);
}
scrollViewer.Content = stackPanel4;
stackPanel.Children.Add(scrollViewer);
return stackPanel;
}
private static Button CreateButton(string text, Color bg, Color fg)
{
Button button = new Button
{
Cursor = Cursors.Hand,
Margin = new Thickness(4.0, 0.0, 0.0, 0.0)
};
ControlTemplate controlTemplate = new ControlTemplate(typeof(Button));
FrameworkElementFactory frameworkElementFactory = new FrameworkElementFactory(typeof(Border));
frameworkElementFactory.SetValue(Border.BackgroundProperty, new SolidColorBrush(bg));
frameworkElementFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(6.0));
frameworkElementFactory.SetValue(Border.PaddingProperty, new Thickness(12.0, 5.0, 12.0, 5.0));
if (bg == Colors.Transparent)
{
frameworkElementFactory.SetValue(Border.BorderBrushProperty, new SolidColorBrush(fg));
frameworkElementFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1.0));
}
FrameworkElementFactory frameworkElementFactory2 = new FrameworkElementFactory(typeof(ContentPresenter));
frameworkElementFactory2.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Center);
frameworkElementFactory.AppendChild(frameworkElementFactory2);
controlTemplate.VisualTree = frameworkElementFactory;
button.Template = controlTemplate;
button.Content = new TextBlock
{
Text = text,
FontSize = 11.0,
Foreground = new SolidColorBrush(fg),
FontWeight = FontWeights.SemiBold
};
return button;
}
}

View File

@@ -0,0 +1,561 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
namespace AxCopilot.Views;
public class DockBarWindow : Window, IComponentConnector
{
private struct MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
}
private DispatcherTimer? _timer;
private PerformanceCounter? _cpuCounter;
private TextBlock? _cpuText;
private TextBlock? _ramText;
private TextBlock? _clockText;
private TextBox? _quickInput;
private static readonly (string Key, string Icon, string Tooltip)[] AllItems = new(string, string, string)[8]
{
("launcher", "\ue721", "AX Commander"),
("clipboard", "\ue77f", "클립보드 히스토리"),
("capture", "\ue722", "화면 캡처"),
("agent", "\ue8bd", "AX Agent"),
("clock", "\ue823", "시계"),
("cpu", "\ue950", "CPU"),
("ram", "\ue7f4", "RAM"),
("quickinput", "\ue8d3", "빠른 입력")
};
private DispatcherTimer? _glowTimer;
private static readonly string[] FixedOrder = new string[8] { "launcher", "clipboard", "capture", "agent", "clock", "cpu", "ram", "quickinput" };
internal Border RainbowGlowBorder;
internal LinearGradientBrush RainbowBrush;
internal Border DockBorder;
internal StackPanel DockContent;
private bool _contentLoaded;
public Action<string>? OnQuickSearch { get; set; }
public Action? OnCapture { get; set; }
public Action? OnOpenAgent { get; set; }
public Action<double, double>? OnPositionChanged { get; set; }
public static IReadOnlyList<(string Key, string Icon, string Tooltip)> AvailableItems => AllItems;
public DockBarWindow()
{
InitializeComponent();
base.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
};
base.LocationChanged += delegate
{
OnPositionChanged?.Invoke(base.Left, base.Top);
};
base.Loaded += delegate
{
PositionDock();
};
base.Closed += delegate
{
DispatcherTimer? timer = _timer;
if (timer != null)
{
timer.Stop();
}
DispatcherTimer? glowTimer = _glowTimer;
if (glowTimer != null)
{
glowTimer.Stop();
}
_cpuCounter?.Dispose();
};
}
public void ApplySettings(double opacity, double left, double top, bool rainbowGlow)
{
base.Opacity = Math.Clamp(opacity, 0.3, 1.0);
if (left >= 0.0 && top >= 0.0)
{
base.Left = left;
base.Top = top;
}
else
{
((DispatcherObject)this).Dispatcher.BeginInvoke((DispatcherPriority)6, (Delegate)new Action(PositionDock));
}
if (rainbowGlow)
{
StartRainbowGlow();
}
else
{
StopRainbowGlow();
}
}
private void StartRainbowGlow()
{
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
//IL_0029: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Expected O, but got Unknown
RainbowGlowBorder.Visibility = Visibility.Visible;
if (_glowTimer == null)
{
_glowTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(50.0)
};
}
double startAngle = 0.0;
_glowTimer.Tick += delegate
{
//IL_009f: Unknown result type (might be due to invalid IL or missing references)
//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
startAngle += 2.0;
if (startAngle >= 360.0)
{
startAngle -= 360.0;
}
double num = startAngle * Math.PI / 180.0;
RainbowBrush.StartPoint = new Point(0.5 + 0.5 * Math.Cos(num), 0.5 + 0.5 * Math.Sin(num));
RainbowBrush.EndPoint = new Point(0.5 - 0.5 * Math.Cos(num), 0.5 - 0.5 * Math.Sin(num));
};
_glowTimer.Start();
}
private void StopRainbowGlow()
{
DispatcherTimer? glowTimer = _glowTimer;
if (glowTimer != null)
{
glowTimer.Stop();
}
RainbowGlowBorder.Visibility = Visibility.Collapsed;
}
public void BuildFromSettings(List<string> itemKeys)
{
//IL_080a: Unknown result type (might be due to invalid IL or missing references)
//IL_080f: Unknown result type (might be due to invalid IL or missing references)
//IL_0829: Expected O, but got Unknown
DockContent.Children.Clear();
_cpuText = null;
_ramText = null;
_clockText = null;
_quickInput = null;
Brush foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush brush = (TryFindResource("AccentColor") as Brush) ?? Brushes.CornflowerBlue;
bool flag = false;
bool flag2 = false;
HashSet<string> enabledSet = new HashSet<string>(itemKeys, StringComparer.OrdinalIgnoreCase);
foreach (string item in FixedOrder.Where((string k) => enabledSet.Contains(k)))
{
if (flag2)
{
AddSeparator();
}
flag2 = true;
switch (item)
{
case "launcher":
AddButton("\ue721", "AX Commander", foreground, delegate
{
OnQuickSearch?.Invoke("");
});
break;
case "clipboard":
AddButton("\ue77f", "클립보드", foreground, delegate
{
OnQuickSearch?.Invoke("#");
});
break;
case "capture":
AddButton("\ue722", "캡처", foreground, delegate
{
if (OnCapture != null)
{
OnCapture();
}
else
{
OnQuickSearch?.Invoke("cap");
}
});
break;
case "agent":
AddButton("\ue8bd", "AI", foreground, delegate
{
if (OnOpenAgent != null)
{
OnOpenAgent();
}
else
{
OnQuickSearch?.Invoke("!");
}
});
break;
case "clock":
_clockText = new TextBlock
{
Text = DateTime.Now.ToString("HH:mm"),
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(6.0, 0.0, 6.0, 0.0)
};
DockContent.Children.Add(_clockText);
flag = true;
break;
case "cpu":
{
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal,
VerticalAlignment = VerticalAlignment.Center
};
stackPanel3.Children.Add(new TextBlock
{
Text = "\ue950",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 11.0,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 3.0, 0.0)
});
_cpuText = new TextBlock
{
Text = "0%",
FontSize = 11.0,
Foreground = foreground2,
VerticalAlignment = VerticalAlignment.Center,
Width = 28.0,
TextAlignment = TextAlignment.Right
};
stackPanel3.Children.Add(_cpuText);
DockContent.Children.Add(stackPanel3);
flag = true;
if (_cpuCounter == null)
{
try
{
_cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
_cpuCounter.NextValue();
}
catch
{
}
}
break;
}
case "ram":
{
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal,
VerticalAlignment = VerticalAlignment.Center
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\ue7f4",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 11.0,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 3.0, 0.0)
});
_ramText = new TextBlock
{
Text = "0%",
FontSize = 11.0,
Foreground = foreground2,
VerticalAlignment = VerticalAlignment.Center,
Width = 28.0,
TextAlignment = TextAlignment.Right
};
stackPanel2.Children.Add(_ramText);
DockContent.Children.Add(stackPanel2);
flag = true;
break;
}
case "quickinput":
{
Border border = new Border();
border.Background = (TryFindResource("ItemBackground") as Brush) ?? Brushes.Transparent;
border.CornerRadius = new CornerRadius(8.0);
border.Padding = new Thickness(8.0, 3.0, 8.0, 3.0);
border.VerticalAlignment = VerticalAlignment.Center;
Border border2 = border;
StackPanel stackPanel = new StackPanel
{
Orientation = Orientation.Horizontal
};
stackPanel.Children.Add(new TextBlock
{
Text = "\ue721",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 11.0,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 5.0, 0.0)
});
_quickInput = new TextBox
{
Width = 100.0,
FontSize = 11.0,
Foreground = foreground,
CaretBrush = brush,
Background = Brushes.Transparent,
BorderThickness = new Thickness(0.0),
VerticalAlignment = VerticalAlignment.Center
};
_quickInput.KeyDown += QuickInput_KeyDown;
stackPanel.Children.Add(_quickInput);
border2.Child = stackPanel;
DockContent.Children.Add(border2);
break;
}
}
}
if (flag)
{
if (_timer == null)
{
_timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1.0)
};
}
_timer.Tick -= OnTick;
_timer.Tick += OnTick;
_timer.Start();
OnTick(null, EventArgs.Empty);
}
}
private void AddButton(string icon, string tooltip, Brush foreground, Action click)
{
Border border = new Border
{
Width = 30.0,
Height = 30.0,
CornerRadius = new CornerRadius(8.0),
Background = new SolidColorBrush(Color.FromArgb(1, byte.MaxValue, byte.MaxValue, byte.MaxValue)),
Cursor = Cursors.Hand,
ToolTip = tooltip,
Margin = new Thickness(2.0, 0.0, 2.0, 0.0)
};
border.Child = new TextBlock
{
Text = icon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 14.0,
Foreground = foreground,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center,
IsHitTestVisible = false
};
border.MouseEnter += delegate(object s, MouseEventArgs _)
{
if (s is Border border2)
{
border2.Background = new SolidColorBrush(Color.FromArgb(34, byte.MaxValue, byte.MaxValue, byte.MaxValue));
}
};
border.MouseLeave += delegate(object s, MouseEventArgs _)
{
if (s is Border border2)
{
border2.Background = new SolidColorBrush(Color.FromArgb(1, byte.MaxValue, byte.MaxValue, byte.MaxValue));
}
};
border.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs e)
{
e.Handled = true;
click();
};
DockContent.Children.Add(border);
}
private void AddSeparator()
{
DockContent.Children.Add(new Border
{
Width = 1.0,
Height = 20.0,
Margin = new Thickness(6.0, 0.0, 6.0, 0.0),
Background = ((TryFindResource("SeparatorColor") as Brush) ?? Brushes.Gray)
});
}
private void PositionDock()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
Rect workArea = SystemParameters.WorkArea;
base.Left = (((Rect)(ref workArea)).Width - base.ActualWidth) / 2.0 + ((Rect)(ref workArea)).Left;
base.Top = ((Rect)(ref workArea)).Bottom - base.ActualHeight - 8.0;
}
private void OnTick(object? sender, EventArgs e)
{
if (_clockText != null)
{
_clockText.Text = DateTime.Now.ToString("HH:mm");
}
if (_cpuText != null)
{
try
{
_cpuText.Text = $"{_cpuCounter?.NextValue() ?? 0f:F0}%";
}
catch
{
_cpuText.Text = "-";
}
}
if (_ramText != null)
{
try
{
MEMORYSTATUSEX lpBuffer = new MEMORYSTATUSEX
{
dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>()
};
_ramText.Text = (GlobalMemoryStatusEx(ref lpBuffer) ? $"{lpBuffer.dwMemoryLoad}%" : "-");
}
catch
{
_ramText.Text = "-";
}
}
}
[DllImport("kernel32.dll")]
private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
private void QuickInput_KeyDown(object sender, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_0067: Unknown result type (might be due to invalid IL or missing references)
//IL_006e: Invalid comparison between Unknown and I4
if ((int)e.Key == 6 && _quickInput != null && !string.IsNullOrWhiteSpace(_quickInput.Text))
{
OnQuickSearch?.Invoke(_quickInput.Text);
_quickInput.Text = "";
e.Handled = true;
}
else if ((int)e.Key == 13 && _quickInput != null)
{
_quickInput.Text = "";
e.Handled = true;
}
}
private void Window_KeyDown(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
if ((int)e.Key == 13)
{
Hide();
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/dockbarwindow.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:
((DockBarWindow)target).KeyDown += Window_KeyDown;
break;
case 2:
RainbowGlowBorder = (Border)target;
break;
case 3:
RainbowBrush = (LinearGradientBrush)target;
break;
case 4:
DockBorder = (Border)target;
break;
case 5:
DockContent = (StackPanel)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,196 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Shapes;
namespace AxCopilot.Views;
public class EyeDropperWindow : Window, IComponentConnector
{
private struct POINT
{
public int X;
public int Y;
}
private readonly System.Drawing.Rectangle _screenBounds;
internal Canvas RootCanvas;
internal Border Magnifier;
internal Ellipse MagPreview;
internal Border HexLabel;
internal TextBlock HexLabelText;
private bool _contentLoaded;
public System.Drawing.Color? PickedColor { get; private set; }
public double PickX { get; private set; }
public double PickY { get; private set; }
[DllImport("user32.dll")]
private static extern bool GetCursorPos(out POINT lpPoint);
[DllImport("gdi32.dll")]
private static extern uint GetPixel(nint hdc, int x, int y);
[DllImport("user32.dll")]
private static extern nint GetDC(nint hWnd);
[DllImport("user32.dll")]
private static extern int ReleaseDC(nint hWnd, nint hDC);
public EyeDropperWindow()
{
InitializeComponent();
_screenBounds = GetAllScreenBounds();
base.Left = _screenBounds.X;
base.Top = _screenBounds.Y;
base.Width = _screenBounds.Width;
base.Height = _screenBounds.Height;
base.Loaded += delegate
{
Magnifier.Visibility = Visibility.Visible;
HexLabel.Visibility = Visibility.Visible;
};
}
private void Window_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
Point position = e.GetPosition(RootCanvas);
System.Drawing.Color screenPixelColor = GetScreenPixelColor();
Canvas.SetLeft(Magnifier, ((Point)(ref position)).X + 16.0);
Canvas.SetTop(Magnifier, ((Point)(ref position)).Y - 100.0);
Canvas.SetLeft(HexLabel, ((Point)(ref position)).X + 16.0);
Canvas.SetTop(HexLabel, ((Point)(ref position)).Y - 10.0);
System.Windows.Media.Color color = System.Windows.Media.Color.FromRgb(screenPixelColor.R, screenPixelColor.G, screenPixelColor.B);
MagPreview.Fill = new SolidColorBrush(color);
HexLabelText.Text = $"#{screenPixelColor.R:X2}{screenPixelColor.G:X2}{screenPixelColor.B:X2}";
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
{
PickedColor = GetScreenPixelColor();
GetCursorPos(out var lpPoint);
PickX = lpPoint.X;
PickY = lpPoint.Y;
Close();
}
else if (e.ChangedButton == MouseButton.Right)
{
PickedColor = null;
Close();
}
}
private void Window_KeyDown(object sender, System.Windows.Input.KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)e.Key == 13)
{
PickedColor = null;
Close();
}
}
private static System.Drawing.Color GetScreenPixelColor()
{
GetCursorPos(out var lpPoint);
nint dC = GetDC(IntPtr.Zero);
try
{
uint pixel = GetPixel(dC, lpPoint.X, lpPoint.Y);
int red = (int)(pixel & 0xFF);
int green = (int)((pixel >> 8) & 0xFF);
int blue = (int)((pixel >> 16) & 0xFF);
return System.Drawing.Color.FromArgb(red, green, blue);
}
finally
{
ReleaseDC(IntPtr.Zero, dC);
}
}
private static System.Drawing.Rectangle GetAllScreenBounds()
{
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
Screen[] allScreens = Screen.AllScreens;
foreach (Screen screen in allScreens)
{
System.Drawing.Rectangle bounds = screen.Bounds;
num = Math.Min(num, bounds.Left);
num2 = Math.Min(num2, bounds.Top);
num3 = Math.Max(num3, bounds.Right);
num4 = Math.Max(num4, bounds.Bottom);
}
return new System.Drawing.Rectangle(num, num2, num3 - num, num4 - num2);
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/eyedropperwindow.xaml", UriKind.Relative);
System.Windows.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:
((EyeDropperWindow)target).MouseDown += Window_MouseDown;
((EyeDropperWindow)target).MouseMove += Window_MouseMove;
((EyeDropperWindow)target).KeyDown += Window_KeyDown;
break;
case 2:
RootCanvas = (Canvas)target;
break;
case 3:
Magnifier = (Border)target;
break;
case 4:
MagPreview = (Ellipse)target;
break;
case 5:
HexLabel = (Border)target;
break;
case 6:
HexLabelText = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,230 @@
#define DEBUG
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using AxCopilot.Services;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
namespace AxCopilot.Views;
public class GuideViewerWindow : Window, IComponentConnector
{
private string? _pendingHtml;
private Uri? _pendingUri;
internal TextBlock TitleText;
internal TextBlock MaxBtnIcon;
internal WebView2 GuideBrowser;
private bool _contentLoaded;
public GuideViewerWindow()
{
InitializeComponent();
base.Loaded += OnLoaded;
base.KeyDown += delegate(object _, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)e.Key == 13)
{
Close();
}
};
base.StateChanged += delegate
{
MaxBtnIcon.Text = ((base.WindowState == WindowState.Maximized) ? "\ue923" : "\ue922");
};
}
private async void OnLoaded(object sender, RoutedEventArgs e)
{
bool devMode = (Application.Current as App)?.SettingsService?.Settings?.Llm?.DevMode == true;
PrepareGuide(devMode);
try
{
CoreWebView2Environment env = await CoreWebView2Environment.CreateAsync(null, Path.Combine(Path.GetTempPath(), "AxCopilot_GuideViewer"));
await GuideBrowser.EnsureCoreWebView2Async(env);
if (_pendingHtml != null)
{
GuideBrowser.NavigateToString(_pendingHtml);
}
else if (_pendingUri != null)
{
GuideBrowser.Source = _pendingUri;
}
}
catch (Exception ex)
{
Debug.WriteLine("WebView2 init error: " + ex.Message);
}
}
public void PrepareGuide(bool devMode)
{
TitleText.Text = (devMode ? "AX Copilot 개발자 가이드" : "AX Copilot 사용 가이드");
base.Title = (devMode ? "AX Copilot — 개발자 가이드" : "AX Copilot — 사용 가이드");
try
{
string path = Path.GetDirectoryName(Environment.ProcessPath) ?? AppContext.BaseDirectory;
string path2 = Path.Combine(path, "Assets");
string text = (devMode ? Path.Combine(path2, "guide_dev.enc") : Path.Combine(path2, "guide_user.enc"));
if (File.Exists(text))
{
_pendingHtml = GuideEncryptor.DecryptToString(text);
return;
}
string text2 = (devMode ? Path.Combine(path2, "AX Copilot 개발자가이드.htm") : Path.Combine(path2, "AX Copilot 사용가이드.htm"));
if (File.Exists(text2))
{
_pendingUri = new Uri(text2);
}
else
{
_pendingHtml = "<html><body style='font-family:Segoe UI;padding:40px;color:#666;'><h2>가이드를 찾을 수 없습니다</h2><p>경로: " + text + "</p></body></html>";
}
}
catch (Exception ex)
{
_pendingHtml = "<html><body style='font-family:Segoe UI;padding:40px;color:#c00;'><h2>가이드 로드 오류</h2><p>" + ex.Message + "</p></body></html>";
}
}
public void LoadGuide(bool devMode)
{
PrepareGuide(devMode);
if (GuideBrowser.CoreWebView2 != null)
{
if (_pendingHtml != null)
{
GuideBrowser.NavigateToString(_pendingHtml);
}
else if (_pendingUri != null)
{
GuideBrowser.Source = _pendingUri;
}
}
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
ToggleMaximize();
}
else
{
DragMove();
}
}
private void MinBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
base.WindowState = WindowState.Minimized;
}
private void MaxBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
ToggleMaximize();
}
private void CloseBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
Close();
}
private void ToggleMaximize()
{
base.WindowState = ((base.WindowState != WindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
}
private void TitleBtn_Enter(object sender, MouseEventArgs e)
{
if (sender is Border border)
{
border.Background = (TryFindResource("ItemHoverBackground") as Brush) ?? new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
}
}
private void CloseBtnEnter(object sender, MouseEventArgs e)
{
if (sender is Border border)
{
border.Background = new SolidColorBrush(Color.FromArgb(68, byte.MaxValue, 64, 64));
}
}
private void TitleBtn_Leave(object sender, MouseEventArgs e)
{
if (sender is Border border)
{
border.Background = Brushes.Transparent;
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/guideviewerwindow.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:
((Border)target).MouseLeftButtonDown += TitleBar_MouseLeftButtonDown;
break;
case 2:
TitleText = (TextBlock)target;
break;
case 3:
((Border)target).MouseLeftButtonDown += MinBtn_Click;
((Border)target).MouseEnter += TitleBtn_Enter;
((Border)target).MouseLeave += TitleBtn_Leave;
break;
case 4:
((Border)target).MouseLeftButtonDown += MaxBtn_Click;
((Border)target).MouseEnter += TitleBtn_Enter;
((Border)target).MouseLeave += TitleBtn_Leave;
break;
case 5:
MaxBtnIcon = (TextBlock)target;
break;
case 6:
((Border)target).MouseLeftButtonDown += CloseBtn_Click;
((Border)target).MouseEnter += CloseBtnEnter;
((Border)target).MouseLeave += TitleBtn_Leave;
break;
case 7:
GuideBrowser = (WebView2)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,706 @@
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;
namespace AxCopilot.Views;
public class HelpDetailWindow : Window, IComponentConnector
{
private enum TopMenu
{
Overview,
Shortcuts,
Prefixes
}
private const string CatAll = "전체";
private const string CatPopular = "⭐ 인기";
private static readonly (TopMenu Key, string Label, string Icon)[] TopMenus = new(TopMenu, string, string)[3]
{
(TopMenu.Overview, "개요", "\ue946"),
(TopMenu.Shortcuts, "단축키 현황", "\ue765"),
(TopMenu.Prefixes, "예약어 현황", "\ue8f4")
};
private TopMenu _currentTopMenu = TopMenu.Overview;
private readonly List<HelpItemModel> _allItems;
private readonly List<HelpItemModel> _shortcutItems;
private readonly List<HelpItemModel> _prefixItems;
private readonly List<HelpItemModel> _overviewItems;
private readonly string _globalHotkey;
private List<string> _categories = new List<string>();
private int _currentPage;
internal TextBlock SubtitleText;
internal StackPanel TopMenuBar;
internal TextBox SearchBox;
internal WrapPanel CategoryBar;
internal ItemsControl ItemsHost;
internal Button PrevBtn;
internal TextBlock PageIndicator;
internal Button NextBtn;
private bool _contentLoaded;
private Brush ThemeAccent => (TryFindResource("AccentColor") as Brush) ?? ParseColor("#4B5EFC");
private Brush ThemePrimary => (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
private Brush ThemeSecondary => (TryFindResource("SecondaryText") as Brush) ?? ParseColor("#8899CC");
public HelpDetailWindow(IEnumerable<HelpItemModel> items, int totalCount, string globalHotkey = "Alt+Space")
{
InitializeComponent();
_allItems = items.ToList();
_globalHotkey = globalHotkey;
_overviewItems = new List<HelpItemModel>
{
new HelpItemModel
{
Category = "개요",
Command = "AX Commander",
Title = "키보드 하나로 모든 업무를 제어하는 AX Commander",
Description = "단축키 한 번으로 앱 실행, 파일/폴더 검색, 계산, 클립보드 관리, 화면 캡처, 창 전환, 시스템 제어, 업무 일지, 루틴 자동화, AI 대화까지. 40개+ 명령어를 예약어로 즉시 접근.",
Symbol = "\ue946",
ColorBrush = ParseColor("#4B5EFC")
},
new HelpItemModel
{
Category = "개요",
Command = "사용법",
Title = "예약어 + 키워드 → Enter",
Description = "특수 문자를 맨 앞에 입력하면 해당 기능 모드로 전환됩니다. 예) = 수식, # 클립보드, ? 웹검색, ! AI 대화, cap 캡처. 예약어 없이 입력하면 앱/파일/폴더 검색.",
Symbol = "\ue765",
ColorBrush = ParseColor("#0078D4")
},
new HelpItemModel
{
Category = "개요",
Command = "데이터 보호",
Title = "모든 데이터는 내 PC에만 안전하게 저장",
Description = "설정, 클립보드, 대화 내역, 통계, 로그 등 모든 데이터가 로컬에 암호화 저장됩니다. 다른 PC에서는 열 수 없으며, 보존 기간 만료 시 자동 삭제됩니다.",
Symbol = "\ue8b7",
ColorBrush = ParseColor("#107C10")
},
new HelpItemModel
{
Category = "AI",
Command = "! (AX Agent)",
Title = "AX Agent — AI 어시스턴트와 대화",
Description = "AX Commander에서 ! 를 입력하면 AI 대화가 열립니다. 질문을 바로 물어보거나, 이전 대화를 이어갈 수 있습니다. 대화 주제별 분류, 검색, 사이드바 토글을 지원합니다.",
Example = "! 오늘 회의 요약해줘\n! 이메일 초안 작성해줘",
Symbol = "\ue8bd",
ColorBrush = ParseColor("#8B2FC9")
},
new HelpItemModel
{
Category = "AI",
Command = "3탭 구조",
Title = "Chat · Cowork · Code — 용도별 3탭 구조",
Description = "Chat: 자유로운 AI 대화 — 질문, 번역, 요약, 아이디어 브레인스토밍.\nCowork: 업무 보조 — 파일 읽기/쓰기, 문서 생성(Excel·Word·PPT·HTML), 데이터 분석, 보고서 작성.\nCode: 코딩 도우미 — 개발, 리팩터링, 코드 리뷰, 보안 점검, 테스트 작성. 개발 환경 자동 감지.",
Symbol = "\ue71b",
ColorBrush = ParseColor("#3B82F6")
},
new HelpItemModel
{
Category = "AI",
Command = "AI 서비스",
Title = "사내 AI · 외부 AI 서비스 선택 가능",
Description = "관리자가 설정한 AI 서비스에 자동 연결됩니다. 사내 서버와 외부 서비스 중 선택할 수 있으며, 연결 정보는 암호화되어 보호됩니다.",
Symbol = "\ue968",
ColorBrush = ParseColor("#0078D4")
},
new HelpItemModel
{
Category = "AI",
Command = "실시간 응답",
Title = "AI 응답이 실시간으로 표시",
Description = "AI의 응답이 생성되는 즉시 화면에 표시됩니다. 긴 답변도 기다리지 않고 바로 읽기 시작할 수 있습니다.",
Symbol = "\ue8ab",
ColorBrush = ParseColor("#107C10")
},
new HelpItemModel
{
Category = "AI",
Command = "대화 보호",
Title = "모든 대화 내역이 암호화 저장",
Description = "대화 내역은 내 PC에서만 열람할 수 있도록 암호화됩니다. 다른 PC로 복사해도 열 수 없으며, 보존 기간 만료 시 자동 삭제됩니다.",
Symbol = "\ue72e",
ColorBrush = ParseColor("#C50F1F")
},
new HelpItemModel
{
Category = "AI",
Command = "AI 규칙 설정",
Title = "관리자가 설정한 응답 규칙이 자동 적용",
Description = "관리자가 지정한 역할, 응답 톤, 업무 규칙이 모든 대화에 자동 적용됩니다. AI의 응답 스타일을 일괄 관리할 수 있습니다.",
Symbol = "\ue771",
ColorBrush = ParseColor("#D97706")
},
new HelpItemModel
{
Category = "AI",
Command = "대화 관리",
Title = "분류 · 검색 · 타임라인",
Description = "대화를 주제별로 분류하고, 오늘/이전 타임라인으로 구분합니다. 검색과 카테고리 필터로 빠르게 찾을 수 있습니다.",
Symbol = "\ue8f1",
ColorBrush = ParseColor("#4B5EFC")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "note",
Title = "빠른 메모 저장 · 검색",
Description = "note 뒤에 내용을 입력하면 즉시 메모가 저장됩니다. 나중에 note 키워드로 검색하면 이전 메모를 다시 찾을 수 있습니다. 간단한 아이디어나 할 일을 빠르게 기록하세요.",
Example = "note 내일 보고서 마감\nnote 김부장님 연락처 확인",
Symbol = "\ue70b",
ColorBrush = ParseColor("#D97706")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "journal",
Title = "업무 일지 작성",
Description = "journal 뒤에 내용을 입력하면 날짜별 업무 일지로 자동 기록됩니다. 하루 동안의 업무 내용을 간결하게 쌓아가면 주간 보고나 회고에 활용할 수 있습니다.",
Example = "journal 배포 완료\njournal 클라이언트 미팅 30분",
Symbol = "\ue8f2",
ColorBrush = ParseColor("#0078D4")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "pipe",
Title = "클립보드 텍스트 파이프라인 변환",
Description = "클립보드에 복사된 텍스트를 여러 변환 함수로 한 번에 처리합니다. upper(대문자), lower(소문자), trim(공백 제거), wrap(줄바꿈), sort(정렬) 등을 연결할 수 있습니다.",
Example = "pipe upper | trim | wrap 80",
Symbol = "\ue8ab",
ColorBrush = ParseColor("#107C10")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "diff",
Title = "두 텍스트 비교 (Diff)",
Description = "클립보드의 두 텍스트를 비교하여 차이점을 한눈에 보여줍니다. 코드 변경 사항 확인, 문서 버전 비교 등에 유용합니다.",
Example = "diff",
Symbol = "\ue8fd",
ColorBrush = ParseColor("#6B2C91")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "encode",
Title = "인코딩 · 디코딩 변환",
Description = "Base64, URL, HTML, Unicode 등 다양한 형식으로 텍스트를 인코딩하거나 디코딩합니다. 개발자에게 특히 유용한 변환 도구입니다.",
Example = "encode base64 hello\nencode url 한글 테스트",
Symbol = "\ue943",
ColorBrush = ParseColor("#323130")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "routine",
Title = "반복 작업 루틴 자동화",
Description = "자주 하는 작업 묶음을 루틴으로 등록해 두면 한 번의 명령으로 여러 앱을 동시에 열거나 작업 환경을 구성할 수 있습니다. 출근·퇴근 루틴 등을 만들어 보세요.",
Example = "routine start 출근\nroutine list",
Symbol = "\ue8f5",
ColorBrush = ParseColor("#BE185D")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "stats",
Title = "텍스트 통계 (글자수·단어수·줄수)",
Description = "클립보드에 복사된 텍스트의 글자 수, 단어 수, 줄 수를 즉시 계산합니다. 보고서 분량 체크, SNS 글자 수 제한 확인 등에 활용하세요.",
Example = "stats",
Symbol = "\ue9d9",
ColorBrush = ParseColor("#44546A")
},
new HelpItemModel
{
Category = "업무 보조",
Command = "json",
Title = "JSON 파싱 · 정리 · 미리보기",
Description = "클립보드에 복사된 JSON을 자동으로 파싱하고 읽기 좋은 형태로 정리합니다. 들여쓰기, 키 하이라이트, 복사 기능을 제공합니다.",
Example = "json {\"key\":\"value\"}",
Symbol = "\ue8a5",
ColorBrush = ParseColor("#4B5EFC")
}
};
_shortcutItems = BuildShortcutItems(_globalHotkey);
_prefixItems = _allItems.ToList();
SubtitleText.Text = $"총 {totalCount}개 명령어 · 단축키 {_shortcutItems.Count}개 · 예약어 {_prefixItems.Count}개";
BuildTopMenu();
SwitchTopMenu(TopMenu.Overview);
base.KeyDown += OnKeyDown;
}
private static List<HelpItemModel> BuildShortcutItems(string globalHotkey = "Alt+Space")
{
List<HelpItemModel> list = new List<HelpItemModel>();
string key = globalHotkey.Replace("+", " + ");
list.Add(MakeShortcut("전역", key, "AX Commander 열기/닫기", "어느 창에서든 눌러 AX Commander를 즉시 호출하거나 닫습니다. 설정 일반에서 원하는 키 조합으로 변경할 수 있습니다.", "\ue765", "#4B5EFC"));
list.Add(MakeShortcut("전역", "PrintScreen", "화면 캡처 즉시 실행", "AX Commander를 열지 않고 곧바로 캡처를 시작합니다. 설정 캡처 탭에서 '글로벌 단축키 활성화'를 켜야 동작합니다.", "\ue722", "#BE185D"));
list.Add(MakeShortcut("AX Commander 탐색", "Escape", "창 닫기 / 이전 단계로", "액션 모드(→ 로 진입)에 있을 때는 일반 검색 화면으로 돌아갑니다. 일반 화면이면 AX Commander를 숨깁니다.", "\ue711", "#999999"));
list.Add(MakeShortcut("AX Commander 탐색", "Enter", "선택 항목 실행", "파일·앱이면 열기, URL이면 브라우저 열기, 시스템 명령이면 즉시 실행, 계산기 결과면 클립보드에 복사합니다.", "\ue768", "#107C10"));
list.Add(MakeShortcut("AX Commander 탐색", "Shift + Enter", "대형 텍스트(Large Type) 표시 / 클립보드 병합 실행", "선택된 텍스트·검색어를 화면 전체에 크게 띄웁니다. 클립보드 병합 항목이 있을 때는 선택한 항목들을 줄바꿈으로 합쳐 클립보드에 복사합니다.", "\ue8c1", "#8764B8"));
list.Add(MakeShortcut("AX Commander 탐색", "↑ / ↓", "결과 목록 위/아래 이동", "목록 끝에서 계속 누르면 처음/끝으로 순환합니다.", "\ue74a", "#0078D4"));
list.Add(MakeShortcut("AX Commander 탐색", "PageUp / PageDown", "목록 5칸 빠른 이동", "한 번에 5항목씩 건너뜁니다. 빠른 목록 탐색에 유용합니다.", "\ue74a", "#0078D4"));
list.Add(MakeShortcut("AX Commander 탐색", "Home / End", "목록 처음 / 마지막 항목으로 점프", "입력창 커서가 맨 앞(또는 입력이 없을 때)이면 첫 항목으로, 맨 끝이면 마지막 항목으로 선택이 이동합니다.", "\ue74a", "#0078D4"));
list.Add(MakeShortcut("AX Commander 탐색", "→ (오른쪽 화살표)", "액션 모드 진입", "파일·앱 항목을 선택한 상태에서 → 를 누르면 경로 복사, 탐색기 열기, 관리자 실행, 터미널, 속성, 이름 변경, 삭제 메뉴가 나타납니다.", "\ue76c", "#44546A"));
list.Add(MakeShortcut("AX Commander 탐색", "Tab", "선택 항목 제목으로 자동완성", "현재 선택된 항목의 이름을 입력창에 채웁니다. 이후 계속 타이핑하거나 Enter로 실행합니다.", "\ue748", "#006EAF"));
list.Add(MakeShortcut("AX Commander 탐색", "Shift + ↑/↓", "클립보드 병합 선택", "클립보드 히스토리(# 모드) 에서 여러 항목을 이동하면서 선택/해제합니다. Shift+Enter로 선택한 항목들을 한 번에 붙여넣을 수 있습니다.", "\ue8c1", "#B7791F"));
list.Add(MakeShortcut("런처 기능", "F1", "도움말 창 열기", "이 화면을 직접 엽니다. 'help' 를 입력하는 것과 동일합니다.", "\ue897", "#6B7280"));
list.Add(MakeShortcut("런처 기능", "F2", "선택 파일 이름 변경", "파일·폴더 항목을 선택한 상태에서 누르면 rename [경로] 형태로 입력창에 채워지고 이름 변경 핸들러가 실행됩니다.", "\ue70f", "#6B2C91"));
list.Add(MakeShortcut("런처 기능", "F5", "파일 인덱스 즉시 재구축", "백그라운드에서 파일·앱 인덱싱을 다시 실행합니다. 새 파일을 추가했거나 목록이 오래됐을 때 사용합니다.", "\ue72c", "#059669"));
list.Add(MakeShortcut("런처 기능", "Delete", "최근 실행 목록에서 항목 제거", "recent 목록에 있는 항목을 제거합니다. 확인 다이얼로그가 표시되며 OK를 눌러야 실제로 제거됩니다.", "\ue74d", "#DC2626"));
list.Add(MakeShortcut("런처 기능", "Ctrl + ,", "설정 창 열기", "AX Copilot 설정 창을 엽니다. 런처가 자동으로 숨겨집니다.", "\ue713", "#44546A"));
list.Add(MakeShortcut("런처 기능", "Ctrl + L", "입력창 전체 초기화", "현재 입력된 검색어·예약어를 모두 지우고 커서를 빈 입력창으로 돌립니다.", "\ue894", "#4B5EFC"));
list.Add(MakeShortcut("런처 기능", "Ctrl + C", "선택 항목 파일 이름 복사", "파일·앱 항목이 선택된 경우 확장자를 제외한 파일 이름을 클립보드에 복사하고 토스트로 알립니다.", "\ue8c8", "#8764B8"));
list.Add(MakeShortcut("런처 기능", "Ctrl + Shift + C", "선택 항목 전체 경로 복사", "선택된 파일·폴더의 절대 경로(예: C:\\Users\\...)를 클립보드에 복사합니다.", "\ue8c8", "#C55A11"));
list.Add(MakeShortcut("런처 기능", "Ctrl + Shift + E", "파일 탐색기에서 선택 항목 열기", "Windows 탐색기가 열리고 해당 파일·폴더가 하이라이트 선택된 상태로 표시됩니다.", "\ue838", "#107C10"));
list.Add(MakeShortcut("런처 기능", "Ctrl + Enter", "관리자(UAC) 권한으로 실행", "선택된 파일·앱을 UAC 권한 상승 후 실행합니다. 설치 프로그램이나 시스템 설정 앱에 유용합니다.", "\ue7ef", "#C50F1F"));
list.Add(MakeShortcut("런처 기능", "Alt + Enter", "파일 속성 대화 상자 열기", "Windows의 '파일 속성' 창(크기·날짜·권한 등)을 엽니다.", "\ue946", "#6B2C91"));
list.Add(MakeShortcut("런처 기능", "Ctrl + T", "선택 항목 위치에서 터미널 열기", "선택된 파일이면 해당 폴더에서, 폴더이면 그 경로에서 Windows Terminal(wt.exe)이 열립니다. wt가 없으면 cmd로 대체됩니다.", "\ue756", "#323130"));
list.Add(MakeShortcut("런처 기능", "Ctrl + P", "즐겨찾기 즉시 추가 / 제거 (핀)", "파일·폴더 항목을 선택한 상태에서 누르면 favorites.json 에 추가하거나 이미 있으면 제거합니다. 토스트로 결과를 알립니다.", "\ue734", "#D97706"));
list.Add(MakeShortcut("런처 기능", "Ctrl + B", "즐겨찾기 목록 보기 / 닫기 토글", "입력창이 'fav' 이면 초기화하고, 아니면 'fav' 를 입력해 즐겨찾기 목록을 표시합니다.", "\ue735", "#D97706"));
list.Add(MakeShortcut("런처 기능", "Ctrl + R", "최근 실행 목록 보기 / 닫기 토글", "'recent' 를 입력해 최근 실행 항목을 표시합니다.", "\ue81c", "#0078D4"));
list.Add(MakeShortcut("런처 기능", "Ctrl + H", "클립보드 히스토리 목록 열기", "'#' 를 입력해 클립보드에 저장된 최근 복사 항목 목록을 표시합니다.", "\ue77f", "#8B2FC9"));
list.Add(MakeShortcut("런처 기능", "Ctrl + D", "다운로드 폴더 바로가기", "사용자 홈의 Downloads 폴더 경로를 입력창에 채워 탐색기로 열 수 있게 합니다.", "\ue8b7", "#107C10"));
list.Add(MakeShortcut("런처 기능", "Ctrl + F", "파일 검색 모드로 전환", "입력창을 초기화하고 포커스를 이동합니다. 이후 파일명을 바로 타이핑해 검색할 수 있습니다.", "\ue71e", "#4B5EFC"));
list.Add(MakeShortcut("런처 기능", "Ctrl + W", "런처 창 즉시 닫기", "현재 입력 내용에 관계없이 런처를 즉시 숨깁니다.", "\ue711", "#9999BB"));
list.Add(MakeShortcut("런처 기능", "Ctrl + K", "단축키 참조 모달 창 열기", "모든 단축키와 설명을 보여주는 별도 모달 창이 열립니다. Esc 또는 닫기 버튼으로 닫습니다.", "\ue8fd", "#4B5EFC"));
list.Add(MakeShortcut("런처 기능", "Ctrl + 1 ~ 9", "N번째 결과 항목 바로 실행", "목록에 번호 배지(1~9)가 표시된 항목을 해당 숫자 키로 즉시 실행합니다. 마우스 없이 빠른 실행에 유용합니다.", "\ue8c4", "#107C10"));
list.Add(MakeShortcut("기타 창", "← / →", "헬프 창 카테고리 이동", "이 도움말 창에서 하위 카테고리 탭을 왼쪽/오른쪽으로 이동합니다.", "\ue76b", "#4455AA"));
list.Add(MakeShortcut("기타 창", "1 / 2 / 3", "헬프 창 상단 메뉴 전환", "이 도움말 창에서 개요(1), 단축키 현황(2), 예약어 현황(3)을 키보드로 전환합니다.", "\ue8bd", "#4455AA"));
list.Add(MakeShortcut("기타 창", "방향키 (캡처 중)", "영역 선택 경계 1px 미세 조정", "화면 캡처의 영역 선택 모드에서 선택 영역 경계를 1픽셀씩 정밀 조정합니다.", "\ue745", "#BE185D"));
list.Add(MakeShortcut("기타 창", "Shift + 방향키 (캡처 중)", "영역 선택 경계 10px 이동", "화면 캡처의 영역 선택 모드에서 선택 영역 경계를 10픽셀씩 빠르게 이동합니다.", "\ue745", "#BE185D"));
return list;
}
private static SolidColorBrush ParseColor(string hex)
{
try
{
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(hex));
}
catch
{
return new SolidColorBrush(Colors.Gray);
}
}
private static HelpItemModel MakeShortcut(string cat, string key, string title, string desc, string symbol, string color)
{
return new HelpItemModel
{
Category = cat,
Command = key,
Title = title,
Description = desc,
Symbol = symbol,
ColorBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(color))
};
}
private void BuildTopMenu()
{
TopMenuBar.Children.Clear();
(TopMenu, string, string)[] topMenus = TopMenus;
for (int i = 0; i < topMenus.Length; i++)
{
(TopMenu, string, string) tuple = topMenus[i];
TopMenu item = tuple.Item1;
string item2 = tuple.Item2;
string item3 = tuple.Item3;
TopMenu k = item;
StackPanel stackPanel = new StackPanel
{
Orientation = Orientation.Horizontal
};
stackPanel.Children.Add(new TextBlock
{
Text = item3,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 14.0,
Foreground = ThemeAccent,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 6.0, 0.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = item2,
FontSize = 12.0,
VerticalAlignment = VerticalAlignment.Center
});
Button button = new Button
{
Content = stackPanel,
FontWeight = FontWeights.SemiBold,
Padding = new Thickness(16.0, 8.0, 16.0, 8.0),
Margin = new Thickness(4.0, 0.0, 4.0, 0.0),
Cursor = Cursors.Hand,
Background = Brushes.Transparent,
Foreground = ThemeSecondary,
BorderThickness = new Thickness(0.0, 0.0, 0.0, 2.0),
BorderBrush = Brushes.Transparent,
Tag = k
};
button.Click += delegate
{
SwitchTopMenu(k);
};
TopMenuBar.Children.Add(button);
}
}
private void SwitchTopMenu(TopMenu menu)
{
_currentTopMenu = menu;
foreach (object child in TopMenuBar.Children)
{
if (!(child is Button { Tag: var tag } button))
{
continue;
}
bool flag = tag is TopMenu topMenu && topMenu == menu;
button.BorderBrush = (flag ? ThemeAccent : Brushes.Transparent);
button.Foreground = (flag ? ThemePrimary : ThemeSecondary);
if (!(button.Content is StackPanel stackPanel))
{
continue;
}
foreach (object child2 in stackPanel.Children)
{
if (child2 is TextBlock textBlock && textBlock.FontFamily.Source != "Segoe MDL2 Assets")
{
textBlock.Foreground = button.Foreground;
}
}
}
switch (menu)
{
case TopMenu.Overview:
BuildCategoryBarFor(_overviewItems);
break;
case TopMenu.Shortcuts:
BuildCategoryBarFor(_shortcutItems);
break;
case TopMenu.Prefixes:
BuildCategoryBarFor(_prefixItems);
break;
}
}
private void BuildCategoryBarFor(List<HelpItemModel> sourceItems)
{
HashSet<string> hashSet = new HashSet<string>();
_categories = new List<string> { "전체" };
if (_currentTopMenu == TopMenu.Prefixes)
{
_categories.Add("⭐ 인기");
}
foreach (HelpItemModel sourceItem in sourceItems)
{
if (hashSet.Add(sourceItem.Category))
{
_categories.Add(sourceItem.Category);
}
}
BuildCategoryBar();
NavigateToPage(0);
}
private void BuildCategoryBar()
{
CategoryBar.Children.Clear();
for (int i = 0; i < _categories.Count; i++)
{
string content = _categories[i];
int idx = i;
Button button = new Button
{
Content = content,
FontSize = 10.5,
FontWeight = FontWeights.SemiBold,
Padding = new Thickness(9.0, 4.0, 9.0, 4.0),
Margin = new Thickness(0.0, 0.0, 3.0, 0.0),
Cursor = Cursors.Hand,
Background = Brushes.Transparent,
Foreground = ThemeSecondary,
BorderThickness = new Thickness(0.0),
Tag = idx
};
button.Click += delegate
{
NavigateToPage(idx);
};
CategoryBar.Children.Add(button);
}
}
private List<HelpItemModel> GetCurrentSourceItems()
{
TopMenu currentTopMenu = _currentTopMenu;
if (1 == 0)
{
}
List<HelpItemModel> result = currentTopMenu switch
{
TopMenu.Overview => _overviewItems,
TopMenu.Shortcuts => _shortcutItems,
TopMenu.Prefixes => _prefixItems,
_ => _overviewItems,
};
if (1 == 0)
{
}
return result;
}
private void NavigateToPage(int pageIndex)
{
if (_categories.Count == 0)
{
return;
}
_currentPage = Math.Clamp(pageIndex, 0, _categories.Count - 1);
List<HelpItemModel> currentSourceItems = GetCurrentSourceItems();
string cat = _categories[_currentPage];
List<HelpItemModel> list;
if (cat == "전체")
{
list = currentSourceItems;
}
else if (cat == "⭐ 인기")
{
HashSet<string> popularCmds = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "파일/폴더", "?", "#", "!", "clip", "pipe", "diff", "win" };
list = currentSourceItems.Where((HelpItemModel i) => popularCmds.Contains(i.Command) || i.Command.StartsWith("?") || i.Title.Contains("검색") || i.Title.Contains("클립보드") || (i.Title.Contains("파일") && i.Category != "키보드")).ToList();
}
else
{
list = currentSourceItems.Where((HelpItemModel i) => i.Category == cat).ToList();
}
ItemsHost.ItemsSource = list;
for (int num = 0; num < CategoryBar.Children.Count; num++)
{
if (CategoryBar.Children[num] is Button button)
{
if (num == _currentPage)
{
button.Background = ThemeAccent;
button.Foreground = Brushes.White;
}
else
{
button.Background = Brushes.Transparent;
button.Foreground = ThemeSecondary;
}
}
}
PageIndicator.Text = $"{cat} ({list.Count}개)";
PrevBtn.Visibility = ((_currentPage <= 0) ? Visibility.Hidden : Visibility.Visible);
NextBtn.Visibility = ((_currentPage >= _categories.Count - 1) ? Visibility.Hidden : Visibility.Visible);
}
private void OnKeyDown(object sender, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Invalid comparison between Unknown and I4
//IL_0020: Unknown result type (might be due to invalid IL or missing references)
//IL_0023: Invalid comparison between Unknown and I4
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0012: Invalid comparison between Unknown and I4
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
//IL_003c: Expected I4, but got Unknown
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Invalid comparison between Unknown and I4
Key key = e.Key;
Key val = key;
if ((int)val <= 23)
{
if ((int)val != 13)
{
if ((int)val == 23)
{
if (_currentPage > 0)
{
NavigateToPage(_currentPage - 1);
}
e.Handled = true;
}
}
else
{
Close();
}
}
else if ((int)val != 25)
{
switch (val - 35)
{
case 0:
SwitchTopMenu(TopMenu.Overview);
e.Handled = true;
break;
case 1:
SwitchTopMenu(TopMenu.Shortcuts);
e.Handled = true;
break;
case 2:
SwitchTopMenu(TopMenu.Prefixes);
e.Handled = true;
break;
}
}
else
{
if (_currentPage < _categories.Count - 1)
{
NavigateToPage(_currentPage + 1);
}
e.Handled = true;
}
}
private void Prev_Click(object sender, RoutedEventArgs e)
{
NavigateToPage(_currentPage - 1);
}
private void Next_Click(object sender, RoutedEventArgs e)
{
NavigateToPage(_currentPage + 1);
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void SearchBox_TextChanged(object sender, TextChangedEventArgs e)
{
string query = SearchBox.Text.Trim();
if (string.IsNullOrEmpty(query))
{
NavigateToPage(_currentPage);
return;
}
List<HelpItemModel> currentSourceItems = GetCurrentSourceItems();
List<HelpItemModel> list = currentSourceItems.Where((HelpItemModel i) => i.Title.Contains(query, StringComparison.OrdinalIgnoreCase) || i.Command.Contains(query, StringComparison.OrdinalIgnoreCase) || i.Description.Contains(query, StringComparison.OrdinalIgnoreCase) || i.Category.Contains(query, StringComparison.OrdinalIgnoreCase)).ToList();
ItemsHost.ItemsSource = list;
PageIndicator.Text = $"검색: \"{query}\" ({list.Count}개)";
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
}
private void Window_KeyDown(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
if ((int)e.Key == 13)
{
Close();
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/helpdetailwindow.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:
((HelpDetailWindow)target).MouseDown += Window_MouseDown;
((HelpDetailWindow)target).KeyDown += Window_KeyDown;
break;
case 2:
SubtitleText = (TextBlock)target;
break;
case 3:
((Button)target).Click += Close_Click;
break;
case 4:
TopMenuBar = (StackPanel)target;
break;
case 5:
SearchBox = (TextBox)target;
SearchBox.TextChanged += SearchBox_TextChanged;
break;
case 6:
CategoryBar = (WrapPanel)target;
break;
case 7:
ItemsHost = (ItemsControl)target;
break;
case 8:
PrevBtn = (Button)target;
PrevBtn.Click += Prev_Click;
break;
case 9:
PageIndicator = (TextBlock)target;
break;
case 10:
NextBtn = (Button)target;
NextBtn.Click += Next_Click;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,22 @@
using System.Windows.Media;
namespace AxCopilot.Views;
public class HelpItemModel
{
public string Category { get; init; } = "";
public string Command { get; init; } = "";
public string Title { get; init; } = "";
public string Description { get; init; } = "";
public string Example { get; init; } = "";
public string Symbol { get; init; } = "";
public SolidColorBrush ColorBrush { get; init; } = new SolidColorBrush(Colors.Gray);
public bool HasExample => !string.IsNullOrEmpty(Example);
}

View File

@@ -0,0 +1,228 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
namespace AxCopilot.Views;
internal sealed class InputDialog : Window
{
private readonly TextBox _textBox;
public string ResponseText => _textBox.Text;
public InputDialog(string title, string prompt, string defaultValue = "", string placeholder = "")
{
base.WindowStartupLocation = WindowStartupLocation.CenterOwner;
base.ResizeMode = ResizeMode.NoResize;
base.WindowStyle = WindowStyle.None;
base.AllowsTransparency = true;
base.Background = Brushes.Transparent;
base.Width = 400.0;
base.SizeToContent = SizeToContent.Height;
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush borderBrush = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Brush foreground = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush accentBrush = (Application.Current.TryFindResource("AccentColor") as Brush) ?? Brushes.CornflowerBlue;
Brush background2 = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 43, 62));
Border border = new Border
{
Background = background,
BorderBrush = borderBrush,
BorderThickness = new Thickness(1.0),
CornerRadius = new CornerRadius(14.0),
Margin = new Thickness(16.0),
Effect = new DropShadowEffect
{
BlurRadius = 24.0,
ShadowDepth = 6.0,
Opacity = 0.35,
Color = Colors.Black,
Direction = 270.0
}
};
StackPanel stackPanel = new StackPanel
{
Margin = new Thickness(24.0, 20.0, 24.0, 20.0)
};
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 16.0)
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\ue8ac",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 16.0,
Foreground = accentBrush,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 10.0, 0.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = title,
FontSize = 15.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center
});
stackPanel.Children.Add(stackPanel2);
stackPanel.Children.Add(new TextBlock
{
Text = prompt,
FontSize = 12.5,
Foreground = foreground2,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
_textBox = new TextBox
{
Text = defaultValue,
FontSize = 13.0,
Padding = new Thickness(14.0, 8.0, 14.0, 8.0),
Foreground = foreground,
Background = Brushes.Transparent,
CaretBrush = accentBrush,
BorderThickness = new Thickness(0.0),
BorderBrush = Brushes.Transparent
};
_textBox.KeyDown += delegate(object _, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Invalid comparison between Unknown and I4
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_002c: Invalid comparison between Unknown and I4
if ((int)e.Key == 6)
{
base.DialogResult = true;
Close();
}
if ((int)e.Key == 13)
{
base.DialogResult = false;
Close();
}
};
TextBlock placeholderBlock = new TextBlock
{
Text = placeholder,
FontSize = 13.0,
Foreground = foreground2,
Opacity = 0.5,
IsHitTestVisible = false,
VerticalAlignment = VerticalAlignment.Center,
Padding = new Thickness(14.0, 8.0, 14.0, 8.0),
Visibility = ((!string.IsNullOrEmpty(defaultValue) || string.IsNullOrEmpty(placeholder)) ? Visibility.Collapsed : Visibility.Visible)
};
_textBox.TextChanged += delegate
{
placeholderBlock.Visibility = ((!string.IsNullOrEmpty(_textBox.Text)) ? Visibility.Collapsed : Visibility.Visible);
};
Grid child = new Grid
{
Children =
{
(UIElement)_textBox,
(UIElement)placeholderBlock
}
};
Border inputBorder = new Border
{
CornerRadius = new CornerRadius(10.0),
BorderBrush = borderBrush,
BorderThickness = new Thickness(1.0),
Background = background2,
Child = child
};
_textBox.GotFocus += delegate
{
inputBorder.BorderBrush = accentBrush;
};
_textBox.LostFocus += delegate
{
inputBorder.BorderBrush = borderBrush;
};
stackPanel.Children.Add(inputBorder);
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 18.0, 0.0, 0.0)
};
Button button = CreateButton("취소", Brushes.Transparent, foreground2, borderBrush);
button.Click += delegate
{
base.DialogResult = false;
Close();
};
stackPanel3.Children.Add(button);
Button button2 = CreateButton("확인", accentBrush, Brushes.White, null);
button2.Click += delegate
{
base.DialogResult = true;
Close();
};
stackPanel3.Children.Add(button2);
stackPanel.Children.Add(stackPanel3);
border.Child = stackPanel;
base.Content = border;
stackPanel2.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs e)
{
if (e.ClickCount == 1)
{
DragMove();
}
};
base.Loaded += delegate
{
_textBox.Focus();
_textBox.SelectAll();
};
}
private static Button CreateButton(string text, Brush background, Brush foreground, Brush? borderBrush)
{
Button button = new Button
{
Cursor = Cursors.Hand,
Margin = new Thickness(0.0, 0.0, 0.0, 0.0)
};
if (text == "취소")
{
button.Margin = new Thickness(0.0, 0.0, 8.0, 0.0);
}
ControlTemplate controlTemplate = new ControlTemplate(typeof(Button));
FrameworkElementFactory frameworkElementFactory = new FrameworkElementFactory(typeof(Border));
frameworkElementFactory.SetValue(Border.BackgroundProperty, background);
frameworkElementFactory.SetValue(Border.CornerRadiusProperty, new CornerRadius(8.0));
frameworkElementFactory.SetValue(Border.PaddingProperty, new Thickness(20.0, 8.0, 20.0, 8.0));
frameworkElementFactory.Name = "Bd";
if (borderBrush != null)
{
frameworkElementFactory.SetValue(Border.BorderBrushProperty, borderBrush);
frameworkElementFactory.SetValue(Border.BorderThicknessProperty, new Thickness(1.0));
}
FrameworkElementFactory frameworkElementFactory2 = new FrameworkElementFactory(typeof(ContentPresenter));
frameworkElementFactory2.SetValue(FrameworkElement.HorizontalAlignmentProperty, HorizontalAlignment.Center);
frameworkElementFactory2.SetValue(FrameworkElement.VerticalAlignmentProperty, VerticalAlignment.Center);
frameworkElementFactory.AppendChild(frameworkElementFactory2);
controlTemplate.VisualTree = frameworkElementFactory;
Trigger trigger = new Trigger
{
Property = UIElement.IsMouseOverProperty,
Value = true
};
trigger.Setters.Add(new Setter(UIElement.OpacityProperty, 0.85));
controlTemplate.Triggers.Add(trigger);
button.Template = controlTemplate;
button.Content = new TextBlock
{
Text = text,
FontSize = 13.0,
Foreground = foreground
};
return button;
}
}

View File

@@ -0,0 +1,102 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
namespace AxCopilot.Views;
public class LargeTypeWindow : Window, IComponentConnector
{
private readonly string _text;
internal Border Overlay;
internal TextBlock LargeText;
private bool _contentLoaded;
public LargeTypeWindow(string text)
{
_text = text;
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
LargeText.Text = _text;
TextBlock largeText = LargeText;
int length = _text.Length;
if (1 == 0)
{
}
int num = ((length <= 60) ? ((length <= 10) ? 120 : ((length > 30) ? 72 : 96)) : ((length > 120) ? 38 : 52));
if (1 == 0)
{
}
largeText.FontSize = num;
Focus();
}
private void Window_KeyDown(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
if ((int)e.Key == 13)
{
Close();
}
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
Close();
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/largetypewindow.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:
((LargeTypeWindow)target).KeyDown += Window_KeyDown;
((LargeTypeWindow)target).MouseDown += Window_MouseDown;
((LargeTypeWindow)target).Loaded += Window_Loaded;
break;
case 2:
Overlay = (Border)target;
break;
case 3:
((Button)target).Click += Close_Click;
break;
case 4:
LargeText = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,499 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shapes;
namespace AxCopilot.Views;
internal sealed class ModelRegistrationDialog : Window
{
private readonly TextBox _aliasBox;
private readonly TextBox _modelBox;
private readonly TextBox _endpointBox;
private readonly TextBox _apiKeyBox;
private readonly ComboBox _authTypeBox;
private readonly StackPanel _cp4dPanel;
private readonly TextBox _cp4dUrlBox;
private readonly TextBox _cp4dUsernameBox;
private readonly PasswordBox _cp4dPasswordBox;
public string ModelAlias => _aliasBox.Text.Trim();
public string ModelName => _modelBox.Text.Trim();
public string Endpoint => _endpointBox.Text.Trim();
public string ApiKey => _apiKeyBox.Text.Trim();
public string AuthType => (_authTypeBox.SelectedItem as ComboBoxItem)?.Tag?.ToString() ?? "bearer";
public string Cp4dUrl => _cp4dUrlBox.Text.Trim();
public string Cp4dUsername => _cp4dUsernameBox.Text.Trim();
public string Cp4dPassword => _cp4dPasswordBox.Password.Trim();
public ModelRegistrationDialog(string service, string existingAlias = "", string existingModel = "", string existingEndpoint = "", string existingApiKey = "", string existingAuthType = "bearer", string existingCp4dUrl = "", string existingCp4dUsername = "", string existingCp4dPassword = "")
{
bool flag = !string.IsNullOrEmpty(existingAlias);
base.Title = (flag ? "모델 편집" : "모델 추가");
base.Width = 420.0;
base.SizeToContent = SizeToContent.Height;
base.WindowStartupLocation = WindowStartupLocation.CenterOwner;
base.ResizeMode = ResizeMode.NoResize;
base.WindowStyle = WindowStyle.None;
base.AllowsTransparency = true;
base.Background = Brushes.Transparent;
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush foreground = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush brush = (Application.Current.TryFindResource("AccentColor") as Brush) ?? Brushes.Blue;
Brush background2 = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 43, 64));
Brush brush2 = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(16.0),
BorderBrush = brush2,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(28.0, 24.0, 28.0, 24.0),
Effect = new DropShadowEffect
{
BlurRadius = 24.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = Colors.Black
}
};
StackPanel stackPanel = new StackPanel();
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 20.0)
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\uea86",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 18.0,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 10.0, 0.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = (flag ? "모델 편집" : "새 모델 등록"),
FontSize = 17.0,
FontWeight = FontWeights.Bold,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center
});
stackPanel.Children.Add(stackPanel2);
string text = ((service == "vllm") ? "vLLM" : "Ollama");
Border border2 = new Border
{
Background = brush,
CornerRadius = new CornerRadius(6.0),
Padding = new Thickness(10.0, 3.0, 10.0, 3.0),
Margin = new Thickness(0.0, 0.0, 0.0, 16.0),
HorizontalAlignment = HorizontalAlignment.Left,
Opacity = 0.85
};
border2.Child = new TextBlock
{
Text = text + " 서비스",
FontSize = 11.0,
FontWeight = FontWeights.SemiBold,
Foreground = Brushes.White
};
stackPanel.Children.Add(border2);
stackPanel.Children.Add(new TextBlock
{
Text = "별칭 (표시 이름)",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = "채팅 화면에서 표시될 이름입니다. 예: 코드 리뷰 전용, 일반 대화",
FontSize = 11.0,
Foreground = foreground2,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
_aliasBox = new TextBox
{
Text = existingAlias,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
Border element = new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _aliasBox
};
stackPanel.Children.Add(element);
stackPanel.Children.Add(new Rectangle
{
Height = 1.0,
Fill = brush2,
Margin = new Thickness(0.0, 16.0, 0.0, 16.0),
Opacity = 0.5
});
stackPanel.Children.Add(new TextBlock
{
Text = "실제 모델명",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = "서버에 배포된 실제 모델 ID (예: llama3:8b, qwen2:7b)",
FontSize = 11.0,
Foreground = foreground2,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
_modelBox = new TextBox
{
Text = existingModel,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
Border element2 = new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _modelBox
};
stackPanel.Children.Add(element2);
stackPanel.Children.Add(new Rectangle
{
Height = 1.0,
Fill = brush2,
Margin = new Thickness(0.0, 16.0, 0.0, 16.0),
Opacity = 0.5
});
stackPanel.Children.Add(new TextBlock
{
Text = "서버 엔드포인트 (선택)",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = "이 모델 전용 서버 주소. 비워두면 기본 엔드포인트를 사용합니다.",
FontSize = 11.0,
Foreground = foreground2,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
_endpointBox = new TextBox
{
Text = existingEndpoint,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
stackPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _endpointBox
});
stackPanel.Children.Add(new TextBlock
{
Text = "인증 방식",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 10.0, 0.0, 6.0)
});
_authTypeBox = new ComboBox
{
FontSize = 13.0,
Padding = new Thickness(8.0, 6.0, 8.0, 6.0),
Foreground = foreground,
Background = background2,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
ComboBoxItem comboBoxItem = new ComboBoxItem
{
Content = "Bearer 토큰 (API 키)",
Tag = "bearer"
};
ComboBoxItem comboBoxItem2 = new ComboBoxItem
{
Content = "CP4D (IBM Cloud Pak for Data)",
Tag = "cp4d"
};
_authTypeBox.Items.Add(comboBoxItem);
_authTypeBox.Items.Add(comboBoxItem2);
_authTypeBox.SelectedItem = ((existingAuthType == "cp4d") ? comboBoxItem2 : comboBoxItem);
stackPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _authTypeBox
});
StackPanel apiKeyPanel = new StackPanel();
apiKeyPanel.Children.Add(new TextBlock
{
Text = "API 키 (선택)",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 10.0, 0.0, 6.0)
});
_apiKeyBox = new TextBox
{
Text = existingApiKey,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
apiKeyPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _apiKeyBox
});
stackPanel.Children.Add(apiKeyPanel);
_cp4dPanel = new StackPanel
{
Visibility = ((!(existingAuthType == "cp4d")) ? Visibility.Collapsed : Visibility.Visible)
};
_cp4dPanel.Children.Add(new TextBlock
{
Text = "CP4D 서버 URL",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 10.0, 0.0, 6.0)
});
_cp4dPanel.Children.Add(new TextBlock
{
Text = "예: https://cpd-host.example.com",
FontSize = 11.0,
Foreground = foreground2,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
_cp4dUrlBox = new TextBox
{
Text = existingCp4dUrl,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
_cp4dPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _cp4dUrlBox
});
_cp4dPanel.Children.Add(new TextBlock
{
Text = "사용자 이름",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 10.0, 0.0, 6.0)
});
_cp4dUsernameBox = new TextBox
{
Text = existingCp4dUsername,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
_cp4dPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _cp4dUsernameBox
});
_cp4dPanel.Children.Add(new TextBlock
{
Text = "비밀번호 / API 키",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 10.0, 0.0, 6.0)
});
_cp4dPasswordBox = new PasswordBox
{
Password = existingCp4dPassword,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
_cp4dPanel.Children.Add(new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _cp4dPasswordBox
});
stackPanel.Children.Add(_cp4dPanel);
_authTypeBox.SelectionChanged += delegate
{
bool flag2 = AuthType == "cp4d";
_cp4dPanel.Visibility = ((!flag2) ? Visibility.Collapsed : Visibility.Visible);
apiKeyPanel.Visibility = (flag2 ? Visibility.Collapsed : Visibility.Visible);
};
apiKeyPanel.Visibility = ((existingAuthType == "cp4d") ? Visibility.Collapsed : Visibility.Visible);
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 12.0, 0.0, 0.0)
};
stackPanel3.Children.Add(new TextBlock
{
Text = "\ue72e",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 11.0,
Foreground = new SolidColorBrush(Color.FromRgb(56, 161, 105)),
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 6.0, 0.0)
});
stackPanel3.Children.Add(new TextBlock
{
Text = "모델명은 AES-256으로 암호화되어 설정 파일에 저장됩니다",
FontSize = 10.5,
Foreground = foreground2,
VerticalAlignment = VerticalAlignment.Center
});
stackPanel.Children.Add(stackPanel3);
StackPanel stackPanel4 = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 24.0, 0.0, 0.0)
};
Button button = new Button
{
Content = "취소",
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Margin = new Thickness(0.0, 0.0, 10.0, 0.0),
Background = Brushes.Transparent,
Foreground = foreground2,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0),
Cursor = Cursors.Hand,
FontSize = 13.0
};
button.Click += delegate
{
base.DialogResult = false;
Close();
};
stackPanel4.Children.Add(button);
Button button2 = new Button
{
Content = (flag ? "저장" : "등록"),
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Background = brush,
Foreground = Brushes.White,
BorderThickness = new Thickness(0.0),
Cursor = Cursors.Hand,
FontSize = 13.0,
FontWeight = FontWeights.SemiBold
};
button2.Click += delegate
{
if (string.IsNullOrWhiteSpace(_aliasBox.Text))
{
CustomMessageBox.Show("별칭을 입력하세요.", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_aliasBox.Focus();
}
else if (string.IsNullOrWhiteSpace(_modelBox.Text))
{
CustomMessageBox.Show("모델명을 입력하세요.", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_modelBox.Focus();
}
else
{
base.DialogResult = true;
Close();
}
};
stackPanel4.Children.Add(button2);
stackPanel.Children.Add(stackPanel4);
border.Child = stackPanel;
base.Content = border;
base.KeyDown += delegate(object _, KeyEventArgs ke)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)ke.Key == 13)
{
base.DialogResult = false;
Close();
}
};
base.Loaded += delegate
{
_aliasBox.Focus();
_aliasBox.SelectAll();
};
border.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs me)
{
if (me.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
};
}
}

View File

@@ -0,0 +1,64 @@
using System.Drawing;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
namespace AxCopilot.Views;
internal sealed class ModernColorTable : ProfessionalColorTable
{
private static System.Drawing.Color Bg => TC("LauncherBackground", System.Drawing.Color.FromArgb(250, 250, 252));
private static System.Drawing.Color Hover => TC("ItemHoverBackground", System.Drawing.Color.FromArgb(234, 234, 247));
private static System.Drawing.Color Border => TC("BorderColor", System.Drawing.Color.FromArgb(210, 210, 232));
private static System.Drawing.Color Sep => TC("SeparatorColor", System.Drawing.Color.FromArgb(228, 228, 242));
public override System.Drawing.Color MenuBorder => Border;
public override System.Drawing.Color ToolStripDropDownBackground => Bg;
public override System.Drawing.Color ImageMarginGradientBegin => Bg;
public override System.Drawing.Color ImageMarginGradientMiddle => Bg;
public override System.Drawing.Color ImageMarginGradientEnd => Bg;
public override System.Drawing.Color MenuItemSelected => Hover;
public override System.Drawing.Color MenuItemSelectedGradientBegin => Hover;
public override System.Drawing.Color MenuItemSelectedGradientEnd => Hover;
public override System.Drawing.Color MenuItemBorder => System.Drawing.Color.Transparent;
public override System.Drawing.Color MenuItemPressedGradientBegin => Hover;
public override System.Drawing.Color MenuItemPressedGradientEnd => Hover;
public override System.Drawing.Color SeparatorLight => Sep;
public override System.Drawing.Color SeparatorDark => Sep;
public override System.Drawing.Color CheckBackground => System.Drawing.Color.Transparent;
public override System.Drawing.Color CheckSelectedBackground => System.Drawing.Color.Transparent;
public override System.Drawing.Color CheckPressedBackground => System.Drawing.Color.Transparent;
private static System.Drawing.Color TC(string key, System.Drawing.Color fb)
{
try
{
if (System.Windows.Application.Current?.Resources[key] is SolidColorBrush { Color: var color } solidColorBrush)
{
return System.Drawing.Color.FromArgb(color.A, solidColorBrush.Color.R, solidColorBrush.Color.G, solidColorBrush.Color.B);
}
}
catch
{
}
return fb;
}
}

View File

@@ -0,0 +1,179 @@
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Text;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Media;
namespace AxCopilot.Views;
internal sealed class ModernTrayRenderer : ToolStripProfessionalRenderer
{
private static readonly System.Drawing.Color BulbOnColor = System.Drawing.Color.FromArgb(255, 185, 0);
private static readonly System.Drawing.Color BulbGlowHalo = System.Drawing.Color.FromArgb(50, 255, 185, 0);
private static System.Drawing.Color BgColor => ThemeColor("LauncherBackground", System.Drawing.Color.FromArgb(250, 250, 252));
private static System.Drawing.Color HoverColor => ThemeColor("ItemHoverBackground", System.Drawing.Color.FromArgb(234, 234, 247));
private static System.Drawing.Color AccentColor => ThemeColor("AccentColor", System.Drawing.Color.FromArgb(75, 94, 252));
private static System.Drawing.Color TextColor => ThemeColor("PrimaryText", System.Drawing.Color.FromArgb(22, 23, 42));
private static System.Drawing.Color TextDimColor => ThemeColor("SecondaryText", System.Drawing.Color.FromArgb(90, 92, 128));
private static System.Drawing.Color SepColor => ThemeColor("SeparatorColor", System.Drawing.Color.FromArgb(228, 228, 242));
private static System.Drawing.Color BorderColor => ThemeColor("BorderColor", System.Drawing.Color.FromArgb(210, 210, 232));
private static System.Drawing.Color IconColor => ThemeColor("SecondaryText", System.Drawing.Color.FromArgb(110, 112, 148));
public ModernTrayRenderer()
: base(new ModernColorTable())
{
}
private static System.Drawing.Color ThemeColor(string key, System.Drawing.Color fallback)
{
try
{
if (System.Windows.Application.Current?.Resources[key] is SolidColorBrush { Color: var color } solidColorBrush)
{
return System.Drawing.Color.FromArgb(color.A, solidColorBrush.Color.R, solidColorBrush.Color.G, solidColorBrush.Color.B);
}
}
catch
{
}
return fallback;
}
protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
{
using SolidBrush brush = new SolidBrush(BgColor);
e.Graphics.FillRectangle(brush, e.AffectedBounds);
}
protected override void OnRenderToolStripBorder(ToolStripRenderEventArgs e)
{
Graphics graphics = e.Graphics;
graphics.SmoothingMode = SmoothingMode.AntiAlias;
using System.Drawing.Pen pen = new System.Drawing.Pen(BorderColor, 1f);
RectangleF rect = new RectangleF(0.5f, 0.5f, (float)e.ToolStrip.Width - 1f, (float)e.ToolStrip.Height - 1f);
using GraphicsPath path = BuildRoundedPath(rect, 15f);
graphics.DrawPath(pen, path);
graphics.SmoothingMode = SmoothingMode.Default;
}
protected override void OnRenderImageMargin(ToolStripRenderEventArgs e)
{
using SolidBrush brush = new SolidBrush(BgColor);
e.Graphics.FillRectangle(brush, e.AffectedBounds);
}
protected override void OnRenderMenuItemBackground(ToolStripItemRenderEventArgs e)
{
Graphics graphics = e.Graphics;
ToolStripItem item = e.Item;
using SolidBrush brush = new SolidBrush(BgColor);
graphics.FillRectangle(brush, 0, 0, item.Width, item.Height);
if (!item.Selected || !item.Enabled)
{
return;
}
graphics.SmoothingMode = SmoothingMode.AntiAlias;
using SolidBrush brush2 = new SolidBrush(HoverColor);
DrawRoundedFill(graphics, brush2, new RectangleF(6f, 2f, item.Width - 12, item.Height - 4), 8f);
graphics.SmoothingMode = SmoothingMode.Default;
}
protected override void OnRenderSeparator(ToolStripSeparatorRenderEventArgs e)
{
int num = e.Item.Height / 2;
using System.Drawing.Pen pen = new System.Drawing.Pen(SepColor);
e.Graphics.DrawLine(pen, 16, num, e.Item.Width - 16, num);
}
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
e.TextColor = (e.Item.Enabled ? TextColor : TextDimColor);
e.TextFormat = TextFormatFlags.VerticalCenter;
base.OnRenderItemText(e);
}
protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e)
{
DrawGlyph(e.Graphics, e.Item, e.ImageRectangle);
}
protected override void OnRenderItemCheck(ToolStripItemImageRenderEventArgs e)
{
DrawGlyph(e.Graphics, e.Item, e.ImageRectangle);
}
private static void DrawGlyph(Graphics g, ToolStripItem item, Rectangle bounds)
{
if (!(item.Tag is string text) || string.IsNullOrEmpty(text) || bounds.Width <= 0 || bounds.Height <= 0)
{
return;
}
g.TextRenderingHint = TextRenderingHint.AntiAlias;
bool flag = text == "\ue82f";
bool flag2 = item is ToolStripMenuItem toolStripMenuItem && toolStripMenuItem.Checked;
System.Drawing.Color color;
if (!(flag && flag2))
{
color = ((flag && !flag2) ? System.Drawing.Color.FromArgb(120, 120, 140) : ((!item.Selected || !item.Enabled) ? IconColor : AccentColor));
}
else
{
DrawLightbulbGlow(g, text, bounds);
color = BulbOnColor;
}
using Font font = new Font("Segoe MDL2 Assets", 12f, GraphicsUnit.Point);
using SolidBrush brush = new SolidBrush(color);
StringFormat genericTypographic = StringFormat.GenericTypographic;
SizeF sizeF = g.MeasureString(text, font, 0, genericTypographic);
float x = (float)bounds.X + ((float)bounds.Width - sizeF.Width) / 2f + 2f;
float y = (float)bounds.Y + ((float)bounds.Height - sizeF.Height) / 2f;
g.DrawString(text, font, brush, x, y, genericTypographic);
}
private static void DrawLightbulbGlow(Graphics g, string glyph, Rectangle bounds)
{
g.SmoothingMode = SmoothingMode.AntiAlias;
float num = (float)bounds.X + (float)bounds.Width / 2f;
float num2 = (float)bounds.Y + (float)bounds.Height / 2f;
float num3 = (float)Math.Max(bounds.Width, bounds.Height) * 0.85f;
RectangleF rect = new RectangleF(num - num3, num2 - num3, num3 * 2f, num3 * 2f);
using GraphicsPath graphicsPath = new GraphicsPath();
graphicsPath.AddEllipse(rect);
PathGradientBrush pathGradientBrush = new PathGradientBrush(graphicsPath);
pathGradientBrush.CenterColor = System.Drawing.Color.FromArgb(60, 255, 185, 0);
pathGradientBrush.SurroundColors = new System.Drawing.Color[1] { System.Drawing.Color.FromArgb(0, 255, 185, 0) };
pathGradientBrush.CenterPoint = new PointF(num, num2);
using PathGradientBrush brush = pathGradientBrush;
g.FillEllipse(brush, rect);
g.SmoothingMode = SmoothingMode.Default;
}
private static GraphicsPath BuildRoundedPath(RectangleF rect, float radius)
{
float num = radius * 2f;
GraphicsPath graphicsPath = new GraphicsPath();
graphicsPath.AddArc(rect.X, rect.Y, num, num, 180f, 90f);
graphicsPath.AddArc(rect.Right - num, rect.Y, num, num, 270f, 90f);
graphicsPath.AddArc(rect.Right - num, rect.Bottom - num, num, num, 0f, 90f);
graphicsPath.AddArc(rect.X, rect.Bottom - num, num, num, 90f, 90f);
graphicsPath.CloseFigure();
return graphicsPath;
}
private static void DrawRoundedFill(Graphics g, System.Drawing.Brush brush, RectangleF rect, float radius)
{
using GraphicsPath path = BuildRoundedPath(rect, radius);
g.FillPath(brush, path);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,686 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
using AxCopilot.Services;
using AxCopilot.Services.Agent;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;
namespace AxCopilot.Views;
public class PreviewWindow : Window, IComponentConnector
{
private static PreviewWindow? _instance;
private readonly List<string> _tabs = new List<string>();
private string? _activeTab;
private bool _webViewInitialized;
private string? _selectedMood;
private static readonly string WebView2DataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "WebView2_Preview");
private static readonly HashSet<string> PreviewableExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".html", ".htm", ".md", ".csv", ".txt", ".json", ".xml", ".log" };
private const int WM_NCHITTEST = 132;
private const int HTLEFT = 10;
private const int HTRIGHT = 11;
private const int HTTOP = 12;
private const int HTTOPLEFT = 13;
private const int HTTOPRIGHT = 14;
private const int HTBOTTOM = 15;
private const int HTBOTTOMLEFT = 16;
private const int HTBOTTOMRIGHT = 17;
internal TextBlock TitleText;
internal TextBlock MaxBtnIcon;
internal StackPanel TabPanel;
internal WebView2 PreviewBrowser;
internal ScrollViewer TextScroll;
internal TextBlock TextContent;
internal DataGrid DataGridContent;
internal TextBlock EmptyMessage;
private bool _contentLoaded;
public static bool IsOpen => _instance != null && _instance.IsLoaded;
public PreviewWindow()
{
InitializeComponent();
base.Loaded += OnLoaded;
base.SourceInitialized += OnSourceInitialized;
base.KeyDown += delegate(object _, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)e.Key == 13)
{
Close();
}
};
base.StateChanged += delegate
{
MaxBtnIcon.Text = ((base.WindowState == WindowState.Maximized) ? "\ue923" : "\ue922");
};
base.Closed += delegate
{
_instance = null;
};
}
[DllImport("user32.dll")]
private static extern nint SendMessage(nint hWnd, int msg, nint wParam, nint lParam);
private void OnSourceInitialized(object? sender, EventArgs e)
{
((HwndSource)PresentationSource.FromVisual(this))?.AddHook(WndProc);
}
private nint WndProc(nint hwnd, int msg, nint wParam, nint lParam, ref bool handled)
{
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003d: Unknown result type (might be due to invalid IL or missing references)
if (msg == 132)
{
Point val = PointFromScreen(new Point((double)(short)(((IntPtr)lParam).ToInt32() & 0xFFFF), (double)(short)((((IntPtr)lParam).ToInt32() >> 16) & 0xFFFF)));
double actualWidth = base.ActualWidth;
double actualHeight = base.ActualHeight;
if (((Point)(ref val)).X < 8.0 && ((Point)(ref val)).Y < 8.0)
{
handled = true;
return 13;
}
if (((Point)(ref val)).X > actualWidth - 8.0 && ((Point)(ref val)).Y < 8.0)
{
handled = true;
return 14;
}
if (((Point)(ref val)).X < 8.0 && ((Point)(ref val)).Y > actualHeight - 8.0)
{
handled = true;
return 16;
}
if (((Point)(ref val)).X > actualWidth - 8.0 && ((Point)(ref val)).Y > actualHeight - 8.0)
{
handled = true;
return 17;
}
if (((Point)(ref val)).X < 8.0)
{
handled = true;
return 10;
}
if (((Point)(ref val)).X > actualWidth - 8.0)
{
handled = true;
return 11;
}
if (((Point)(ref val)).Y < 8.0)
{
handled = true;
return 12;
}
if (((Point)(ref val)).Y > actualHeight - 8.0)
{
handled = true;
return 15;
}
}
return IntPtr.Zero;
}
public static void ShowPreview(string filePath, string? mood = null)
{
if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
{
return;
}
string item = Path.GetExtension(filePath).ToLowerInvariant();
if (!PreviewableExtensions.Contains(item))
{
return;
}
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
{
if (_instance == null || !_instance.IsLoaded)
{
_instance = new PreviewWindow();
Window mainWindow = Application.Current.MainWindow;
if (mainWindow != null)
{
foreach (ResourceDictionary mergedDictionary in mainWindow.Resources.MergedDictionaries)
{
_instance.Resources.MergedDictionaries.Add(mergedDictionary);
}
}
_instance._selectedMood = mood;
_instance.Show();
}
_instance.AddTab(filePath);
_instance.Activate();
});
}
public static void RefreshIfOpen(string filePath)
{
if (_instance == null || !_instance.IsLoaded)
{
return;
}
((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
{
if (_instance._activeTab != null && string.Equals(_instance._activeTab, filePath, StringComparison.OrdinalIgnoreCase))
{
_instance.LoadContent(filePath);
}
else
{
string text = _instance._tabs.FirstOrDefault((string t) => string.Equals(t, filePath, StringComparison.OrdinalIgnoreCase));
if (text != null)
{
_instance._activeTab = text;
_instance.LoadContent(text);
_instance.RebuildTabs();
}
}
});
}
private async void OnLoaded(object sender, RoutedEventArgs e)
{
try
{
CoreWebView2Environment env = await CoreWebView2Environment.CreateAsync(null, WebView2DataFolder);
await PreviewBrowser.EnsureCoreWebView2Async(env);
_webViewInitialized = true;
if (_activeTab != null)
{
LoadContent(_activeTab);
}
}
catch (Exception ex)
{
Exception ex2 = ex;
LogService.Warn("PreviewWindow WebView2 초기화 실패: " + ex2.Message);
}
}
private void AddTab(string filePath)
{
if (!_tabs.Contains<string>(filePath, StringComparer.OrdinalIgnoreCase))
{
_tabs.Add(filePath);
}
_activeTab = filePath;
RebuildTabs();
LoadContent(filePath);
}
private void CloseTab(string filePath)
{
_tabs.RemoveAll((string t) => string.Equals(t, filePath, StringComparison.OrdinalIgnoreCase));
if (_tabs.Count == 0)
{
Close();
return;
}
if (string.Equals(_activeTab, filePath, StringComparison.OrdinalIgnoreCase))
{
List<string> tabs = _tabs;
_activeTab = tabs[tabs.Count - 1];
LoadContent(_activeTab);
}
RebuildTabs();
}
private void RebuildTabs()
{
TabPanel.Children.Clear();
Brush brush = (TryFindResource("AccentColor") as Brush) ?? Brushes.CornflowerBlue;
Brush brush2 = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush brush3 = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush background = (TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
foreach (string tab in _tabs)
{
string fileName = Path.GetFileName(tab);
bool flag = string.Equals(tab, _activeTab, StringComparison.OrdinalIgnoreCase);
Border border = new Border
{
Background = Brushes.Transparent,
BorderBrush = (flag ? brush : Brushes.Transparent),
BorderThickness = new Thickness(0.0, 0.0, 0.0, flag ? 2 : 0),
Padding = new Thickness(10.0, 6.0, 6.0, 6.0),
Cursor = Cursors.Hand,
MaxWidth = ((_tabs.Count <= 3) ? 220 : ((_tabs.Count <= 5) ? 160 : 110))
};
StackPanel stackPanel = new StackPanel
{
Orientation = Orientation.Horizontal
};
stackPanel.Children.Add(new TextBlock
{
Text = fileName,
FontSize = 11.5,
Foreground = (flag ? brush3 : brush2),
FontWeight = (flag ? FontWeights.SemiBold : FontWeights.Normal),
VerticalAlignment = VerticalAlignment.Center,
TextTrimming = TextTrimming.CharacterEllipsis,
MaxWidth = border.MaxWidth - 36.0,
ToolTip = tab
});
string closePath = tab;
Border border2 = new Border
{
Background = Brushes.Transparent,
CornerRadius = new CornerRadius(3.0),
Padding = new Thickness(4.0, 2.0, 4.0, 2.0),
Margin = new Thickness(6.0, 0.0, 0.0, 0.0),
Cursor = Cursors.Hand,
VerticalAlignment = VerticalAlignment.Center,
Child = new TextBlock
{
Text = "\ue711",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 8.0,
Foreground = brush2,
VerticalAlignment = VerticalAlignment.Center
}
};
border2.MouseEnter += delegate(object s, MouseEventArgs _)
{
if (s is Border border3)
{
border3.Background = new SolidColorBrush(Color.FromArgb(48, byte.MaxValue, 80, 80));
}
};
border2.MouseLeave += delegate(object s, MouseEventArgs _)
{
if (s is Border border3)
{
border3.Background = Brushes.Transparent;
}
};
border2.MouseLeftButtonUp += delegate(object _, MouseButtonEventArgs me)
{
me.Handled = true;
CloseTab(closePath);
};
stackPanel.Children.Add(border2);
border.Child = stackPanel;
string clickPath = tab;
border.MouseLeftButtonUp += delegate(object _, MouseButtonEventArgs me)
{
if (!me.Handled)
{
me.Handled = true;
_activeTab = clickPath;
RebuildTabs();
LoadContent(clickPath);
}
};
border.MouseEnter += delegate(object s, MouseEventArgs _)
{
if (s is Border border3 && !string.Equals(clickPath, _activeTab, StringComparison.OrdinalIgnoreCase))
{
border3.Background = new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
}
};
border.MouseLeave += delegate(object s, MouseEventArgs _)
{
if (s is Border border3)
{
border3.Background = Brushes.Transparent;
}
};
TabPanel.Children.Add(border);
List<string> tabs = _tabs;
if (tab != tabs[tabs.Count - 1])
{
TabPanel.Children.Add(new Border
{
Width = 1.0,
Height = 14.0,
Background = background,
Margin = new Thickness(2.0, 0.0, 2.0, 0.0),
VerticalAlignment = VerticalAlignment.Center
});
}
}
if (_activeTab != null)
{
TitleText.Text = "미리보기 — " + Path.GetFileName(_activeTab);
}
}
private async void LoadContent(string filePath)
{
string ext = Path.GetExtension(filePath).ToLowerInvariant();
PreviewBrowser.Visibility = Visibility.Collapsed;
TextScroll.Visibility = Visibility.Collapsed;
DataGridContent.Visibility = Visibility.Collapsed;
EmptyMessage.Visibility = Visibility.Collapsed;
if (!File.Exists(filePath))
{
EmptyMessage.Text = "파일을 찾을 수 없습니다";
EmptyMessage.Visibility = Visibility.Visible;
return;
}
try
{
switch (ext)
{
case ".html":
case ".htm":
if (!_webViewInitialized)
{
return;
}
PreviewBrowser.Source = new Uri(filePath);
PreviewBrowser.Visibility = Visibility.Visible;
break;
case ".csv":
LoadCsvContent(filePath);
DataGridContent.Visibility = Visibility.Visible;
break;
case ".md":
{
if (!_webViewInitialized)
{
return;
}
string mdText = File.ReadAllText(filePath);
if (mdText.Length > 50000)
{
mdText = mdText.Substring(0, 50000);
}
string mdHtml = TemplateService.RenderMarkdownToHtml(mdText, _selectedMood ?? "modern");
PreviewBrowser.NavigateToString(mdHtml);
PreviewBrowser.Visibility = Visibility.Visible;
break;
}
case ".txt":
case ".json":
case ".xml":
case ".log":
{
string text = File.ReadAllText(filePath);
if (text.Length > 50000)
{
text = text.Substring(0, 50000) + "\n\n... (이후 생략)";
}
TextContent.Text = text;
TextScroll.Visibility = Visibility.Visible;
break;
}
default:
EmptyMessage.Text = "미리보기할 수 없는 파일 형식입니다";
EmptyMessage.Visibility = Visibility.Visible;
break;
}
}
catch (Exception ex)
{
Exception ex2 = ex;
TextContent.Text = "미리보기 오류: " + ex2.Message;
TextScroll.Visibility = Visibility.Visible;
}
await Task.CompletedTask;
}
private void LoadCsvContent(string filePath)
{
string[] array = File.ReadAllLines(filePath);
if (array.Length == 0)
{
return;
}
DataTable dataTable = new DataTable();
string[] array2 = ParseCsvLine(array[0]);
string[] array3 = array2;
foreach (string columnName in array3)
{
dataTable.Columns.Add(columnName);
}
int num = Math.Min(array.Length, 501);
for (int j = 1; j < num; j++)
{
string[] array4 = ParseCsvLine(array[j]);
DataRow dataRow = dataTable.NewRow();
for (int k = 0; k < Math.Min(array4.Length, array2.Length); k++)
{
dataRow[k] = array4[k];
}
dataTable.Rows.Add(dataRow);
}
DataGridContent.ItemsSource = dataTable.DefaultView;
}
private static string[] ParseCsvLine(string line)
{
List<string> list = new List<string>();
StringBuilder stringBuilder = new StringBuilder();
bool flag = false;
for (int i = 0; i < line.Length; i++)
{
char c = line[i];
if (flag)
{
if (c == '"' && i + 1 < line.Length && line[i + 1] == '"')
{
stringBuilder.Append('"');
i++;
}
else if (c == '"')
{
flag = false;
}
else
{
stringBuilder.Append(c);
}
continue;
}
switch (c)
{
case '"':
flag = true;
break;
case ',':
list.Add(stringBuilder.ToString());
stringBuilder.Clear();
break;
default:
stringBuilder.Append(c);
break;
}
}
list.Add(stringBuilder.ToString());
return list.ToArray();
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
ToggleMaximize();
}
else
{
DragMove();
}
}
private void OpenExternalBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
if (_activeTab == null || !File.Exists(_activeTab))
{
return;
}
try
{
Process.Start(new ProcessStartInfo
{
FileName = _activeTab,
UseShellExecute = true
});
}
catch (Exception ex)
{
LogService.Warn("외부 프로그램 열기 실패: " + ex.Message);
}
}
private void MinBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
base.WindowState = WindowState.Minimized;
}
private void MaxBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
ToggleMaximize();
}
private void CloseBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
Close();
}
private void ToggleMaximize()
{
base.WindowState = ((base.WindowState != WindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
}
private void TitleBtn_Enter(object sender, MouseEventArgs e)
{
if (sender is Border border)
{
border.Background = (TryFindResource("ItemHoverBackground") as Brush) ?? new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
}
}
private void CloseBtnEnter(object sender, MouseEventArgs e)
{
if (sender is Border border)
{
border.Background = new SolidColorBrush(Color.FromArgb(68, byte.MaxValue, 64, 64));
}
}
private void TitleBtn_Leave(object sender, MouseEventArgs e)
{
if (sender is Border border)
{
border.Background = Brushes.Transparent;
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/previewwindow.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:
((Border)target).MouseLeftButtonDown += TitleBar_MouseLeftButtonDown;
break;
case 2:
TitleText = (TextBlock)target;
break;
case 3:
((Border)target).MouseLeftButtonDown += OpenExternalBtn_Click;
((Border)target).MouseEnter += TitleBtn_Enter;
((Border)target).MouseLeave += TitleBtn_Leave;
break;
case 4:
((Border)target).MouseLeftButtonDown += MinBtn_Click;
((Border)target).MouseEnter += TitleBtn_Enter;
((Border)target).MouseLeave += TitleBtn_Leave;
break;
case 5:
((Border)target).MouseLeftButtonDown += MaxBtn_Click;
((Border)target).MouseEnter += TitleBtn_Enter;
((Border)target).MouseLeave += TitleBtn_Leave;
break;
case 6:
MaxBtnIcon = (TextBlock)target;
break;
case 7:
((Border)target).MouseLeftButtonDown += CloseBtn_Click;
((Border)target).MouseEnter += CloseBtnEnter;
((Border)target).MouseLeave += TitleBtn_Leave;
break;
case 8:
TabPanel = (StackPanel)target;
break;
case 9:
PreviewBrowser = (WebView2)target;
break;
case 10:
TextScroll = (ScrollViewer)target;
break;
case 11:
TextContent = (TextBlock)target;
break;
case 12:
DataGridContent = (DataGrid)target;
break;
case 13:
EmptyMessage = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,261 @@
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Effects;
using System.Windows.Shapes;
namespace AxCopilot.Views;
internal sealed class PromptTemplateDialog : Window
{
private readonly TextBox _nameBox;
private readonly TextBox _contentBox;
public string TemplateName => _nameBox.Text.Trim();
public string TemplateContent => _contentBox.Text.Trim();
public PromptTemplateDialog(string existingName = "", string existingContent = "")
{
bool flag = !string.IsNullOrEmpty(existingName);
base.Title = (flag ? "템플릿 편집" : "템플릿 추가");
base.Width = 480.0;
base.SizeToContent = SizeToContent.Height;
base.WindowStartupLocation = WindowStartupLocation.CenterOwner;
base.ResizeMode = ResizeMode.NoResize;
base.WindowStyle = WindowStyle.None;
base.AllowsTransparency = true;
base.Background = Brushes.Transparent;
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush foreground = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush brush = (Application.Current.TryFindResource("AccentColor") as Brush) ?? Brushes.Blue;
Brush background2 = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 43, 64));
Brush brush2 = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(16.0),
BorderBrush = brush2,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(28.0, 24.0, 28.0, 24.0),
Effect = new DropShadowEffect
{
BlurRadius = 24.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = Colors.Black
}
};
StackPanel stackPanel = new StackPanel();
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 20.0)
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\ue8a5",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 18.0,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 10.0, 0.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = (flag ? "템플릿 편집" : "새 프롬프트 템플릿"),
FontSize = 17.0,
FontWeight = FontWeights.Bold,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center
});
stackPanel.Children.Add(stackPanel2);
stackPanel.Children.Add(new TextBlock
{
Text = "템플릿 이름",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = "목록에 표시될 이름입니다. 예: 코드 리뷰 요청, 번역 요청",
FontSize = 11.0,
Foreground = foreground2,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
_nameBox = new TextBox
{
Text = existingName,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0)
};
Border element = new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _nameBox
};
stackPanel.Children.Add(element);
stackPanel.Children.Add(new Rectangle
{
Height = 1.0,
Fill = brush2,
Margin = new Thickness(0.0, 16.0, 0.0, 16.0),
Opacity = 0.5
});
stackPanel.Children.Add(new TextBlock
{
Text = "프롬프트 내용",
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = "채팅 입력란에 자동으로 삽입될 텍스트입니다.",
FontSize = 11.0,
Foreground = foreground2,
Margin = new Thickness(0.0, 0.0, 0.0, 8.0)
});
_contentBox = new TextBox
{
Text = existingContent,
FontSize = 13.0,
Padding = new Thickness(12.0, 8.0, 12.0, 8.0),
Foreground = foreground,
Background = background2,
CaretBrush = brush,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0),
AcceptsReturn = true,
TextWrapping = TextWrapping.Wrap,
MinHeight = 100.0,
MaxHeight = 240.0,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto
};
Border element2 = new Border
{
CornerRadius = new CornerRadius(8.0),
ClipToBounds = true,
Child = _contentBox
};
stackPanel.Children.Add(element2);
TextBlock charCount = new TextBlock
{
FontSize = 10.5,
Foreground = foreground2,
Margin = new Thickness(0.0, 6.0, 0.0, 0.0),
HorizontalAlignment = HorizontalAlignment.Right
};
UpdateCharCount(charCount);
_contentBox.TextChanged += delegate
{
UpdateCharCount(charCount);
};
stackPanel.Children.Add(charCount);
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 20.0, 0.0, 0.0)
};
Button button = new Button
{
Content = "취소",
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Margin = new Thickness(0.0, 0.0, 10.0, 0.0),
Background = Brushes.Transparent,
Foreground = foreground2,
BorderBrush = brush2,
BorderThickness = new Thickness(1.0),
Cursor = Cursors.Hand,
FontSize = 13.0
};
button.Click += delegate
{
base.DialogResult = false;
Close();
};
stackPanel3.Children.Add(button);
Button button2 = new Button
{
Content = (flag ? "저장" : "추가"),
Width = 80.0,
Padding = new Thickness(0.0, 8.0, 0.0, 8.0),
Background = brush,
Foreground = Brushes.White,
BorderThickness = new Thickness(0.0),
Cursor = Cursors.Hand,
FontSize = 13.0,
FontWeight = FontWeights.SemiBold
};
button2.Click += delegate
{
if (string.IsNullOrWhiteSpace(_nameBox.Text))
{
CustomMessageBox.Show("템플릿 이름을 입력하세요.", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_nameBox.Focus();
}
else if (string.IsNullOrWhiteSpace(_contentBox.Text))
{
CustomMessageBox.Show("프롬프트 내용을 입력하세요.", "입력 오류", MessageBoxButton.OK, MessageBoxImage.Exclamation);
_contentBox.Focus();
}
else
{
base.DialogResult = true;
Close();
}
};
stackPanel3.Children.Add(button2);
stackPanel.Children.Add(stackPanel3);
border.Child = stackPanel;
base.Content = border;
base.KeyDown += delegate(object _, KeyEventArgs ke)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)ke.Key == 13)
{
base.DialogResult = false;
Close();
}
};
base.Loaded += delegate
{
_nameBox.Focus();
_nameBox.SelectAll();
};
border.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs me)
{
if (me.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
};
}
private void UpdateCharCount(TextBlock tb)
{
int length = _contentBox.Text.Length;
tb.Text = $"{length}자";
}
}

View File

@@ -0,0 +1,310 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace AxCopilot.Views;
public class RegionSelectWindow : Window, IComponentConnector
{
private readonly System.Drawing.Rectangle _screenBounds;
private Point _startPoint;
private Point _endPoint;
private bool _isDragging;
internal Canvas RootCanvas;
internal System.Windows.Shapes.Rectangle OverlayTop;
internal System.Windows.Shapes.Rectangle OverlayBottom;
internal System.Windows.Shapes.Rectangle OverlayLeft;
internal System.Windows.Shapes.Rectangle OverlayRight;
internal System.Windows.Shapes.Rectangle SelectionBorder;
internal Border GuideText;
internal Border SizeLabel;
internal TextBlock SizeLabelText;
private bool _contentLoaded;
public System.Drawing.Rectangle? SelectedRect { get; private set; }
public RegionSelectWindow(Bitmap fullScreenshot, System.Drawing.Rectangle screenBounds)
{
InitializeComponent();
_screenBounds = screenBounds;
base.Left = screenBounds.X;
base.Top = screenBounds.Y;
base.Width = screenBounds.Width;
base.Height = screenBounds.Height;
RootCanvas.Background = CreateFrozenBrush(fullScreenshot);
OverlayTop.Width = screenBounds.Width;
OverlayTop.Height = screenBounds.Height;
OverlayBottom.Width = screenBounds.Width;
OverlayLeft.Width = 0.0;
OverlayRight.Width = 0.0;
base.Loaded += delegate
{
Canvas.SetLeft(GuideText, (base.Width - GuideText.ActualWidth) / 2.0);
Canvas.SetTop(GuideText, (base.Height - GuideText.ActualHeight) / 2.0);
};
}
private static ImageBrush CreateFrozenBrush(Bitmap bmp)
{
using MemoryStream memoryStream = new MemoryStream();
bmp.Save(memoryStream, ImageFormat.Bmp);
memoryStream.Position = 0L;
BitmapImage bitmapImage = new BitmapImage();
bitmapImage.BeginInit();
bitmapImage.StreamSource = memoryStream;
bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
bitmapImage.EndInit();
((Freezable)bitmapImage).Freeze();
ImageBrush imageBrush = new ImageBrush(bitmapImage)
{
Stretch = Stretch.None,
AlignmentX = AlignmentX.Left,
AlignmentY = AlignmentY.Top
};
((Freezable)imageBrush).Freeze();
return imageBrush;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001d: Unknown result type (might be due to invalid IL or missing references)
if (e.ChangedButton == MouseButton.Left)
{
_startPoint = e.GetPosition(RootCanvas);
_isDragging = true;
GuideText.Visibility = Visibility.Collapsed;
SelectionBorder.Visibility = Visibility.Visible;
SizeLabel.Visibility = Visibility.Visible;
CaptureMouse();
}
}
private void Window_MouseMove(object sender, MouseEventArgs e)
{
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
//IL_001f: Unknown result type (might be due to invalid IL or missing references)
//IL_0024: Unknown result type (might be due to invalid IL or missing references)
if (_isDragging)
{
Point position = e.GetPosition(RootCanvas);
UpdateSelection(_startPoint, position);
}
}
private void Window_MouseUp(object sender, MouseButtonEventArgs e)
{
//IL_0030: Unknown result type (might be due to invalid IL or missing references)
//IL_0035: Unknown result type (might be due to invalid IL or missing references)
//IL_0037: Unknown result type (might be due to invalid IL or missing references)
//IL_0038: Unknown result type (might be due to invalid IL or missing references)
//IL_003e: Unknown result type (might be due to invalid IL or missing references)
//IL_0043: Unknown result type (might be due to invalid IL or missing references)
//IL_0044: Unknown result type (might be due to invalid IL or missing references)
//IL_0049: Unknown result type (might be due to invalid IL or missing references)
if (_isDragging && e.ChangedButton == MouseButton.Left)
{
_isDragging = false;
ReleaseMouseCapture();
Rect val = MakeRect(b: _endPoint = e.GetPosition(RootCanvas), a: _startPoint);
if (!(((Rect)(ref val)).Width < 4.0) && !(((Rect)(ref val)).Height < 4.0))
{
SizeLabelText.Text += " · ↑↓←→ 미세조정 · Enter 확정";
}
}
}
private void Window_KeyDown(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_0062: Unknown result type (might be due to invalid IL or missing references)
//IL_0086: Unknown result type (might be due to invalid IL or missing references)
//IL_008b: Unknown result type (might be due to invalid IL or missing references)
//IL_008d: Unknown result type (might be due to invalid IL or missing references)
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0091: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Invalid comparison between Unknown and I4
//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
//IL_0098: Unknown result type (might be due to invalid IL or missing references)
//IL_009c: Unknown result type (might be due to invalid IL or missing references)
//IL_00b2: Expected I4, but got Unknown
//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
//IL_01bd: Unknown result type (might be due to invalid IL or missing references)
//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
if ((int)e.Key == 13)
{
SelectedRect = null;
Close();
}
else
{
if (_isDragging || SelectionBorder.Visibility != Visibility.Visible)
{
return;
}
double num = 0.0;
double num2 = 0.0;
double num3 = ((!((Enum)Keyboard.Modifiers).HasFlag((Enum)(object)(ModifierKeys)4)) ? 1 : 10);
Key key = e.Key;
Key val = key;
if ((int)val != 6)
{
switch (val - 23)
{
default:
return;
case 0:
num = 0.0 - num3;
break;
case 2:
num = num3;
break;
case 1:
num2 = 0.0 - num3;
break;
case 3:
num2 = num3;
break;
}
_endPoint = new Point(((Point)(ref _endPoint)).X + num, ((Point)(ref _endPoint)).Y + num2);
UpdateSelection(_startPoint, _endPoint);
e.Handled = true;
}
else
{
Rect val2 = MakeRect(_startPoint, _endPoint);
if (((Rect)(ref val2)).Width >= 4.0 && ((Rect)(ref val2)).Height >= 4.0)
{
DpiScale dpi = VisualTreeHelper.GetDpi(this);
SelectedRect = new System.Drawing.Rectangle((int)(((Rect)(ref val2)).X * dpi.DpiScaleX) + _screenBounds.X, (int)(((Rect)(ref val2)).Y * dpi.DpiScaleY) + _screenBounds.Y, (int)(((Rect)(ref val2)).Width * dpi.DpiScaleX), (int)(((Rect)(ref val2)).Height * dpi.DpiScaleY));
}
Close();
}
}
}
private void UpdateSelection(Point a, Point b)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
Rect val = MakeRect(a, b);
Canvas.SetLeft(SelectionBorder, ((Rect)(ref val)).X);
Canvas.SetTop(SelectionBorder, ((Rect)(ref val)).Y);
SelectionBorder.Width = ((Rect)(ref val)).Width;
SelectionBorder.Height = ((Rect)(ref val)).Height;
OverlayTop.Width = base.Width;
OverlayTop.Height = ((Rect)(ref val)).Y;
OverlayBottom.Width = base.Width;
OverlayBottom.Height = base.Height - ((Rect)(ref val)).Y - ((Rect)(ref val)).Height;
Canvas.SetTop(OverlayBottom, ((Rect)(ref val)).Y + ((Rect)(ref val)).Height);
OverlayLeft.Width = ((Rect)(ref val)).X;
OverlayLeft.Height = ((Rect)(ref val)).Height;
Canvas.SetTop(OverlayLeft, ((Rect)(ref val)).Y);
OverlayRight.Width = base.Width - ((Rect)(ref val)).X - ((Rect)(ref val)).Width;
OverlayRight.Height = ((Rect)(ref val)).Height;
Canvas.SetLeft(OverlayRight, ((Rect)(ref val)).X + ((Rect)(ref val)).Width);
Canvas.SetTop(OverlayRight, ((Rect)(ref val)).Y);
DpiScale dpi = VisualTreeHelper.GetDpi(this);
int value = (int)(((Rect)(ref val)).Width * dpi.DpiScaleX);
int value2 = (int)(((Rect)(ref val)).Height * dpi.DpiScaleY);
SizeLabelText.Text = $"{value} × {value2}";
Canvas.SetLeft(SizeLabel, ((Rect)(ref val)).X + ((Rect)(ref val)).Width + 8.0);
Canvas.SetTop(SizeLabel, ((Rect)(ref val)).Y + ((Rect)(ref val)).Height + 4.0);
}
private static Rect MakeRect(Point a, Point b)
{
//IL_004e: Unknown result type (might be due to invalid IL or missing references)
return new Rect(Math.Min(((Point)(ref a)).X, ((Point)(ref b)).X), Math.Min(((Point)(ref a)).Y, ((Point)(ref b)).Y), Math.Abs(((Point)(ref b)).X - ((Point)(ref a)).X), Math.Abs(((Point)(ref b)).Y - ((Point)(ref a)).Y));
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/regionselectwindow.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:
((RegionSelectWindow)target).MouseDown += Window_MouseDown;
((RegionSelectWindow)target).MouseMove += Window_MouseMove;
((RegionSelectWindow)target).MouseUp += Window_MouseUp;
((RegionSelectWindow)target).KeyDown += Window_KeyDown;
break;
case 2:
RootCanvas = (Canvas)target;
break;
case 3:
OverlayTop = (System.Windows.Shapes.Rectangle)target;
break;
case 4:
OverlayBottom = (System.Windows.Shapes.Rectangle)target;
break;
case 5:
OverlayLeft = (System.Windows.Shapes.Rectangle)target;
break;
case 6:
OverlayRight = (System.Windows.Shapes.Rectangle)target;
break;
case 7:
SelectionBorder = (System.Windows.Shapes.Rectangle)target;
break;
case 8:
GuideText = (Border)target;
break;
case 9:
SizeLabel = (Border)target;
break;
case 10:
SizeLabelText = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,190 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Markup;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using AxCopilot.Models;
using AxCopilot.Services;
namespace AxCopilot.Views;
public class ReminderPopupWindow : Window, IComponentConnector
{
private const int GWL_EXSTYLE = -20;
private const int WS_EX_NOACTIVATE = 134217728;
private const int WS_EX_TOOLWINDOW = 128;
private readonly DispatcherTimer _timer;
private readonly EventHandler _tickHandler;
private int _remaining;
internal Border PopupBorder;
internal TextBlock UsageText;
internal Button CloseBtn;
internal TextBlock QuoteText;
internal TextBlock AuthorText;
internal ProgressBar CountdownBar;
private bool _contentLoaded;
[DllImport("user32.dll")]
private static extern nint GetWindowLongPtr(nint hwnd, int nIndex);
[DllImport("user32.dll")]
private static extern nint SetWindowLongPtr(nint hwnd, int nIndex, nint dwNewLong);
public ReminderPopupWindow(string quoteText, string? author, TimeSpan todayUsage, SettingsService settings)
{
//IL_017d: Unknown result type (might be due to invalid IL or missing references)
//IL_0182: Unknown result type (might be due to invalid IL or missing references)
//IL_019c: Expected O, but got Unknown
InitializeComponent();
ReminderSettings cfg = settings.Settings.Reminder;
QuoteText.Text = quoteText;
if (!string.IsNullOrWhiteSpace(author))
{
AuthorText.Text = "— " + author;
AuthorText.Visibility = Visibility.Visible;
}
int num = (int)todayUsage.TotalHours;
int minutes = todayUsage.Minutes;
UsageText.Text = ((num > 0) ? $"오늘 총 {num}시간 {minutes}분 근무 중" : ((minutes >= 1) ? $"오늘 총 {minutes}분 근무 중" : "오늘 방금 시작했습니다"));
_remaining = Math.Max(3, cfg.DisplaySeconds);
CountdownBar.Maximum = _remaining;
CountdownBar.Value = _remaining;
base.Loaded += delegate
{
SetNoActivate();
PositionWindow(cfg.Corner);
AnimateIn();
};
_tickHandler = delegate
{
_remaining--;
CountdownBar.Value = _remaining;
if (_remaining <= 0)
{
Close();
}
};
_timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1.0)
};
_timer.Tick += _tickHandler;
_timer.Start();
base.KeyDown += delegate(object _, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Invalid comparison between Unknown and I4
if ((int)e.Key == 13)
{
Close();
}
};
}
protected override void OnSourceInitialized(EventArgs e)
{
base.OnSourceInitialized(e);
SetNoActivate();
}
private void SetNoActivate()
{
nint handle = new WindowInteropHelper(this).Handle;
if (handle != IntPtr.Zero)
{
long num = GetWindowLongPtr(handle, -20);
SetWindowLongPtr(handle, -20, (nint)(num | 0x8000000 | 0x80));
}
}
private void PositionWindow(string corner)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
Rect workArea = SystemParameters.WorkArea;
base.Left = (corner.Contains("left") ? (((Rect)(ref workArea)).Left + 20.0) : (((Rect)(ref workArea)).Right - base.ActualWidth - 20.0));
base.Top = (corner.Contains("top") ? (((Rect)(ref workArea)).Top + 20.0) : (((Rect)(ref workArea)).Bottom - base.ActualHeight - 20.0));
}
private void AnimateIn()
{
base.Opacity = 0.0;
DoubleAnimation animation = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(280.0));
BeginAnimation(UIElement.OpacityProperty, animation);
}
private void CloseBtn_Click(object sender, RoutedEventArgs e)
{
Close();
}
protected override void OnClosed(EventArgs e)
{
_timer.Stop();
_timer.Tick -= _tickHandler;
base.OnClosed(e);
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/reminderpopupwindow.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:
PopupBorder = (Border)target;
break;
case 2:
UsageText = (TextBlock)target;
break;
case 3:
CloseBtn = (Button)target;
CloseBtn.Click += CloseBtn_Click;
break;
case 4:
QuoteText = (TextBlock)target;
break;
case 5:
AuthorText = (TextBlock)target;
break;
case 6:
CountdownBar = (ProgressBar)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,546 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
using Microsoft.Win32;
namespace AxCopilot.Views;
public class ResourceMonitorWindow : Window, IComponentConnector
{
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
private struct MEMORYSTATUSEX
{
public uint dwLength;
public uint dwMemoryLoad;
public ulong ullTotalPhys;
public ulong ullAvailPhys;
public ulong ullTotalPageFile;
public ulong ullAvailPageFile;
public ulong ullTotalVirtual;
public ulong ullAvailVirtual;
public ulong ullAvailExtendedVirtual;
}
public sealed class DriveDisplayItem : INotifyPropertyChanged
{
private string _label = "";
private string _detail = "";
private double _barWidth = 0.0;
private Brush _barColor = Brushes.Green;
public string Label
{
get
{
return _label;
}
set
{
_label = value;
OnPropertyChanged("Label");
}
}
public string Detail
{
get
{
return _detail;
}
set
{
_detail = value;
OnPropertyChanged("Detail");
}
}
public double BarWidth
{
get
{
return _barWidth;
}
set
{
_barWidth = value;
OnPropertyChanged("BarWidth");
}
}
public Brush BarColor
{
get
{
return _barColor;
}
set
{
_barColor = value;
OnPropertyChanged("BarColor");
}
}
public ICommand OpenCommand { get; init; } = null;
public event PropertyChangedEventHandler? PropertyChanged;
private void OnPropertyChanged([CallerMemberName] string? n = null)
{
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(n));
}
}
public sealed class ProcessDisplayItem
{
public string Rank { get; init; } = "";
public string Name { get; init; } = "";
public string MemText { get; init; } = "";
public double BarWidth { get; init; }
}
private sealed class RelayCommand(Action execute) : ICommand
{
public event EventHandler? CanExecuteChanged
{
add
{
}
remove
{
}
}
public bool CanExecute(object? _)
{
return true;
}
public void Execute(object? _)
{
execute();
}
}
private const int WM_NCLBUTTONDOWN = 161;
private const int HTBOTTOMRIGHT = 17;
private readonly DispatcherTimer _timer;
private static PerformanceCounter? _cpuCounter;
private static float _cpuCached;
private static DateTime _cpuUpdated = DateTime.MinValue;
private readonly ObservableCollection<DriveDisplayItem> _drives = new ObservableCollection<DriveDisplayItem>();
private const double MaxBarWidth = 160.0;
internal TextBlock RefreshLabel;
internal TextBlock CpuValueText;
internal Border CpuBar;
internal TextBlock CpuNameText;
internal TextBlock RamValueText;
internal Border RamBar;
internal TextBlock RamDetailText;
internal ItemsControl DriveList;
internal ItemsControl ProcessList;
internal TextBlock UptimeText;
private bool _contentLoaded;
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
[DllImport("user32.dll")]
private static extern void ReleaseCapture();
[DllImport("user32.dll")]
private static extern nint SendMessage(nint hWnd, int msg, nint wParam, nint lParam);
public ResourceMonitorWindow()
{
//IL_006f: Unknown result type (might be due to invalid IL or missing references)
//IL_0074: Unknown result type (might be due to invalid IL or missing references)
//IL_008e: Expected O, but got Unknown
InitializeComponent();
DriveList.ItemsSource = _drives;
if (_cpuCounter == null)
{
try
{
_cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total");
_cpuCounter.NextValue();
}
catch
{
}
}
InitDrives();
_timer = new DispatcherTimer
{
Interval = TimeSpan.FromSeconds(1.0)
};
_timer.Tick += delegate
{
Refresh();
};
_timer.Start();
Refresh();
}
private void InitDrives()
{
_drives.Clear();
foreach (DriveInfo item in from d in DriveInfo.GetDrives()
where d.IsReady && d.DriveType == DriveType.Fixed
select d)
{
string root = item.RootDirectory.FullName;
_drives.Add(new DriveDisplayItem
{
OpenCommand = new RelayCommand(delegate
{
try
{
Process.Start(new ProcessStartInfo("explorer.exe", root)
{
UseShellExecute = true
});
}
catch
{
}
})
});
}
}
private void Refresh()
{
RefreshCpu();
RefreshRam();
RefreshDrives();
RefreshProcesses();
RefreshUptime();
}
private void RefreshCpu()
{
try
{
if (_cpuCounter == null)
{
CpuValueText.Text = "—";
return;
}
if ((DateTime.Now - _cpuUpdated).TotalMilliseconds > 800.0)
{
_cpuCached = _cpuCounter.NextValue();
_cpuUpdated = DateTime.Now;
}
int num = (int)Math.Clamp(_cpuCached, 0f, 100f);
CpuValueText.Text = $"{num}%";
SolidColorBrush solidColorBrush = ((num > 80) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((num > 50) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(75, 158, 252))));
CpuValueText.Foreground = solidColorBrush;
CpuBar.Background = solidColorBrush;
Border cpuBar = CpuBar;
FrameworkElement obj = CpuBar.Parent as FrameworkElement;
cpuBar.Width = ((obj != null) ? (obj.ActualWidth * (double)num / 100.0) : 0.0);
if (string.IsNullOrEmpty(CpuNameText.Text))
{
CpuNameText.Text = GetProcessorName();
}
}
catch
{
CpuValueText.Text = "—";
}
}
private void RefreshRam()
{
MEMORYSTATUSEX lpBuffer = new MEMORYSTATUSEX
{
dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>()
};
if (GlobalMemoryStatusEx(ref lpBuffer))
{
double value = (double)lpBuffer.ullTotalPhys / 1024.0 / 1024.0 / 1024.0;
double value2 = (double)(lpBuffer.ullTotalPhys - lpBuffer.ullAvailPhys) / 1024.0 / 1024.0 / 1024.0;
double value3 = (double)lpBuffer.ullAvailPhys / 1024.0 / 1024.0 / 1024.0;
int dwMemoryLoad = (int)lpBuffer.dwMemoryLoad;
RamValueText.Text = $"{dwMemoryLoad}%";
RamDetailText.Text = $"사용: {value2:F1} GB / 전체: {value:F1} GB / 여유: {value3:F1} GB";
Border ramBar = RamBar;
FrameworkElement obj = RamBar.Parent as FrameworkElement;
ramBar.Width = ((obj != null) ? (obj.ActualWidth * (double)dwMemoryLoad / 100.0) : 0.0);
SolidColorBrush solidColorBrush = ((dwMemoryLoad > 85) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((dwMemoryLoad > 65) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(124, 58, 237))));
RamValueText.Foreground = solidColorBrush;
RamBar.Background = solidColorBrush;
}
}
private void RefreshDrives()
{
List<DriveInfo> list = (from d in DriveInfo.GetDrives()
where d.IsReady && d.DriveType == DriveType.Fixed
select d).ToList();
if (list.Count != _drives.Count)
{
InitDrives();
}
for (int num = 0; num < list.Count && num < _drives.Count; num++)
{
DriveInfo driveInfo = list[num];
double num2 = (double)driveInfo.TotalSize / 1024.0 / 1024.0 / 1024.0;
double num3 = (double)driveInfo.AvailableFreeSpace / 1024.0 / 1024.0 / 1024.0;
double num4 = num2 - num3;
int num5 = (int)(num4 / num2 * 100.0);
string label = (string.IsNullOrWhiteSpace(driveInfo.VolumeLabel) ? driveInfo.Name.TrimEnd('\\') : (driveInfo.Name.TrimEnd('\\') + " (" + driveInfo.VolumeLabel + ")"));
_drives[num].Label = label;
_drives[num].Detail = $"{num3:F1}GB 여유";
_drives[num].BarWidth = 160.0 * (double)num5 / 100.0;
_drives[num].BarColor = ((num5 > 90) ? new SolidColorBrush(Color.FromRgb(220, 38, 38)) : ((num5 > 75) ? new SolidColorBrush(Color.FromRgb(217, 119, 6)) : new SolidColorBrush(Color.FromRgb(5, 150, 105))));
}
}
private void RefreshProcesses()
{
try
{
List<Process> list = Process.GetProcesses().OrderByDescending(delegate(Process p)
{
try
{
return p.WorkingSet64;
}
catch
{
return 0L;
}
}).Take(7)
.ToList();
long maxMem = ((list.Count <= 0) ? 1 : ((list[0].WorkingSet64 > 0) ? list[0].WorkingSet64 : 1));
List<ProcessDisplayItem> itemsSource = list.Select(delegate(Process p, int i)
{
long num = 0L;
string text = "";
try
{
num = p.WorkingSet64;
text = p.ProcessName;
}
catch
{
text = "—";
}
double num2 = (double)num / 1024.0 / 1024.0;
return new ProcessDisplayItem
{
Rank = $"{i + 1}",
Name = text,
MemText = ((num2 > 1024.0) ? $"{num2 / 1024.0:F1} GB" : $"{num2:F0} MB"),
BarWidth = Math.Max(2.0, 46.0 * (double)num / (double)maxMem)
};
}).ToList();
ProcessList.ItemsSource = itemsSource;
}
catch
{
}
}
private void RefreshUptime()
{
TimeSpan timeSpan = TimeSpan.FromMilliseconds(Environment.TickCount64);
int num = (int)timeSpan.TotalDays;
int hours = timeSpan.Hours;
int minutes = timeSpan.Minutes;
UptimeText.Text = ((num > 0) ? $"가동: {num}일 {hours}시간 {minutes}분" : ((hours > 0) ? $"가동: {hours}시간 {minutes}분" : $"가동: {minutes}분 {timeSpan.Seconds}초"));
}
private void ResizeGrip_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Pressed)
{
ReleaseCapture();
SendMessage(new WindowInteropHelper(this).Handle, 161, 17, IntPtr.Zero);
}
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void Window_KeyDown(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
if ((int)e.Key == 13)
{
Close();
}
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
}
protected override void OnMouseWheel(MouseWheelEventArgs e)
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Invalid comparison between Unknown and I4
if ((int)Keyboard.Modifiers == 2)
{
int num = ((e.Delta > 0) ? 40 : (-40));
double num2 = base.Height + (double)num;
if (num2 >= base.MinHeight && num2 <= 900.0)
{
base.Height = num2;
}
e.Handled = true;
}
else
{
base.OnMouseWheel(e);
}
}
protected override void OnClosed(EventArgs e)
{
_timer.Stop();
base.OnClosed(e);
}
private static string GetProcessorName()
{
try
{
using RegistryKey registryKey = Registry.LocalMachine.OpenSubKey("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0");
return (registryKey?.GetValue("ProcessorNameString") as string) ?? "";
}
catch
{
return "";
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/resourcemonitorwindow.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:
((ResourceMonitorWindow)target).MouseDown += Window_MouseDown;
((ResourceMonitorWindow)target).KeyDown += Window_KeyDown;
break;
case 2:
RefreshLabel = (TextBlock)target;
break;
case 3:
((Button)target).Click += Close_Click;
break;
case 4:
CpuValueText = (TextBlock)target;
break;
case 5:
CpuBar = (Border)target;
break;
case 6:
CpuNameText = (TextBlock)target;
break;
case 7:
RamValueText = (TextBlock)target;
break;
case 8:
RamBar = (Border)target;
break;
case 9:
RamDetailText = (TextBlock)target;
break;
case 10:
DriveList = (ItemsControl)target;
break;
case 11:
ProcessList = (ItemsControl)target;
break;
case 12:
((Border)target).MouseLeftButtonDown += ResizeGrip_MouseLeftButtonDown;
break;
case 13:
UptimeText = (TextBlock)target;
break;
case 14:
((Button)target).Click += Close_Click;
break;
default:
_contentLoaded = true;
break;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,322 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Markup;
using System.Windows.Media;
using AxCopilot.Services;
namespace AxCopilot.Views;
public class ShortcutHelpWindow : Window, IComponentConnector
{
private record ShortcutRow(string Key, string Description, string Icon = "\ue72d", string Color = "#4B5EFC");
private const int WM_NCLBUTTONDOWN = 161;
private const int HTBOTTOMRIGHT = 17;
internal ItemsControl NavigationItems;
internal ItemsControl FileActionItems;
internal ItemsControl ViewItems;
internal ItemsControl RunItems;
internal ItemsControl PrefixItems;
internal CheckBox ThemeColorChk;
private bool _contentLoaded;
[DllImport("user32.dll")]
private static extern void ReleaseCapture();
[DllImport("user32.dll")]
private static extern nint SendMessage(nint hWnd, int msg, nint wParam, nint lParam);
public ShortcutHelpWindow()
{
InitializeComponent();
base.Loaded += delegate
{
SettingsService settingsService = (Application.Current as App)?.SettingsService;
if (settingsService != null)
{
ThemeColorChk.IsChecked = settingsService.Settings.Launcher.ShortcutHelpUseThemeColor;
}
BuildItems();
};
}
private void BuildItems()
{
bool valueOrDefault = ThemeColorChk.IsChecked == true;
ShortcutRow[] rows = new ShortcutRow[6]
{
new ShortcutRow("↑ / ↓", "결과 목록 위/아래로 이동", "\ue74a"),
new ShortcutRow("PageUp / PageDown", "목록 5칸 빠른 이동", "\ue74a"),
new ShortcutRow("Home / End", "목록 처음 항목 / 마지막 항목으로 점프", "\ue74a"),
new ShortcutRow("Tab", "선택 항목 제목을 입력창에 자동 완성", "\ue748", "#7B68EE"),
new ShortcutRow("→", "파일/앱 선택 시 액션 모드(복사·실행 등) 진입", "\ue76c", "#107C10"),
new ShortcutRow("Escape", "액션 모드면 일반 모드로 복귀, 아니면 AX Commander 닫기", "\ue711", "#C50F1F")
};
ShortcutRow[] rows2 = new ShortcutRow[10]
{
new ShortcutRow("Enter", "선택 항목 실행 (파일 열기·명령 실행·URL 열기 등)", "\ue768", "#107C10"),
new ShortcutRow("Ctrl+Enter", "선택 파일·앱을 관리자(UAC 상승) 권한으로 실행", "\ue7ef", "#C50F1F"),
new ShortcutRow("Alt+Enter", "선택 항목의 Windows 속성 대화 상자 열기", "\ue7ee", "#8B2FC9"),
new ShortcutRow("Ctrl+C", "선택 항목의 파일 이름(확장자 제외)을 클립보드에 복사", "\ue8c8", "#0078D4"),
new ShortcutRow("Ctrl+Shift+C", "선택 항목의 전체 경로를 클립보드에 복사", "\ue8c8", "#0078D4"),
new ShortcutRow("Ctrl+Shift+E", "파일 탐색기를 열고 선택 항목 위치를 하이라이트", "\ue8da", "#107C10"),
new ShortcutRow("Ctrl+T", "선택 항목 폴더 경로에서 터미널(wt/cmd) 열기", "\ue756", "#323130"),
new ShortcutRow("Ctrl+P", "선택 항목을 즐겨찾기에 추가 (이미 있으면 제거)", "\ue734", "#D97706"),
new ShortcutRow("F2", "선택 파일·폴더의 이름 변경 모드로 전환", "\ue70f", "#6B2C91"),
new ShortcutRow("Delete", "선택 항목을 최근 목록에서 제거 (확인 후 실행)", "\ue74d", "#C50F1F")
};
ShortcutRow[] rows3 = new ShortcutRow[6]
{
new ShortcutRow("Ctrl+B", "즐겨찾기 목록 보기 (다시 누르면 닫기, 토글)", "\ue735", "#D97706"),
new ShortcutRow("Ctrl+R", "최근 실행 목록 보기 (다시 누르면 닫기, 토글)", "\ue81c", "#0078D4"),
new ShortcutRow("Ctrl+H", "클립보드 히스토리 목록 보기", "\ue77f", "#8B2FC9"),
new ShortcutRow("Ctrl+D", "다운로드 폴더 경로 바로 열기", "\ue8b7", "#107C10"),
new ShortcutRow("Ctrl+F", "입력 초기화 후 파일 검색 모드로 포커스 이동", "\ue71e"),
new ShortcutRow("F1", "헬프 화면 열기 (help 입력과 동일)", "\ue897")
};
ShortcutRow[] rows4 = new ShortcutRow[7]
{
new ShortcutRow("Ctrl+1 ~ Ctrl+9", "표시 중인 N번째 결과를 즉시 실행 (번호 배지와 연동)", "\ue8c4", "#107C10"),
new ShortcutRow("Ctrl+L", "입력창 전체 초기화", "\ue711", "#9999BB"),
new ShortcutRow("Ctrl+W", "AX Commander 창 즉시 닫기", "\ue711", "#9999BB"),
new ShortcutRow("Ctrl+K", "이 단축키 참조 창 열기", "\ue8fd"),
new ShortcutRow("Ctrl+,", "설정 창 열기", "\ue713"),
new ShortcutRow("F5", "파일 인덱스 즉시 재구축", "\ue72c", "#107C10"),
new ShortcutRow("Shift+Enter", "Large Type / 병합 실행 / 캡처 모드: 지연 캡처(3/5/10초) 타이머", "\ue8a7", "#7B68EE")
};
ShortcutRow[] rows5 = new ShortcutRow[9]
{
new ShortcutRow("cd [경로/별칭]", "지정한 경로 또는 등록된 폴더 별칭을 탐색기로 열기", "\ue8da", "#107C10"),
new ShortcutRow("~ [이름]", "워크스페이스 저장(save)/복원(restore)/목록(list)", "\ue8b7", "#C50F1F"),
new ShortcutRow("# [검색어]", "클립보드 히스토리 검색·붙여넣기", "\ue77f", "#8B2FC9"),
new ShortcutRow("fav [검색어]", "즐겨찾기 목록 검색 및 열기. add/del 로 관리", "\ue735", "#D97706"),
new ShortcutRow("recent [검색어]", "최근 실행 항목 검색", "\ue81c", "#0078D4"),
new ShortcutRow("cap [모드]", "화면 캡처 (region/window/scroll/screen) · Shift+Enter: 지연 캡처", "\ue722", "#C09010"),
new ShortcutRow("help [검색어]", "도움말 및 기능 목록 검색", "\ue897"),
new ShortcutRow("/ [명령]", "시스템 명령 (lock/sleep/restart/shutdown 등)", "\ue7e8", "#C50F1F"),
new ShortcutRow("! [질문]", "AX Agent — Ollama/vLLM/Gemini/Claude", "\ue8bd", "#8B2FC9")
};
NavigationItems.Items.Clear();
FileActionItems.Items.Clear();
ViewItems.Items.Clear();
RunItems.Items.Clear();
PrefixItems.Items.Clear();
Populate(NavigationItems, rows, valueOrDefault);
Populate(FileActionItems, rows2, valueOrDefault);
Populate(ViewItems, rows3, valueOrDefault);
Populate(RunItems, rows4, valueOrDefault);
Populate(PrefixItems, rows5, valueOrDefault);
}
private static void Populate(ItemsControl control, ShortcutRow[] rows, bool useThemeColor)
{
Brush foreground = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? new SolidColorBrush(Color.FromRgb(51, 51, 85));
Brush background = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(238, 238, byte.MaxValue));
string text = ((Application.Current.TryFindResource("AccentColor") is SolidColorBrush solidColorBrush) ? $"#{solidColorBrush.Color.R:X2}{solidColorBrush.Color.G:X2}{solidColorBrush.Color.B:X2}" : "#4B5EFC");
foreach (ShortcutRow shortcutRow in rows)
{
string text2 = (useThemeColor ? text : shortcutRow.Color);
Grid grid = new Grid
{
Margin = new Thickness(0.0, 0.0, 0.0, 3.0)
};
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(28.0)
});
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(148.0)
});
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1.0, GridUnitType.Star)
});
Border border = new Border
{
Width = 22.0,
Height = 22.0,
CornerRadius = new CornerRadius(5.0),
Background = ParseBrush(text2 + "22"),
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Center
};
border.Child = new TextBlock
{
Text = shortcutRow.Icon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 10.0,
Foreground = ParseBrush(text2),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
Grid.SetColumn(border, 0);
grid.Children.Add(border);
Border border2 = new Border
{
Background = background,
CornerRadius = new CornerRadius(5.0),
Padding = new Thickness(7.0, 3.0, 7.0, 3.0),
Margin = new Thickness(4.0, 1.0, 8.0, 1.0),
VerticalAlignment = VerticalAlignment.Center,
HorizontalAlignment = HorizontalAlignment.Left
};
border2.Child = new TextBlock
{
Text = shortcutRow.Key,
FontFamily = new FontFamily("Consolas, Courier New"),
FontSize = 11.0,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center
};
Grid.SetColumn(border2, 1);
grid.Children.Add(border2);
TextBlock element = new TextBlock
{
Text = shortcutRow.Description,
FontSize = 11.5,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center,
TextWrapping = TextWrapping.Wrap,
LineHeight = 16.0
};
Grid.SetColumn(element, 2);
grid.Children.Add(element);
control.Items.Add(grid);
}
}
private static SolidColorBrush ParseBrush(string hex)
{
try
{
return new SolidColorBrush((Color)ColorConverter.ConvertFromString(hex));
}
catch
{
return new SolidColorBrush(Colors.Transparent);
}
}
private void ThemeColorChk_Changed(object sender, RoutedEventArgs e)
{
SettingsService settingsService = (Application.Current as App)?.SettingsService;
if (settingsService != null)
{
settingsService.Settings.Launcher.ShortcutHelpUseThemeColor = ThemeColorChk.IsChecked == true;
settingsService.Save();
}
BuildItems();
}
private void ResizeGrip_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Pressed)
{
ReleaseCapture();
SendMessage(new WindowInteropHelper(this).Handle, 161, 17, IntPtr.Zero);
}
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void Window_KeyDown(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
if ((int)e.Key == 13)
{
Close();
}
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/shortcuthelpwindow.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:
((ShortcutHelpWindow)target).KeyDown += Window_KeyDown;
((ShortcutHelpWindow)target).MouseDown += Window_MouseDown;
break;
case 2:
((Button)target).Click += Close_Click;
break;
case 3:
NavigationItems = (ItemsControl)target;
break;
case 4:
FileActionItems = (ItemsControl)target;
break;
case 5:
ViewItems = (ItemsControl)target;
break;
case 6:
RunItems = (ItemsControl)target;
break;
case 7:
PrefixItems = (ItemsControl)target;
break;
case 8:
((Border)target).MouseLeftButtonDown += ResizeGrip_MouseLeftButtonDown;
break;
case 9:
ThemeColorChk = (CheckBox)target;
ThemeColorChk.Checked += ThemeColorChk_Changed;
ThemeColorChk.Unchecked += ThemeColorChk_Changed;
break;
case 10:
((Button)target).Click += Close_Click;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,629 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Effects;
using AxCopilot.Services;
using AxCopilot.Services.Agent;
namespace AxCopilot.Views;
public class SkillEditorWindow : Window, IComponentConnector
{
private static readonly string[] IconCandidates = new string[20]
{
"\ue70f", "\ue8a5", "\ue943", "\ue74c", "\ue8b7", "\ue896", "\ue713", "\ue753", "\ue774", "\ue8d6",
"\ue8f1", "\ue7c3", "\ueca7", "\ue71e", "\ue8c8", "\ue8f6", "\ue81e", "\uebd2", "\ue9d9", "\ue77b"
};
private string _selectedIcon = "\ue70f";
private SkillDefinition? _editingSkill;
private readonly ToolRegistry _toolRegistry;
internal TextBlock TitleText;
internal TextBox TxtName;
internal TextBox TxtLabel;
internal TextBox TxtDescription;
internal StackPanel IconSelectorPanel;
internal ComboBox CmbRequires;
internal Border BtnInsertToolList;
internal Border BtnInsertFormat;
internal TextBox TxtInstructions;
internal StackPanel ToolCheckListPanel;
internal TextBlock PreviewTokens;
internal TextBlock PreviewFileName;
internal TextBlock StatusText;
private bool _contentLoaded;
public SkillEditorWindow()
{
InitializeComponent();
_toolRegistry = ToolRegistry.CreateDefault();
base.Loaded += delegate
{
BuildIconSelector();
BuildToolChecklist();
UpdatePreview();
};
}
public SkillEditorWindow(SkillDefinition skill)
: this()
{
SkillEditorWindow skillEditorWindow = this;
_editingSkill = skill;
base.Loaded += delegate
{
skillEditorWindow.LoadSkill(skill);
};
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
Point position = e.GetPosition(this);
if (!(((Point)(ref position)).X > base.ActualWidth - 50.0))
{
if (e.ClickCount == 2)
{
base.WindowState = ((base.WindowState != WindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
}
else
{
DragMove();
}
}
}
private void BtnClose_Click(object sender, MouseButtonEventArgs e)
{
Close();
}
private void BtnCancel_Click(object sender, MouseButtonEventArgs e)
{
Close();
}
private void BuildIconSelector()
{
IconSelectorPanel.Children.Clear();
SolidColorBrush solidColorBrush = new SolidColorBrush(Color.FromRgb(75, 94, 252));
Brush brush = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush bgBrush = (TryFindResource("ItemBackground") as Brush) ?? Brushes.Transparent;
string[] iconCandidates = IconCandidates;
foreach (string text in iconCandidates)
{
bool flag = text == _selectedIcon;
Border border = new Border
{
Width = 34.0,
Height = 34.0,
CornerRadius = new CornerRadius(8.0),
Margin = new Thickness(0.0, 0.0, 4.0, 4.0),
Cursor = Cursors.Hand,
Background = (flag ? solidColorBrush : bgBrush),
BorderBrush = (flag ? solidColorBrush : Brushes.Transparent),
BorderThickness = new Thickness(1.5),
Tag = text
};
border.Child = new TextBlock
{
Text = text,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 14.0,
Foreground = (flag ? Brushes.White : brush),
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
border.MouseLeftButtonUp += delegate(object s, MouseButtonEventArgs _)
{
if (s is Border { Tag: string tag })
{
_selectedIcon = tag;
BuildIconSelector();
}
};
string capturedIcon = text;
border.MouseEnter += delegate(object s, MouseEventArgs _)
{
if (s is Border border2 && capturedIcon != _selectedIcon)
{
border2.Background = new SolidColorBrush(Color.FromArgb(48, 75, 94, 252));
}
};
border.MouseLeave += delegate(object s, MouseEventArgs _)
{
if (s is Border border2 && capturedIcon != _selectedIcon)
{
border2.Background = bgBrush;
}
};
IconSelectorPanel.Children.Add(border);
}
}
private void BuildToolChecklist()
{
ToolCheckListPanel.Children.Clear();
List<IAgentTool> list = _toolRegistry.All.OrderBy((IAgentTool t) => t.Name).ToList();
Brush foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush brush = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
if (_editingSkill != null && !string.IsNullOrWhiteSpace(_editingSkill.AllowedTools))
{
string[] array = _editingSkill.AllowedTools.Split(',', StringSplitOptions.RemoveEmptyEntries);
foreach (string text in array)
{
hashSet.Add(text.Trim());
}
}
foreach (IAgentTool item in list)
{
CheckBox checkBox = new CheckBox();
checkBox.Tag = item.Name;
checkBox.IsChecked = hashSet.Count == 0 || hashSet.Contains(item.Name);
checkBox.Margin = new Thickness(0.0, 0.0, 0.0, 4.0);
checkBox.Style = TryFindResource("ToggleSwitch") as Style;
CheckBox element = checkBox;
StackPanel stackPanel = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 2.0)
};
stackPanel.Children.Add(element);
stackPanel.Children.Add(new TextBlock
{
Text = item.Name,
FontSize = 11.5,
FontFamily = new FontFamily("Consolas"),
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(6.0, 0.0, 0.0, 0.0)
});
if (!string.IsNullOrEmpty(item.Description))
{
stackPanel.ToolTip = item.Description;
}
ToolCheckListPanel.Children.Add(stackPanel);
}
}
private List<string> GetCheckedTools()
{
List<string> list = new List<string>();
foreach (object child in ToolCheckListPanel.Children)
{
if (child is StackPanel stackPanel && stackPanel.Children.Count > 0 && stackPanel.Children[0] is CheckBox { IsChecked: var isChecked } checkBox && isChecked == true && checkBox.Tag is string item)
{
list.Add(item);
}
}
return list;
}
private void BtnInsertTemplate_Click(object sender, MouseButtonEventArgs e)
{
if (sender is FrameworkElement { Tag: string tag })
{
if (1 == 0)
{
}
string text = tag switch
{
"tools" => BuildToolListTemplate(),
"format" => "## 출력 형식\n\n1. 결과를 사용자에게 한국어로 설명합니다.\n2. 코드 블록은 마크다운 형식으로 감쌉니다.\n3. 핵심 정보를 먼저 제시하고, 세부 사항은 뒤에 붙입니다.",
"steps" => "## 실행 단계\n\n1. **분석**: 사용자의 요청을 분석합니다.\n2. **계획**: 수행할 작업을 계획합니다.\n3. **실행**: 도구를 사용하여 작업을 수행합니다.\n4. **검증**: 결과를 검증합니다.\n5. **보고**: 결과를 사용자에게 보고합니다.",
_ => "",
};
if (1 == 0)
{
}
string text2 = text;
if (!string.IsNullOrEmpty(text2))
{
int caretIndex = TxtInstructions.CaretIndex;
string text3 = ((caretIndex > 0 && TxtInstructions.Text.Length > 0 && TxtInstructions.Text[caretIndex - 1] != '\n') ? "\n\n" : "");
TxtInstructions.Text = TxtInstructions.Text.Insert(caretIndex, text3 + text2.Trim());
TxtInstructions.CaretIndex = caretIndex + text3.Length + text2.Trim().Length;
TxtInstructions.Focus();
}
}
}
private string BuildToolListTemplate()
{
List<string> checkedTools = GetCheckedTools();
if (checkedTools.Count == 0)
{
return "## 사용 가능한 도구\n\n(도구가 선택되지 않았습니다. 우측 패널에서 도구를 선택하세요.)";
}
List<string> list = new List<string> { "## 사용 가능한 도구", "" };
foreach (string toolName in checkedTools)
{
IAgentTool agentTool = _toolRegistry.All.FirstOrDefault((IAgentTool t) => t.Name == toolName);
if (agentTool != null)
{
list.Add("- **" + agentTool.Name + "**: " + agentTool.Description);
}
}
return string.Join("\n", list);
}
private void TxtInstructions_TextChanged(object sender, TextChangedEventArgs e)
{
UpdatePreview();
}
private void UpdatePreview()
{
if (PreviewTokens != null && PreviewFileName != null)
{
string text = GenerateSkillContent();
int value = TokenEstimator.Estimate(text);
PreviewTokens.Text = $"예상 토큰: ~{value:N0}자 | {text.Length:N0}자";
string text2 = (string.IsNullOrWhiteSpace(TxtName?.Text) ? "new-skill" : TxtName.Text.Trim());
PreviewFileName.Text = text2 + ".skill.md";
}
}
private string GenerateSkillContent()
{
string text = TxtName?.Text?.Trim() ?? "new-skill";
string text2 = TxtLabel?.Text?.Trim() ?? "";
string text3 = TxtDescription?.Text?.Trim() ?? "";
string text4 = TxtInstructions?.Text ?? "";
string text5 = "";
if (CmbRequires?.SelectedItem is ComboBoxItem { Tag: string tag } && !string.IsNullOrEmpty(tag))
{
text5 = tag;
}
List<string> checkedTools = GetCheckedTools();
int count = _toolRegistry.All.Count;
string text6 = ((checkedTools.Count < count) ? string.Join(", ", checkedTools) : "");
List<string> list = new List<string> { "---" };
list.Add("name: " + text);
if (!string.IsNullOrEmpty(text2))
{
list.Add("label: " + text2);
}
if (!string.IsNullOrEmpty(text3))
{
list.Add("description: " + text3);
}
list.Add("icon: " + _selectedIcon);
if (!string.IsNullOrEmpty(text5))
{
list.Add("requires: " + text5);
}
if (!string.IsNullOrEmpty(text6))
{
list.Add("allowed-tools: " + text6);
}
list.Add("---");
list.Add("");
return string.Join("\n", list) + text4;
}
private void BtnPreview_Click(object sender, MouseButtonEventArgs e)
{
string text = GenerateSkillContent();
Window previewWin = new Window
{
Title = "스킬 파일 미리보기",
Width = 640.0,
Height = 520.0,
WindowStyle = WindowStyle.None,
AllowsTransparency = true,
Background = Brushes.Transparent,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Owner = this
};
Brush background = (TryFindResource("LauncherBackground") as Brush) ?? Brushes.White;
Brush foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush itemBg = (TryFindResource("ItemBackground") as Brush) ?? Brushes.Transparent;
Brush borderBrush = (TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(12.0),
BorderBrush = borderBrush,
BorderThickness = new Thickness(1.0),
Effect = new DropShadowEffect
{
BlurRadius = 20.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = Colors.Black
}
};
Grid grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(44.0)
});
grid.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(1.0, GridUnitType.Star)
});
grid.RowDefinitions.Add(new RowDefinition
{
Height = GridLength.Auto
});
Border border2 = new Border
{
Background = itemBg,
CornerRadius = new CornerRadius(12.0, 12.0, 0.0, 0.0)
};
border2.MouseLeftButtonDown += delegate
{
previewWin.DragMove();
};
TextBlock child = new TextBlock
{
Text = "미리보기 — .skill.md",
FontSize = 14.0,
FontWeight = FontWeights.SemiBold,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(16.0, 0.0, 0.0, 0.0)
};
border2.Child = child;
Grid.SetRow(border2, 0);
TextBox element = new TextBox
{
Text = text,
FontFamily = new FontFamily("Consolas, Cascadia Code, Segoe UI"),
FontSize = 12.5,
IsReadOnly = true,
AcceptsReturn = true,
TextWrapping = TextWrapping.Wrap,
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
Background = itemBg,
Foreground = foreground,
BorderThickness = new Thickness(0.0),
Padding = new Thickness(16.0, 12.0, 16.0, 12.0),
Margin = new Thickness(8.0, 8.0, 8.0, 0.0)
};
Grid.SetRow(element, 1);
Border border3 = new Border
{
Padding = new Thickness(16.0, 10.0, 16.0, 10.0),
CornerRadius = new CornerRadius(0.0, 0.0, 12.0, 12.0)
};
Border border4 = new Border
{
CornerRadius = new CornerRadius(8.0),
Padding = new Thickness(18.0, 8.0, 18.0, 8.0),
Background = itemBg,
Cursor = Cursors.Hand,
HorizontalAlignment = HorizontalAlignment.Right
};
border4.Child = new TextBlock
{
Text = "닫기",
FontSize = 12.5,
Foreground = foreground2
};
border4.MouseLeftButtonUp += delegate
{
previewWin.Close();
};
border4.MouseEnter += delegate(object s, MouseEventArgs _)
{
if (s is Border border5)
{
border5.Background = new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
}
};
border4.MouseLeave += delegate(object s, MouseEventArgs _)
{
if (s is Border border5)
{
border5.Background = itemBg;
}
};
border3.Child = border4;
Grid.SetRow(border3, 2);
grid.Children.Add(border2);
grid.Children.Add(element);
grid.Children.Add(border3);
border.Child = grid;
previewWin.Content = border;
previewWin.ShowDialog();
}
private void BtnSave_Click(object sender, MouseButtonEventArgs e)
{
string text = TxtName.Text.Trim();
if (string.IsNullOrWhiteSpace(text))
{
StatusText.Text = "⚠ 이름을 입력하세요.";
StatusText.Foreground = new SolidColorBrush(Color.FromRgb(248, 113, 113));
TxtName.Focus();
return;
}
if (!Regex.IsMatch(text, "^[a-zA-Z][a-zA-Z0-9\\-]*$"))
{
StatusText.Text = "⚠ 이름은 영문으로 시작하며 영문, 숫자, 하이픈만 사용 가능합니다.";
StatusText.Foreground = new SolidColorBrush(Color.FromRgb(248, 113, 113));
TxtName.Focus();
return;
}
if (string.IsNullOrWhiteSpace(TxtInstructions.Text))
{
StatusText.Text = "⚠ 지시사항을 입력하세요.";
StatusText.Foreground = new SolidColorBrush(Color.FromRgb(248, 113, 113));
TxtInstructions.Focus();
return;
}
string contents = GenerateSkillContent();
string path;
if (_editingSkill != null)
{
path = _editingSkill.FilePath;
}
else
{
string text2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "skills");
if (!Directory.Exists(text2))
{
Directory.CreateDirectory(text2);
}
path = Path.Combine(text2, text + ".skill.md");
if (File.Exists(path))
{
int num = 2;
while (File.Exists(Path.Combine(text2, $"{text}_{num}.skill.md")))
{
num++;
}
path = Path.Combine(text2, $"{text}_{num}.skill.md");
}
}
try
{
File.WriteAllText(path, contents, Encoding.UTF8);
SkillService.LoadSkills();
StatusText.Text = "✓ 저장 완료: " + Path.GetFileName(path);
StatusText.Foreground = new SolidColorBrush(Color.FromRgb(52, 211, 153));
base.DialogResult = true;
}
catch (Exception ex)
{
CustomMessageBox.Show("저장 실패: " + ex.Message, "스킬 저장");
}
}
private void LoadSkill(SkillDefinition skill)
{
TitleText.Text = "스킬 편집";
TxtName.Text = skill.Name;
TxtLabel.Text = skill.Label;
TxtDescription.Text = skill.Description;
TxtInstructions.Text = skill.SystemPrompt;
_selectedIcon = (IconCandidates.Contains(skill.Icon) ? skill.Icon : IconCandidates[0]);
BuildIconSelector();
for (int i = 0; i < CmbRequires.Items.Count; i++)
{
if (CmbRequires.Items[i] is ComboBoxItem { Tag: string tag } && string.Equals(tag, skill.Requires, StringComparison.OrdinalIgnoreCase))
{
CmbRequires.SelectedIndex = i;
break;
}
}
UpdatePreview();
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/skilleditorwindow.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:
((Border)target).MouseLeftButtonDown += TitleBar_MouseLeftButtonDown;
break;
case 2:
TitleText = (TextBlock)target;
break;
case 3:
((Border)target).MouseLeftButtonUp += BtnClose_Click;
break;
case 4:
TxtName = (TextBox)target;
break;
case 5:
TxtLabel = (TextBox)target;
break;
case 6:
TxtDescription = (TextBox)target;
break;
case 7:
IconSelectorPanel = (StackPanel)target;
break;
case 8:
CmbRequires = (ComboBox)target;
break;
case 9:
BtnInsertToolList = (Border)target;
BtnInsertToolList.MouseLeftButtonUp += BtnInsertTemplate_Click;
break;
case 10:
BtnInsertFormat = (Border)target;
BtnInsertFormat.MouseLeftButtonUp += BtnInsertTemplate_Click;
break;
case 11:
((Border)target).MouseLeftButtonUp += BtnInsertTemplate_Click;
break;
case 12:
TxtInstructions = (TextBox)target;
TxtInstructions.TextChanged += TxtInstructions_TextChanged;
break;
case 13:
ToolCheckListPanel = (StackPanel)target;
break;
case 14:
PreviewTokens = (TextBlock)target;
break;
case 15:
PreviewFileName = (TextBlock)target;
break;
case 16:
StatusText = (TextBlock)target;
break;
case 17:
((Border)target).MouseLeftButtonUp += BtnCancel_Click;
break;
case 18:
((Border)target).MouseLeftButtonUp += BtnPreview_Click;
break;
case 19:
((Border)target).MouseLeftButtonUp += BtnSave_Click;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,736 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Forms;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Effects;
using AxCopilot.Services.Agent;
using Microsoft.Win32;
namespace AxCopilot.Views;
public class SkillGalleryWindow : Window, IComponentConnector
{
private string _selectedCategory = "전체";
internal Border BtnCloseGallery;
internal StackPanel CategoryFilterBar;
internal StackPanel SkillListPanel;
internal TextBlock GalleryStatus;
private bool _contentLoaded;
public SkillGalleryWindow()
{
InitializeComponent();
base.Loaded += delegate
{
BuildCategoryFilter();
RenderSkills();
};
}
private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
Point position = e.GetPosition(this);
if (!(((Point)(ref position)).X > base.ActualWidth - 160.0))
{
if (e.ClickCount == 2)
{
base.WindowState = ((base.WindowState != WindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
}
else
{
DragMove();
}
}
}
private void BtnClose_Click(object sender, MouseButtonEventArgs e)
{
Close();
}
private void BtnAddSkill_Click(object sender, MouseButtonEventArgs e)
{
SkillEditorWindow skillEditorWindow = new SkillEditorWindow
{
Owner = this
};
if (skillEditorWindow.ShowDialog() == true)
{
BuildCategoryFilter();
RenderSkills();
}
}
private void BtnImport_Click(object sender, MouseButtonEventArgs e)
{
Microsoft.Win32.OpenFileDialog openFileDialog = new Microsoft.Win32.OpenFileDialog
{
Filter = "스킬 패키지 (*.zip)|*.zip",
Title = "가져올 스킬 zip 파일을 선택하세요"
};
if (openFileDialog.ShowDialog() == true)
{
int num = SkillService.ImportSkills(openFileDialog.FileName);
if (num > 0)
{
CustomMessageBox.Show($"스킬 {num}개를 성공적으로 가져왔습니다.", "스킬 가져오기");
BuildCategoryFilter();
RenderSkills();
}
else
{
CustomMessageBox.Show("스킬 가져오기에 실패했습니다.", "스킬 가져오기");
}
}
}
private void BuildCategoryFilter()
{
CategoryFilterBar.Children.Clear();
IReadOnlyList<SkillDefinition> skills = SkillService.Skills;
List<string> list = new string[1] { "전체" }.Concat(skills.Select((SkillDefinition s) => string.IsNullOrEmpty(s.Requires) ? "내장" : "고급 (런타임)").Distinct()).ToList();
string userFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "skills");
if (skills.Any((SkillDefinition s) => s.FilePath.StartsWith(userFolder, StringComparison.OrdinalIgnoreCase)) && !list.Contains("사용자"))
{
list.Add("사용자");
}
foreach (string item in list)
{
Border border = new Border();
border.Tag = item;
border.CornerRadius = new CornerRadius(8.0);
border.Padding = new Thickness(14.0, 5.0, 14.0, 5.0);
border.Margin = new Thickness(0.0, 0.0, 6.0, 0.0);
border.Background = ((item == _selectedCategory) ? new SolidColorBrush(Color.FromRgb(75, 94, 252)) : ((TryFindResource("ItemBackground") as Brush) ?? Brushes.Transparent));
border.Cursor = System.Windows.Input.Cursors.Hand;
Border border2 = border;
border2.Child = new TextBlock
{
Text = item,
FontSize = 12.0,
FontWeight = FontWeights.SemiBold,
Foreground = ((item == _selectedCategory) ? Brushes.White : ((TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray))
};
border2.MouseLeftButtonUp += delegate(object s, MouseButtonEventArgs _)
{
if (s is Border { Tag: string tag })
{
_selectedCategory = tag;
BuildCategoryFilter();
RenderSkills();
}
};
CategoryFilterBar.Children.Add(border2);
}
}
private void RenderSkills()
{
SkillListPanel.Children.Clear();
List<SkillDefinition> list = FilterSkills(SkillService.Skills);
string userFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "skills");
foreach (SkillDefinition item in list)
{
SkillListPanel.Children.Add(BuildSkillCard(item, userFolder));
}
if (list.Count == 0)
{
SkillListPanel.Children.Add(new TextBlock
{
Text = "표시할 스킬이 없습니다.",
FontSize = 13.0,
Foreground = ((TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray),
Margin = new Thickness(0.0, 20.0, 0.0, 0.0),
HorizontalAlignment = System.Windows.HorizontalAlignment.Center
});
}
int count = SkillService.Skills.Count;
int num = SkillService.Skills.Count((SkillDefinition s) => s.IsAvailable);
GalleryStatus.Text = $"총 {count}개 스킬 | 사용 가능 {num}개 | 런타임 필요 {count - num}개";
}
private List<SkillDefinition> FilterSkills(IReadOnlyList<SkillDefinition> skills)
{
string userFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "skills");
string selectedCategory = _selectedCategory;
if (1 == 0)
{
}
List<SkillDefinition> result = selectedCategory switch
{
"내장" => skills.Where((SkillDefinition s) => string.IsNullOrEmpty(s.Requires) && !s.FilePath.StartsWith(userFolder, StringComparison.OrdinalIgnoreCase)).ToList(),
"고급 (런타임)" => skills.Where((SkillDefinition s) => !string.IsNullOrEmpty(s.Requires)).ToList(),
"사용자" => skills.Where((SkillDefinition s) => s.FilePath.StartsWith(userFolder, StringComparison.OrdinalIgnoreCase)).ToList(),
_ => skills.ToList(),
};
if (1 == 0)
{
}
return result;
}
private Border BuildSkillCard(SkillDefinition skill, string userFolder)
{
Brush bgBrush = (TryFindResource("ItemBackground") as Brush) ?? Brushes.Transparent;
Brush foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush brush = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
bool isUser = skill.FilePath.StartsWith(userFolder, StringComparison.OrdinalIgnoreCase);
bool flag = !string.IsNullOrEmpty(skill.Requires);
Border card = new Border
{
Background = bgBrush,
CornerRadius = new CornerRadius(10.0),
Padding = new Thickness(14.0, 10.0, 14.0, 10.0),
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
};
Grid grid = new Grid();
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1.0, GridUnitType.Auto)
});
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(1.0, GridUnitType.Auto)
});
Border border = new Border
{
Width = 38.0,
Height = 38.0,
CornerRadius = new CornerRadius(10.0),
Background = new SolidColorBrush(Color.FromArgb(48, 75, 94, 252)),
Margin = new Thickness(0.0, 0.0, 12.0, 0.0),
VerticalAlignment = VerticalAlignment.Center
};
border.Child = new TextBlock
{
Text = skill.Icon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 16.0,
Foreground = (skill.IsAvailable ? new SolidColorBrush(Color.FromRgb(75, 94, 252)) : brush),
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
Grid.SetColumn(border, 0);
StackPanel stackPanel = new StackPanel
{
VerticalAlignment = VerticalAlignment.Center
};
StackPanel stackPanel2 = new StackPanel
{
Orientation = System.Windows.Controls.Orientation.Horizontal,
Margin = new Thickness(0.0, 0.0, 0.0, 3.0)
};
stackPanel2.Children.Add(new TextBlock
{
Text = "/" + skill.Name,
FontSize = 13.0,
FontWeight = FontWeights.SemiBold,
FontFamily = new FontFamily("Consolas"),
Foreground = (skill.IsAvailable ? new SolidColorBrush(Color.FromRgb(75, 94, 252)) : brush),
Opacity = (skill.IsAvailable ? 1.0 : 0.6),
VerticalAlignment = VerticalAlignment.Center
});
stackPanel2.Children.Add(new TextBlock
{
Text = " " + skill.Label,
FontSize = 12.5,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center
});
if (isUser)
{
stackPanel2.Children.Add(MakeBadge("사용자", "#34D399"));
}
else if (flag)
{
stackPanel2.Children.Add(MakeBadge("고급", "#A78BFA"));
}
else
{
stackPanel2.Children.Add(MakeBadge("내장", "#9CA3AF"));
}
if (!skill.IsAvailable)
{
stackPanel2.Children.Add(MakeBadge(skill.UnavailableHint, "#F87171"));
}
stackPanel.Children.Add(stackPanel2);
stackPanel.Children.Add(new TextBlock
{
Text = skill.Description,
FontSize = 11.5,
Foreground = brush,
TextWrapping = TextWrapping.Wrap,
Opacity = (skill.IsAvailable ? 1.0 : 0.6)
});
Grid.SetColumn(stackPanel, 1);
StackPanel actions = new StackPanel
{
Orientation = System.Windows.Controls.Orientation.Horizontal,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(8.0, 0.0, 0.0, 0.0)
};
actions.Children.Add(MakeActionBtn("\ue70f", "#3B82F6", isUser ? "편집 (시각적 편집기)" : "편집 (파일 열기)", delegate
{
if (isUser)
{
SkillEditorWindow skillEditorWindow = new SkillEditorWindow(skill)
{
Owner = this
};
if (skillEditorWindow.ShowDialog() == true)
{
SkillService.LoadSkills();
BuildCategoryFilter();
RenderSkills();
}
return;
}
try
{
Process.Start(new ProcessStartInfo(skill.FilePath)
{
UseShellExecute = true
});
}
catch (Exception ex)
{
CustomMessageBox.Show("파일을 열 수 없습니다: " + ex.Message, "편집");
}
}));
actions.Children.Add(MakeActionBtn("\ue8c8", "#10B981", "복제", delegate
{
try
{
string text = Path.Combine(userFolder);
if (!Directory.Exists(text))
{
Directory.CreateDirectory(text);
}
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(skill.FilePath);
string text2 = Path.Combine(text, fileNameWithoutExtension + "_copy.skill.md");
int num = 2;
while (File.Exists(text2))
{
text2 = Path.Combine(text, $"{fileNameWithoutExtension}_copy{num++}.skill.md");
}
File.Copy(skill.FilePath, text2);
SkillService.LoadSkills();
BuildCategoryFilter();
RenderSkills();
}
catch (Exception ex)
{
CustomMessageBox.Show("복제 실패: " + ex.Message, "복제");
}
}));
actions.Children.Add(MakeActionBtn("\uede1", "#F59E0B", "내보내기 (.zip)", delegate
{
FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog
{
Description = "내보낼 폴더를 선택하세요"
};
if (folderBrowserDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
string text = SkillService.ExportSkill(skill, folderBrowserDialog.SelectedPath);
if (text != null)
{
CustomMessageBox.Show("내보내기 완료:\n" + text, "내보내기");
}
else
{
CustomMessageBox.Show("내보내기에 실패했습니다.", "내보내기");
}
}
}));
if (isUser)
{
actions.Children.Add(MakeActionBtn("\ue74d", "#F87171", "삭제", delegate
{
MessageBoxResult messageBoxResult = CustomMessageBox.Show("스킬 '/" + skill.Name + "'을 삭제하시겠습니까?", "스킬 삭제", MessageBoxButton.YesNo, MessageBoxImage.Question);
if (messageBoxResult != MessageBoxResult.Yes)
{
return;
}
try
{
File.Delete(skill.FilePath);
SkillService.LoadSkills();
BuildCategoryFilter();
RenderSkills();
}
catch (Exception ex)
{
CustomMessageBox.Show("삭제 실패: " + ex.Message, "삭제");
}
}));
}
Grid.SetColumn(actions, 2);
grid.Children.Add(border);
grid.Children.Add(stackPanel);
grid.Children.Add(actions);
card.Child = grid;
card.Cursor = System.Windows.Input.Cursors.Hand;
card.MouseEnter += delegate
{
card.Background = new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
};
card.MouseLeave += delegate
{
card.Background = bgBrush;
};
card.MouseLeftButtonUp += delegate(object _, MouseButtonEventArgs e)
{
if (e.OriginalSource is FrameworkElement frameworkElement)
{
for (FrameworkElement frameworkElement2 = frameworkElement; frameworkElement2 != null; frameworkElement2 = VisualTreeHelper.GetParent((DependencyObject)(object)frameworkElement2) as FrameworkElement)
{
if (frameworkElement2 == actions)
{
return;
}
}
}
ShowSkillDetail(skill);
};
return card;
}
private Border MakeBadge(string text, string colorHex)
{
Color color = (Color)ColorConverter.ConvertFromString(colorHex);
return new Border
{
Background = new SolidColorBrush(Color.FromArgb(37, color.R, color.G, color.B)),
CornerRadius = new CornerRadius(4.0),
Padding = new Thickness(5.0, 1.0, 5.0, 1.0),
Margin = new Thickness(6.0, 0.0, 0.0, 0.0),
VerticalAlignment = VerticalAlignment.Center,
Child = new TextBlock
{
Text = text,
FontSize = 9.5,
FontWeight = FontWeights.SemiBold,
Foreground = new SolidColorBrush(color)
}
};
}
private Border MakeActionBtn(string icon, string colorHex, string tooltip, Action action)
{
Color col = (Color)ColorConverter.ConvertFromString(colorHex);
Border btn = new Border
{
Width = 28.0,
Height = 28.0,
CornerRadius = new CornerRadius(6.0),
Background = Brushes.Transparent,
Cursor = System.Windows.Input.Cursors.Hand,
Margin = new Thickness(2.0, 0.0, 0.0, 0.0),
ToolTip = tooltip,
Child = new TextBlock
{
Text = icon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 12.0,
Foreground = new SolidColorBrush(col),
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
}
};
btn.MouseEnter += delegate
{
btn.Background = new SolidColorBrush(Color.FromArgb(32, col.R, col.G, col.B));
};
btn.MouseLeave += delegate
{
btn.Background = Brushes.Transparent;
};
btn.MouseLeftButtonUp += delegate
{
action();
};
return btn;
}
private void ShowSkillDetail(SkillDefinition skill)
{
Brush background = (TryFindResource("LauncherBackground") as Brush) ?? Brushes.Black;
Brush fgBrush = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush subBrush = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush background2 = (TryFindResource("ItemBackground") as Brush) ?? Brushes.Transparent;
Brush brush = (TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Window popup = new Window
{
Title = "/" + skill.Name,
Width = 580.0,
Height = 480.0,
WindowStyle = WindowStyle.None,
AllowsTransparency = true,
Background = Brushes.Transparent,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Owner = this
};
Border border = new Border
{
Background = background,
CornerRadius = new CornerRadius(12.0),
BorderBrush = brush,
BorderThickness = new Thickness(1.0, 1.0, 1.0, 1.0),
Effect = new DropShadowEffect
{
BlurRadius = 20.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = Colors.Black
}
};
Grid grid = new Grid();
grid.RowDefinitions.Add(new RowDefinition
{
Height = new GridLength(44.0)
});
grid.RowDefinitions.Add(new RowDefinition());
Border border2 = new Border
{
CornerRadius = new CornerRadius(12.0, 12.0, 0.0, 0.0),
Background = background2
};
border2.MouseLeftButtonDown += delegate(object _, MouseButtonEventArgs e)
{
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Unknown result type (might be due to invalid IL or missing references)
Point position = e.GetPosition(popup);
if (!(((Point)(ref position)).X > popup.ActualWidth - 50.0))
{
popup.DragMove();
}
};
Grid grid2 = new Grid
{
Margin = new Thickness(16.0, 0.0, 12.0, 0.0)
};
StackPanel stackPanel = new StackPanel
{
Orientation = System.Windows.Controls.Orientation.Horizontal,
VerticalAlignment = VerticalAlignment.Center
};
stackPanel.Children.Add(new TextBlock
{
Text = skill.Icon,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 14.0,
Foreground = new SolidColorBrush(Color.FromRgb(75, 94, 252)),
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 1.0, 8.0, 0.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = "/" + skill.Name + " " + skill.Label,
FontSize = 14.0,
FontWeight = FontWeights.SemiBold,
Foreground = fgBrush,
VerticalAlignment = VerticalAlignment.Center
});
grid2.Children.Add(stackPanel);
Border border3 = new Border
{
Width = 28.0,
Height = 28.0,
CornerRadius = new CornerRadius(6.0),
Cursor = System.Windows.Input.Cursors.Hand,
HorizontalAlignment = System.Windows.HorizontalAlignment.Right,
VerticalAlignment = VerticalAlignment.Center
};
border3.Child = new TextBlock
{
Text = "\ue8bb",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 10.0,
Foreground = subBrush,
HorizontalAlignment = System.Windows.HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
};
border3.MouseEnter += delegate(object s, System.Windows.Input.MouseEventArgs _)
{
((Border)s).Background = new SolidColorBrush(Color.FromArgb(51, byte.MaxValue, 68, 68));
};
border3.MouseLeave += delegate(object s, System.Windows.Input.MouseEventArgs _)
{
((Border)s).Background = Brushes.Transparent;
};
border3.MouseLeftButtonUp += delegate
{
popup.Close();
};
grid2.Children.Add(border3);
border2.Child = grid2;
Grid.SetRow(border2, 0);
ScrollViewer scrollViewer = new ScrollViewer
{
VerticalScrollBarVisibility = ScrollBarVisibility.Auto,
Padding = new Thickness(20.0, 16.0, 20.0, 16.0)
};
StackPanel stackPanel2 = new StackPanel();
Grid metaGrid = new Grid
{
Margin = new Thickness(0.0, 0.0, 0.0, 14.0)
};
metaGrid.ColumnDefinitions.Add(new ColumnDefinition
{
Width = new GridLength(80.0)
});
metaGrid.ColumnDefinitions.Add(new ColumnDefinition());
int num = 0;
AddMetaRow("명령어", "/" + skill.Name, num++);
AddMetaRow("라벨", skill.Label, num++);
AddMetaRow("설명", skill.Description, num++);
if (!string.IsNullOrEmpty(skill.Requires))
{
AddMetaRow("런타임", skill.Requires, num++);
}
if (!string.IsNullOrEmpty(skill.AllowedTools))
{
AddMetaRow("허용 도구", skill.AllowedTools, num++);
}
AddMetaRow("상태", skill.IsAvailable ? "✓ 사용 가능" : ("✗ " + skill.UnavailableHint), num++);
AddMetaRow("경로", skill.FilePath, num++);
stackPanel2.Children.Add(metaGrid);
stackPanel2.Children.Add(new Border
{
Height = 1.0,
Background = brush,
Margin = new Thickness(0.0, 4.0, 0.0, 12.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = "시스템 프롬프트 (미리보기)",
FontSize = 11.0,
FontWeight = FontWeights.SemiBold,
Foreground = subBrush,
Margin = new Thickness(0.0, 0.0, 0.0, 6.0)
});
Border border4 = new Border
{
Background = background2,
CornerRadius = new CornerRadius(8.0),
Padding = new Thickness(12.0, 10.0, 12.0, 10.0)
};
string text = skill.SystemPrompt;
if (text.Length > 2000)
{
text = text.Substring(0, 2000) + "\n\n... (이하 생략)";
}
border4.Child = new TextBlock
{
Text = text,
FontSize = 11.5,
FontFamily = new FontFamily("Consolas, Cascadia Code, Segoe UI"),
Foreground = fgBrush,
TextWrapping = TextWrapping.Wrap,
Opacity = 0.85
};
stackPanel2.Children.Add(border4);
scrollViewer.Content = stackPanel2;
Grid.SetRow(scrollViewer, 1);
grid.Children.Add(border2);
grid.Children.Add(scrollViewer);
border.Child = grid;
popup.Content = border;
popup.ShowDialog();
void AddMetaRow(string label, string value, int row)
{
if (!string.IsNullOrEmpty(value))
{
metaGrid.RowDefinitions.Add(new RowDefinition
{
Height = GridLength.Auto
});
TextBlock element = new TextBlock
{
Text = label,
FontSize = 11.5,
Foreground = subBrush,
Margin = new Thickness(0.0, 2.0, 0.0, 2.0)
};
Grid.SetRow(element, row);
Grid.SetColumn(element, 0);
metaGrid.Children.Add(element);
TextBlock element2 = new TextBlock
{
Text = value,
FontSize = 11.5,
Foreground = fgBrush,
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness(0.0, 2.0, 0.0, 2.0)
};
Grid.SetRow(element2, row);
Grid.SetColumn(element2, 1);
metaGrid.Children.Add(element2);
}
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/skillgallerywindow.xaml", UriKind.Relative);
System.Windows.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:
((Border)target).MouseLeftButtonDown += TitleBar_MouseLeftButtonDown;
break;
case 2:
((Border)target).MouseLeftButtonUp += BtnAddSkill_Click;
break;
case 3:
((Border)target).MouseLeftButtonUp += BtnImport_Click;
break;
case 4:
BtnCloseGallery = (Border)target;
BtnCloseGallery.MouseLeftButtonUp += BtnClose_Click;
break;
case 5:
CategoryFilterBar = (StackPanel)target;
break;
case 6:
SkillListPanel = (StackPanel)target;
break;
case 7:
GalleryStatus = (TextBlock)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,150 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Markup;
using AxCopilot.ViewModels;
namespace AxCopilot.Views;
public class StatisticsWindow : Window, IComponentConnector
{
private const int WM_NCLBUTTONDOWN = 161;
private const int HTBOTTOMRIGHT = 17;
private readonly StatisticsViewModel _vm;
internal RadioButton StatsTabMain;
internal RadioButton StatsTabCommander;
internal RadioButton StatsTabAgent;
internal ScrollViewer PanelMain;
internal ScrollViewer PanelCommander;
internal ScrollViewer PanelAgent;
private bool _contentLoaded;
[DllImport("user32.dll")]
private static extern void ReleaseCapture();
[DllImport("user32.dll")]
private static extern nint SendMessage(nint hWnd, int msg, nint wParam, nint lParam);
public StatisticsWindow()
{
InitializeComponent();
_vm = new StatisticsViewModel();
base.DataContext = _vm;
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left && e.LeftButton == MouseButtonState.Pressed)
{
try
{
DragMove();
}
catch
{
}
}
}
private void ResizeGrip_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Pressed)
{
ReleaseCapture();
SendMessage(new WindowInteropHelper(this).Handle, 161, 17, IntPtr.Zero);
}
}
private void Close_Click(object sender, RoutedEventArgs e)
{
Close();
}
private void Refresh_Click(object sender, RoutedEventArgs e)
{
_vm.Refresh();
}
private void StatsTab_Click(object sender, RoutedEventArgs e)
{
if (PanelMain != null && PanelCommander != null && PanelAgent != null)
{
PanelMain.Visibility = ((StatsTabMain.IsChecked != true) ? Visibility.Collapsed : Visibility.Visible);
PanelCommander.Visibility = ((StatsTabCommander.IsChecked != true) ? Visibility.Collapsed : Visibility.Visible);
PanelAgent.Visibility = ((StatsTabAgent.IsChecked != true) ? Visibility.Collapsed : Visibility.Visible);
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/statisticswindow.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:
((StatisticsWindow)target).MouseDown += Window_MouseDown;
break;
case 2:
((Button)target).Click += Refresh_Click;
break;
case 3:
((Button)target).Click += Close_Click;
break;
case 4:
StatsTabMain = (RadioButton)target;
StatsTabMain.Click += StatsTab_Click;
break;
case 5:
StatsTabCommander = (RadioButton)target;
StatsTabCommander.Click += StatsTab_Click;
break;
case 6:
StatsTabAgent = (RadioButton)target;
StatsTabAgent.Click += StatsTab_Click;
break;
case 7:
PanelMain = (ScrollViewer)target;
break;
case 8:
PanelCommander = (ScrollViewer)target;
break;
case 9:
PanelAgent = (ScrollViewer)target;
break;
case 10:
((Border)target).MouseLeftButtonDown += ResizeGrip_MouseLeftButtonDown;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,298 @@
using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
namespace AxCopilot.Views;
public class TextActionPopup : Window, IComponentConnector
{
private struct POINT
{
public int X;
public int Y;
}
public enum ActionResult
{
None,
OpenLauncher,
Translate,
Summarize,
GrammarFix,
Explain,
Rewrite
}
private int _selectedIndex;
private readonly List<(ActionResult Action, string Icon, string Label)> _items;
private static readonly (string Key, ActionResult Action, string Icon, string Label)[] AllCommands = new(string, ActionResult, string, string)[5]
{
("translate", ActionResult.Translate, "\ue774", "번역"),
("summarize", ActionResult.Summarize, "\ue8d2", "요약"),
("grammar", ActionResult.GrammarFix, "\ue8ac", "문법 교정"),
("explain", ActionResult.Explain, "\ue946", "설명"),
("rewrite", ActionResult.Rewrite, "\ue70f", "다시 쓰기")
};
internal TextBlock PreviewText;
internal StackPanel MenuItems;
private bool _contentLoaded;
public ActionResult SelectedAction { get; private set; } = ActionResult.None;
public string SelectedText { get; private set; } = "";
public static IReadOnlyList<(string Key, string Label)> AvailableCommands => AllCommands.Select(((string Key, ActionResult Action, string Icon, string Label) c) => (Key: c.Key, Label: c.Label)).ToList();
[DllImport("user32.dll")]
private static extern bool GetCursorPos(out POINT lpPoint);
public TextActionPopup(string selectedText, List<string>? enabledCommands = null)
{
InitializeComponent();
SelectedText = selectedText;
string text = selectedText.Replace("\r\n", " ").Replace("\n", " ");
PreviewText.Text = ((text.Length > 60) ? (text.Substring(0, 57) + "…") : text);
List<string> source = enabledCommands ?? AllCommands.Select(((string Key, ActionResult Action, string Icon, string Label) c) => c.Key).ToList();
_items = new List<(ActionResult, string, string)> { (ActionResult.OpenLauncher, "\ue8a7", "AX Commander 열기") };
(string, ActionResult, string, string)[] allCommands = AllCommands;
for (int num = 0; num < allCommands.Length; num++)
{
(string, ActionResult, string, string) tuple = allCommands[num];
if (source.Contains<string>(tuple.Item1, StringComparer.OrdinalIgnoreCase))
{
_items.Add((tuple.Item2, tuple.Item3, tuple.Item4));
}
}
BuildMenuItems();
PositionAtCursor();
base.Loaded += delegate
{
Focus();
UpdateSelection();
};
}
private void BuildMenuItems()
{
Brush foreground = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush foreground2 = (TryFindResource("AccentColor") as Brush) ?? Brushes.CornflowerBlue;
for (int i = 0; i < _items.Count; i++)
{
(ActionResult, string, string) tuple = _items[i];
ActionResult action = tuple.Item1;
string item = tuple.Item2;
string item2 = tuple.Item3;
int num = i;
StackPanel stackPanel = new StackPanel
{
Orientation = Orientation.Horizontal
};
stackPanel.Children.Add(new TextBlock
{
Text = item,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 14.0,
Foreground = foreground2,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 10.0, 0.0),
Width = 20.0,
TextAlignment = TextAlignment.Center
});
stackPanel.Children.Add(new TextBlock
{
Text = item2,
FontSize = 13.0,
Foreground = foreground,
VerticalAlignment = VerticalAlignment.Center
});
Border border = new Border
{
Child = stackPanel,
CornerRadius = new CornerRadius(8.0),
Padding = new Thickness(10.0, 8.0, 14.0, 8.0),
Margin = new Thickness(0.0, 1.0, 0.0, 1.0),
Background = Brushes.Transparent,
Cursor = Cursors.Hand,
Tag = num
};
border.MouseEnter += delegate(object s, MouseEventArgs _)
{
if (s is Border { Tag: var tag } && tag is int selectedIndex)
{
_selectedIndex = selectedIndex;
UpdateSelection();
}
};
border.MouseLeftButtonUp += delegate
{
SelectedAction = action;
Close();
};
MenuItems.Children.Add(border);
}
}
private void UpdateSelection()
{
Brush brush = (TryFindResource("ItemHoverBackground") as Brush) ?? new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
Brush brush2 = (TryFindResource("ItemSelectedBackground") as Brush) ?? new SolidColorBrush(Color.FromArgb(68, 75, 94, 252));
for (int i = 0; i < MenuItems.Children.Count; i++)
{
if (MenuItems.Children[i] is Border border)
{
border.Background = ((i == _selectedIndex) ? brush2 : Brushes.Transparent);
}
}
}
private void PositionAtCursor()
{
//IL_008f: Unknown result type (might be due to invalid IL or missing references)
//IL_0094: Unknown result type (might be due to invalid IL or missing references)
//IL_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0045: Unknown result type (might be due to invalid IL or missing references)
//IL_0055: Unknown result type (might be due to invalid IL or missing references)
//IL_005a: Unknown result type (might be due to invalid IL or missing references)
GetCursorPos(out var lpPoint);
PresentationSource presentationSource = PresentationSource.FromVisual(this);
double num = 1.0;
double num2 = 1.0;
if (presentationSource?.CompositionTarget != null)
{
Matrix transformFromDevice = presentationSource.CompositionTarget.TransformFromDevice;
num = ((Matrix)(ref transformFromDevice)).M11;
transformFromDevice = presentationSource.CompositionTarget.TransformFromDevice;
num2 = ((Matrix)(ref transformFromDevice)).M22;
}
base.Left = (double)lpPoint.X * num;
base.Top = (double)lpPoint.Y * num2 + 10.0;
Rect workArea = SystemParameters.WorkArea;
if (base.Left + 280.0 > ((Rect)(ref workArea)).Right)
{
base.Left = ((Rect)(ref workArea)).Right - 280.0;
}
if (base.Top + 300.0 > ((Rect)(ref workArea)).Bottom)
{
base.Top = (double)lpPoint.Y * num2 - 300.0;
}
if (base.Left < ((Rect)(ref workArea)).Left)
{
base.Left = ((Rect)(ref workArea)).Left;
}
if (base.Top < ((Rect)(ref workArea)).Top)
{
base.Top = ((Rect)(ref workArea)).Top;
}
}
private void Window_KeyDown(object sender, KeyEventArgs e)
{
//IL_0002: Unknown result type (might be due to invalid IL or missing references)
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
//IL_0009: Unknown result type (might be due to invalid IL or missing references)
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
//IL_000d: Invalid comparison between Unknown and I4
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
//IL_0028: Invalid comparison between Unknown and I4
//IL_000f: Unknown result type (might be due to invalid IL or missing references)
//IL_0011: Invalid comparison between Unknown and I4
//IL_002c: Unknown result type (might be due to invalid IL or missing references)
//IL_002f: Invalid comparison between Unknown and I4
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
//IL_001b: Invalid comparison between Unknown and I4
Key key = e.Key;
Key val = key;
if ((int)val <= 13)
{
if ((int)val != 6)
{
if ((int)val == 13)
{
SelectedAction = ActionResult.None;
Close();
e.Handled = true;
}
}
else
{
SelectedAction = _items[_selectedIndex].Action;
Close();
e.Handled = true;
}
}
else if ((int)val != 24)
{
if ((int)val == 26)
{
_selectedIndex = (_selectedIndex + 1) % _items.Count;
UpdateSelection();
e.Handled = true;
}
}
else
{
_selectedIndex = (_selectedIndex - 1 + _items.Count) % _items.Count;
UpdateSelection();
e.Handled = true;
}
}
private void Window_Deactivated(object? sender, EventArgs e)
{
if (base.IsVisible)
{
Close();
}
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/textactionpopup.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:
((TextActionPopup)target).Deactivated += Window_Deactivated;
((TextActionPopup)target).KeyDown += Window_KeyDown;
break;
case 2:
PreviewText = (TextBlock)target;
break;
case 3:
MenuItems = (StackPanel)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,130 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Windows.Forms;
namespace AxCopilot.Views;
internal static class TrayContextMenu
{
internal const string GlyphOpen = "\ue7c5";
internal const string GlyphSettings = "\ue713";
internal const string GlyphReload = "\ue72c";
internal const string GlyphFolder = "\ue838";
internal const string GlyphInfo = "\ue946";
internal const string GlyphStats = "\ue9d9";
internal const string GlyphChat = "\ue8bd";
internal const string GlyphGuide = "\ue736";
internal const string GlyphAutoRun = "\ue82f";
internal const string GlyphExit = "\ue711";
private static readonly Bitmap DummyImage = new Bitmap(1, 1);
private static float GetDpiScale()
{
try
{
using Graphics graphics = Graphics.FromHwnd(IntPtr.Zero);
return Math.Max(1f, graphics.DpiX / 96f);
}
catch
{
return 1f;
}
}
private static int Dp(int logicalPx, float dpiScale)
{
return Math.Max(1, (int)Math.Round((float)logicalPx / dpiScale));
}
public static Padding DpiPadding(int left, int top, int right, int bottom)
{
float dpiScale = GetDpiScale();
return new Padding(Dp(left, dpiScale), Dp(top, dpiScale), Dp(right, dpiScale), Dp(bottom, dpiScale));
}
public static ToolStripMenuItem MakeItem(string text, string glyph, EventHandler onClick)
{
float dpiScale = GetDpiScale();
ToolStripMenuItem toolStripMenuItem = new ToolStripMenuItem(text)
{
Tag = glyph,
Image = DummyImage,
Padding = new Padding(Dp(4, dpiScale), Dp(10, dpiScale), Dp(16, dpiScale), Dp(10, dpiScale))
};
toolStripMenuItem.Click += onClick;
return toolStripMenuItem;
}
public static ContextMenuStrip CreateMenu()
{
float dpiScale = GetDpiScale();
ContextMenuStrip menu = new ContextMenuStrip();
menu.Renderer = new ModernTrayRenderer();
menu.Font = new Font("Segoe UI", 10f, GraphicsUnit.Point);
menu.ShowImageMargin = true;
menu.ImageScalingSize = new Size(Dp(52, dpiScale), Dp(32, dpiScale));
menu.MinimumSize = new Size(Dp(280, dpiScale), 0);
menu.Opened += delegate
{
ApplyRoundedCorners(menu);
};
return menu;
}
private static void ApplyRoundedCorners(ContextMenuStrip menu)
{
try
{
nint num = CreateRoundRectRgn(0, 0, menu.Width, menu.Height, 16, 16);
if (num != IntPtr.Zero && SetWindowRgn(menu.Handle, num, bRedraw: true) == 0)
{
DeleteObject(num);
}
}
catch
{
}
}
[DllImport("gdi32.dll")]
private static extern nint CreateRoundRectRgn(int x1, int y1, int x2, int y2, int cx, int cy);
[DllImport("gdi32.dll")]
private static extern bool DeleteObject(nint hObject);
[DllImport("user32.dll")]
private static extern int SetWindowRgn(nint hWnd, nint hRgn, bool bRedraw);
public static void ApplySpacing(ContextMenuStrip menu, int top = 10, int bottom = 10, int left = 0, int right = 0)
{
if (menu.Items.Count == 0)
{
return;
}
float dpiScale = GetDpiScale();
int top2 = Dp(top, dpiScale);
int bottom2 = Dp(bottom, dpiScale);
int num = Dp(left, dpiScale);
int num2 = Dp(right, dpiScale);
foreach (ToolStripItem item in menu.Items)
{
Padding margin = item.Margin;
item.Margin = new Padding(margin.Left + num, margin.Top, margin.Right + num2, margin.Bottom);
}
ToolStripItem toolStripItem2 = menu.Items[0];
toolStripItem2.Margin = new Padding(toolStripItem2.Margin.Left, top2, toolStripItem2.Margin.Right, toolStripItem2.Margin.Bottom);
ToolStripItem toolStripItem3 = menu.Items[menu.Items.Count - 1];
toolStripItem3.Margin = new Padding(toolStripItem3.Margin.Left, toolStripItem3.Margin.Top, toolStripItem3.Margin.Right, bottom2);
}
}

View File

@@ -0,0 +1,335 @@
using System;
using System.CodeDom.Compiler;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
using System.Windows.Threading;
namespace AxCopilot.Views;
public class TrayMenuWindow : Window, IComponentConnector
{
private struct POINT
{
public int X;
public int Y;
}
private DispatcherTimer? _autoCloseTimer;
private static readonly Brush BulbOnBrush = new SolidColorBrush(Color.FromRgb(byte.MaxValue, 185, 0));
private static readonly Brush BulbOffBrush = new SolidColorBrush(Color.FromRgb(120, 120, 140));
internal Border RootBorder;
internal StackPanel MenuPanel;
private bool _contentLoaded;
public event Action? Opening;
public TrayMenuWindow()
{
InitializeComponent();
base.MouseLeave += delegate
{
//IL_0014: Unknown result type (might be due to invalid IL or missing references)
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
//IL_0033: Expected O, but got Unknown
DispatcherTimer? autoCloseTimer = _autoCloseTimer;
if (autoCloseTimer != null)
{
autoCloseTimer.Stop();
}
_autoCloseTimer = new DispatcherTimer
{
Interval = TimeSpan.FromMilliseconds(400.0)
};
_autoCloseTimer.Tick += delegate
{
_autoCloseTimer.Stop();
Hide();
};
_autoCloseTimer.Start();
};
base.MouseEnter += delegate
{
DispatcherTimer? autoCloseTimer = _autoCloseTimer;
if (autoCloseTimer != null)
{
autoCloseTimer.Stop();
}
};
}
public TrayMenuWindow AddItem(string glyph, string text, Action onClick)
{
Border border = CreateItemBorder(glyph, text);
border.MouseLeftButtonUp += delegate
{
Hide();
onClick();
};
MenuPanel.Children.Add(border);
return this;
}
public TrayMenuWindow AddItem(string glyph, string text, Action onClick, out Border itemRef)
{
Border border = CreateItemBorder(glyph, text);
border.MouseLeftButtonUp += delegate
{
Hide();
onClick();
};
MenuPanel.Children.Add(border);
itemRef = border;
return this;
}
public TrayMenuWindow AddToggleItem(string glyph, string text, bool initialChecked, Action<bool> onToggle, out Func<bool> getChecked, out Action<string> setText)
{
TextBlock glyphBlock = new TextBlock
{
Text = glyph,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 14.0,
Foreground = (initialChecked ? BulbOnBrush : BulbOffBrush),
VerticalAlignment = VerticalAlignment.Center,
Width = 20.0,
TextAlignment = TextAlignment.Center
};
if (initialChecked)
{
glyphBlock.Effect = new DropShadowEffect
{
Color = Color.FromRgb(byte.MaxValue, 185, 0),
BlurRadius = 12.0,
ShadowDepth = 0.0,
Opacity = 0.7
};
}
TextBlock label = new TextBlock
{
Text = text,
FontSize = 13.0,
VerticalAlignment = VerticalAlignment.Center
};
label.SetResourceReference(TextBlock.ForegroundProperty, "PrimaryText");
StackPanel child = new StackPanel
{
Orientation = Orientation.Horizontal,
Children =
{
(UIElement)glyphBlock,
(UIElement)label
}
};
Border border = new Border
{
Child = child,
CornerRadius = new CornerRadius(6.0),
Padding = new Thickness(12.0, 8.0, 16.0, 8.0),
Cursor = Cursors.Hand,
Background = Brushes.Transparent
};
border.MouseEnter += delegate
{
border.Background = (TryFindResource("ItemHoverBackground") as Brush) ?? Brushes.Transparent;
};
border.MouseLeave += delegate
{
border.Background = Brushes.Transparent;
};
border.MouseLeftButtonUp += delegate
{
initialChecked = !initialChecked;
glyphBlock.Foreground = (initialChecked ? BulbOnBrush : BulbOffBrush);
glyphBlock.Effect = (initialChecked ? new DropShadowEffect
{
Color = Color.FromRgb(byte.MaxValue, 185, 0),
BlurRadius = 12.0,
ShadowDepth = 0.0,
Opacity = 0.7
} : null);
onToggle(initialChecked);
};
getChecked = () => initialChecked;
setText = delegate(string t)
{
label.Text = t;
};
MenuPanel.Children.Add(border);
return this;
}
public TrayMenuWindow AddSeparator()
{
Border border = new Border
{
Height = 1.0,
Margin = new Thickness(16.0, 5.0, 16.0, 5.0)
};
border.SetResourceReference(Border.BackgroundProperty, "SeparatorColor");
MenuPanel.Children.Add(border);
return this;
}
public void ShowAtTray()
{
//IL_0001: Unknown result type (might be due to invalid IL or missing references)
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
Rect workArea = SystemParameters.WorkArea;
base.Opacity = 0.0;
Show();
UpdateLayout();
double actualWidth = base.ActualWidth;
double actualHeight = base.ActualHeight;
POINT cursorPosition = GetCursorPosition();
double pixelsPerDip = VisualTreeHelper.GetDpi(this).PixelsPerDip;
double num = (double)cursorPosition.X / pixelsPerDip;
double num2 = (double)cursorPosition.Y / pixelsPerDip;
double num3 = num - actualWidth - 8.0;
double num4 = num2 - actualHeight - 8.0;
if (num3 < ((Rect)(ref workArea)).Left)
{
num3 = ((Rect)(ref workArea)).Left + 4.0;
}
if (num4 < ((Rect)(ref workArea)).Top)
{
num4 = ((Rect)(ref workArea)).Top + 4.0;
}
if (num3 + actualWidth > ((Rect)(ref workArea)).Right)
{
num3 = ((Rect)(ref workArea)).Right - actualWidth - 4.0;
}
if (num4 + actualHeight > ((Rect)(ref workArea)).Bottom)
{
num4 = ((Rect)(ref workArea)).Bottom - actualHeight - 4.0;
}
base.Left = num3;
base.Top = num4;
Activate();
DoubleAnimation animation = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(120.0))
{
EasingFunction = new CubicEase
{
EasingMode = EasingMode.EaseOut
}
};
BeginAnimation(UIElement.OpacityProperty, animation);
}
public void ShowWithUpdate()
{
this.Opening?.Invoke();
ShowAtTray();
}
private Border CreateItemBorder(string glyph, string text)
{
TextBlock glyphBlock = new TextBlock
{
Text = glyph,
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 14.0,
VerticalAlignment = VerticalAlignment.Center,
Width = 20.0,
TextAlignment = TextAlignment.Center
};
glyphBlock.SetResourceReference(TextBlock.ForegroundProperty, "SecondaryText");
TextBlock textBlock = new TextBlock
{
Text = text,
FontSize = 13.0,
VerticalAlignment = VerticalAlignment.Center
};
textBlock.SetResourceReference(TextBlock.ForegroundProperty, "PrimaryText");
StackPanel child = new StackPanel
{
Orientation = Orientation.Horizontal,
Children =
{
(UIElement)glyphBlock,
(UIElement)textBlock
}
};
Border border = new Border
{
Child = child,
CornerRadius = new CornerRadius(6.0),
Padding = new Thickness(12.0, 8.0, 16.0, 8.0),
Cursor = Cursors.Hand,
Background = Brushes.Transparent
};
border.MouseEnter += delegate
{
border.Background = (TryFindResource("ItemHoverBackground") as Brush) ?? Brushes.Transparent;
glyphBlock.Foreground = (TryFindResource("AccentColor") as Brush) ?? Brushes.Blue;
};
border.MouseLeave += delegate
{
border.Background = Brushes.Transparent;
glyphBlock.SetResourceReference(TextBlock.ForegroundProperty, "SecondaryText");
};
return border;
}
private void Window_Deactivated(object sender, EventArgs e)
{
Hide();
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool GetCursorPos(out POINT lpPoint);
private static POINT GetCursorPosition()
{
GetCursorPos(out var lpPoint);
return lpPoint;
}
[DebuggerNonUserCode]
[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
public void InitializeComponent()
{
if (!_contentLoaded)
{
_contentLoaded = true;
Uri resourceLocator = new Uri("/AxCopilot;component/views/traymenuwindow.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:
((TrayMenuWindow)target).Deactivated += Window_Deactivated;
break;
case 2:
RootBorder = (Border)target;
break;
case 3:
MenuPanel = (StackPanel)target;
break;
default:
_contentLoaded = true;
break;
}
}
}

View File

@@ -0,0 +1,380 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Effects;
namespace AxCopilot.Views;
internal sealed class UserAskDialog : Window
{
private string _selectedResponse = "";
private readonly TextBox _customInput;
private readonly StackPanel _optionPanel;
public string SelectedResponse => _selectedResponse;
private UserAskDialog(string question, List<string> options, string defaultValue)
{
//IL_0c8c: Unknown result type (might be due to invalid IL or missing references)
UserAskDialog userAskDialog = this;
base.Width = 460.0;
base.MinWidth = 380.0;
base.MaxWidth = 560.0;
base.SizeToContent = SizeToContent.Height;
base.WindowStartupLocation = WindowStartupLocation.CenterScreen;
base.ResizeMode = ResizeMode.NoResize;
base.WindowStyle = WindowStyle.None;
base.AllowsTransparency = true;
base.Background = Brushes.Transparent;
base.Topmost = true;
Brush background = (Application.Current.TryFindResource("LauncherBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(26, 27, 46));
Brush brush = (Application.Current.TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
Brush brush2 = (Application.Current.TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
Brush accentBrush = (Application.Current.TryFindResource("AccentColor") as Brush) ?? new SolidColorBrush(Color.FromRgb(75, 94, 252));
Brush brush3 = (Application.Current.TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
Brush itemBg = (Application.Current.TryFindResource("ItemBackground") as Brush) ?? new SolidColorBrush(Color.FromRgb(42, 43, 64));
Brush hoverBg = (Application.Current.TryFindResource("ItemHoverBackground") as Brush) ?? new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
Border root = new Border
{
Background = background,
CornerRadius = new CornerRadius(16.0),
BorderBrush = brush3,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(24.0, 20.0, 24.0, 18.0),
Effect = new DropShadowEffect
{
BlurRadius = 24.0,
ShadowDepth = 4.0,
Opacity = 0.3,
Color = Colors.Black
}
};
StackPanel stackPanel = new StackPanel();
Grid grid = new Grid
{
Margin = new Thickness(0.0, 0.0, 0.0, 12.0)
};
grid.MouseLeftButtonDown += delegate
{
try
{
userAskDialog.DragMove();
}
catch
{
}
};
StackPanel stackPanel2 = new StackPanel
{
Orientation = Orientation.Horizontal
};
stackPanel2.Children.Add(new TextBlock
{
Text = "\ue9ce",
FontFamily = new FontFamily("Segoe MDL2 Assets"),
FontSize = 16.0,
Foreground = accentBrush,
VerticalAlignment = VerticalAlignment.Center,
Margin = new Thickness(0.0, 0.0, 8.0, 0.0)
});
stackPanel2.Children.Add(new TextBlock
{
Text = "AX Agent — 질문",
FontSize = 14.0,
FontWeight = FontWeights.SemiBold,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center
});
grid.Children.Add(stackPanel2);
stackPanel.Children.Add(grid);
stackPanel.Children.Add(new Border
{
Height = 1.0,
Background = brush3,
Opacity = 0.3,
Margin = new Thickness(0.0, 0.0, 0.0, 14.0)
});
stackPanel.Children.Add(new TextBlock
{
Text = question,
FontSize = 13.5,
Foreground = brush,
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness(0.0, 0.0, 0.0, 16.0),
LineHeight = 20.0
});
_optionPanel = new StackPanel
{
Margin = new Thickness(0.0, 0.0, 0.0, 12.0)
};
Border selectedBorder = null;
foreach (string option in options)
{
string capturedOption = option;
Border border = new Border
{
Background = itemBg,
CornerRadius = new CornerRadius(10.0),
Padding = new Thickness(14.0, 10.0, 14.0, 10.0),
Margin = new Thickness(0.0, 0.0, 0.0, 6.0),
Cursor = Cursors.Hand,
BorderBrush = Brushes.Transparent,
BorderThickness = new Thickness(1.5)
};
StackPanel stackPanel3 = new StackPanel
{
Orientation = Orientation.Horizontal
};
Border element = new Border
{
Width = 18.0,
Height = 18.0,
CornerRadius = new CornerRadius(9.0),
BorderBrush = brush2,
BorderThickness = new Thickness(1.5),
Margin = new Thickness(0.0, 0.0, 10.0, 0.0),
VerticalAlignment = VerticalAlignment.Center,
Child = new Border
{
Width = 10.0,
Height = 10.0,
CornerRadius = new CornerRadius(5.0),
Background = Brushes.Transparent,
HorizontalAlignment = HorizontalAlignment.Center,
VerticalAlignment = VerticalAlignment.Center
}
};
stackPanel3.Children.Add(element);
stackPanel3.Children.Add(new TextBlock
{
Text = capturedOption,
FontSize = 13.0,
Foreground = brush,
VerticalAlignment = VerticalAlignment.Center,
TextWrapping = TextWrapping.Wrap
});
border.Child = stackPanel3;
border.MouseEnter += delegate(object s, MouseEventArgs _)
{
Border border4 = (Border)s;
if (border4.BorderBrush != accentBrush)
{
border4.Background = hoverBg;
}
};
border.MouseLeave += delegate(object s, MouseEventArgs _)
{
Border border4 = (Border)s;
if (border4.BorderBrush != accentBrush)
{
border4.Background = itemBg;
}
};
border.MouseLeftButtonUp += delegate(object s, MouseButtonEventArgs _)
{
if (selectedBorder != null)
{
selectedBorder.BorderBrush = Brushes.Transparent;
selectedBorder.Background = itemBg;
Border border4 = FindRadioCircle(selectedBorder);
if (border4 != null)
{
border4.Background = Brushes.Transparent;
}
}
Border border5 = (Border)s;
border5.BorderBrush = accentBrush;
border5.Background = new SolidColorBrush(Color.FromArgb(21, ((SolidColorBrush)accentBrush).Color.R, ((SolidColorBrush)accentBrush).Color.G, ((SolidColorBrush)accentBrush).Color.B));
Border border6 = FindRadioCircle(border5);
if (border6 != null)
{
border6.Background = accentBrush;
}
selectedBorder = border5;
userAskDialog._selectedResponse = capturedOption;
if (userAskDialog._customInput != null)
{
userAskDialog._customInput.Text = "";
}
};
_optionPanel.Children.Add(border);
}
stackPanel.Children.Add(_optionPanel);
stackPanel.Children.Add(new TextBlock
{
Text = "또는 직접 입력:",
FontSize = 11.5,
Foreground = brush2,
Margin = new Thickness(2.0, 0.0, 0.0, 6.0)
});
_customInput = new TextBox
{
MinHeight = 40.0,
MaxHeight = 100.0,
AcceptsReturn = true,
TextWrapping = TextWrapping.Wrap,
FontSize = 13.0,
Background = itemBg,
Foreground = brush,
CaretBrush = brush,
BorderBrush = brush3,
BorderThickness = new Thickness(1.0),
Padding = new Thickness(10.0, 8.0, 10.0, 8.0),
Text = defaultValue
};
_customInput.TextChanged += delegate
{
if (!string.IsNullOrEmpty(userAskDialog._customInput.Text))
{
if (selectedBorder != null)
{
selectedBorder.BorderBrush = Brushes.Transparent;
selectedBorder.Background = itemBg;
Border border4 = FindRadioCircle(selectedBorder);
if (border4 != null)
{
border4.Background = Brushes.Transparent;
}
selectedBorder = null;
}
userAskDialog._selectedResponse = userAskDialog._customInput.Text;
}
};
stackPanel.Children.Add(_customInput);
StackPanel stackPanel4 = new StackPanel
{
Orientation = Orientation.Horizontal,
HorizontalAlignment = HorizontalAlignment.Right,
Margin = new Thickness(0.0, 16.0, 0.0, 0.0)
};
Border border2 = new Border
{
Background = accentBrush,
CornerRadius = new CornerRadius(10.0),
Padding = new Thickness(20.0, 9.0, 20.0, 9.0),
Cursor = Cursors.Hand,
Margin = new Thickness(8.0, 0.0, 0.0, 0.0)
};
border2.Child = new TextBlock
{
Text = "확인",
FontSize = 13.0,
FontWeight = FontWeights.SemiBold,
Foreground = Brushes.White
};
border2.MouseEnter += delegate(object s, MouseEventArgs _)
{
((Border)s).Opacity = 0.85;
};
border2.MouseLeave += delegate(object s, MouseEventArgs _)
{
((Border)s).Opacity = 1.0;
};
border2.MouseLeftButtonUp += delegate
{
if (string.IsNullOrWhiteSpace(userAskDialog._selectedResponse) && !string.IsNullOrWhiteSpace(defaultValue))
{
userAskDialog._selectedResponse = defaultValue;
}
userAskDialog.DialogResult = true;
userAskDialog.Close();
};
stackPanel4.Children.Add(border2);
Border border3 = new Border
{
Background = Brushes.Transparent,
CornerRadius = new CornerRadius(10.0),
Padding = new Thickness(16.0, 9.0, 16.0, 9.0),
Cursor = Cursors.Hand,
BorderBrush = new SolidColorBrush(Color.FromArgb(64, 220, 38, 38)),
BorderThickness = new Thickness(1.0)
};
border3.Child = new TextBlock
{
Text = "취소",
FontSize = 13.0,
Foreground = new SolidColorBrush(Color.FromRgb(220, 38, 38))
};
border3.MouseEnter += delegate(object s, MouseEventArgs _)
{
((Border)s).Opacity = 0.85;
};
border3.MouseLeave += delegate(object s, MouseEventArgs _)
{
((Border)s).Opacity = 1.0;
};
border3.MouseLeftButtonUp += delegate
{
userAskDialog._selectedResponse = "";
userAskDialog.DialogResult = false;
userAskDialog.Close();
};
stackPanel4.Children.Insert(0, border3);
stackPanel.Children.Add(stackPanel4);
root.Child = stackPanel;
base.Content = root;
root.RenderTransformOrigin = new Point(0.5, 0.5);
root.RenderTransform = new ScaleTransform(0.95, 0.95);
root.Opacity = 0.0;
base.Loaded += delegate
{
DoubleAnimation animation = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(150.0));
root.BeginAnimation(UIElement.OpacityProperty, animation);
DoubleAnimation animation2 = new DoubleAnimation(0.95, 1.0, TimeSpan.FromMilliseconds(200.0))
{
EasingFunction = new QuadraticEase
{
EasingMode = EasingMode.EaseOut
}
};
DoubleAnimation animation3 = new DoubleAnimation(0.95, 1.0, TimeSpan.FromMilliseconds(200.0))
{
EasingFunction = new QuadraticEase
{
EasingMode = EasingMode.EaseOut
}
};
((ScaleTransform)root.RenderTransform).BeginAnimation(ScaleTransform.ScaleXProperty, animation2);
((ScaleTransform)root.RenderTransform).BeginAnimation(ScaleTransform.ScaleYProperty, animation3);
};
base.KeyDown += delegate(object _, 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_0040: Unknown result type (might be due to invalid IL or missing references)
//IL_0046: Invalid comparison between Unknown and I4
if ((int)e.Key == 13)
{
userAskDialog._selectedResponse = "";
userAskDialog.DialogResult = false;
userAskDialog.Close();
}
if ((int)e.Key == 6 && !userAskDialog._customInput.IsFocused)
{
userAskDialog.DialogResult = true;
userAskDialog.Close();
}
};
}
private static Border? FindRadioCircle(Border optionBorder)
{
if (optionBorder.Child is StackPanel stackPanel && stackPanel.Children.Count > 0 && stackPanel.Children[0] is Border { Child: Border child })
{
return child;
}
return null;
}
public static string? Show(string question, List<string> options, string defaultValue = "")
{
UserAskDialog userAskDialog = new UserAskDialog(question, options, defaultValue);
return (userAskDialog.ShowDialog() == true) ? userAskDialog.SelectedResponse : null;
}
}

File diff suppressed because it is too large Load Diff