Files
AX-Copilot-Codex/src/AxCopilot/Views/GuideViewerWindow.xaml.cs

166 lines
5.4 KiB
C#

using System;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using Microsoft.Web.WebView2.Core;
namespace AxCopilot.Views;
public partial class GuideViewerWindow : Window
{
private string? _pendingHtml;
private Uri? _pendingUri;
public GuideViewerWindow()
{
InitializeComponent();
Loaded += OnLoaded;
KeyDown += (_, e) => { if (e.Key == Key.Escape) Close(); };
StateChanged += (_, _) =>
{
MaxBtnIcon.Text = WindowState == WindowState.Maximized ? "\uE923" : "\uE922";
};
}
private async void OnLoaded(object sender, RoutedEventArgs e)
{
var app = Application.Current as App;
var devMode = app?.SettingsService?.Settings?.Llm?.DevMode ?? false;
PrepareGuide(devMode);
try
{
// WebView2 초기화
var env = await CoreWebView2Environment.CreateAsync(
userDataFolder: 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)
{
// WebView2 런타임 미설치 시 오류 메시지 표시
System.Diagnostics.Debug.WriteLine($"WebView2 init error: {ex.Message}");
}
}
/// <summary>개발자 모드 여부에 따라 적절한 가이드를 준비합니다.</summary>
public void PrepareGuide(bool devMode)
{
TitleText.Text = devMode ? "AX Copilot 개발자 가이드" : "AX Copilot 사용 가이드";
Title = devMode ? "AX Copilot — 개발자 가이드" : "AX Copilot — 사용 가이드";
try
{
var exeDir = Path.GetDirectoryName(Environment.ProcessPath)
?? AppContext.BaseDirectory;
var assetsDir = Path.Combine(exeDir, "Assets");
// 1차: 암호화된 가이드 파일 (.enc) 시도
var encFile = devMode
? Path.Combine(assetsDir, "guide_dev.enc")
: Path.Combine(assetsDir, "guide_user.enc");
if (File.Exists(encFile))
{
_pendingHtml = Services.GuideEncryptor.DecryptToString(encFile);
return;
}
// 2차: 평문 가이드 파일 (.htm) 폴백 (개발 환경)
var htmFile = devMode
? Path.Combine(assetsDir, "AX Copilot 개발자가이드.htm")
: Path.Combine(assetsDir, "AX Copilot 사용가이드.htm");
if (File.Exists(htmFile))
{
_pendingUri = new Uri(htmFile);
return;
}
_pendingHtml = "<html><body style='font-family:Segoe UI;padding:40px;color:#666;'>" +
"<h2>가이드를 찾을 수 없습니다</h2>" +
$"<p>경로: {encFile}</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>";
}
}
/// <summary>외부에서 직접 가이드를 로드합니다 (WebView2 초기화 후 호출).</summary>
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();
return;
}
DragMove();
}
private void MinBtn_Click(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
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()
{
WindowState = WindowState == WindowState.Maximized
? WindowState.Normal
: WindowState.Maximized;
}
private void TitleBtn_Enter(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = TryFindResource("ItemHoverBackground") as Brush
?? new SolidColorBrush(Color.FromArgb(0x18, 0xFF, 0xFF, 0xFF));
}
private void CloseBtnEnter(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = new SolidColorBrush(Color.FromArgb(0x44, 0xFF, 0x40, 0x40));
}
private void TitleBtn_Leave(object sender, MouseEventArgs e)
{
if (sender is Border b)
b.Background = Brushes.Transparent;
}
}