196 lines
6.6 KiB
C#
196 lines
6.6 KiB
C#
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
using System.Text.Json;
|
|
using System.Windows;
|
|
using System.Windows.Input;
|
|
using System.Windows.Media.Imaging;
|
|
|
|
namespace AxCopilot.Views;
|
|
|
|
public partial class AboutWindow : Window
|
|
{
|
|
public AboutWindow()
|
|
{
|
|
InitializeComponent();
|
|
Loaded += OnLoaded;
|
|
KeyDown += (_, e) => { if (e.Key == Key.Escape) Close(); };
|
|
}
|
|
|
|
private void OnLoaded(object sender, RoutedEventArgs e)
|
|
{
|
|
// 버전 정보
|
|
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
|
VersionText.Text = version != null ? $"v{version.Major}.{version.Minor}.{version.Build}" : "v1.0";
|
|
BuildInfoText.Text = $"AX Copilot \u00b7 Commander + Agent \u00b7 \u00a9 2026";
|
|
|
|
// about.json에서 모든 텍스트 로드 (없으면 기본값 유지)
|
|
TryLoadBranding(version);
|
|
|
|
// 상단: 앱 아이콘 로드
|
|
TryLoadAppIcon();
|
|
// 마스코트: 숨겨진 상태로 로드 (사용자 클릭 시 오버레이용)
|
|
TryLoadMascot();
|
|
}
|
|
|
|
private void TryLoadBranding(Version? version)
|
|
{
|
|
try
|
|
{
|
|
var uri = new Uri("pack://application:,,,/Assets/about.json");
|
|
var info = System.Windows.Application.GetResourceStream(uri);
|
|
if (info == null) return;
|
|
|
|
using var reader = new StreamReader(info.Stream);
|
|
using var doc = JsonDocument.Parse(reader.ReadToEnd());
|
|
var root = doc.RootElement;
|
|
|
|
string Get(string key) =>
|
|
root.TryGetProperty(key, out var v) ? v.GetString() ?? "" : "";
|
|
|
|
var appName = Get("appName");
|
|
var company = Get("companyName");
|
|
var author = Get("authorName");
|
|
var title = Get("authorTitle");
|
|
var purpose = Get("purpose");
|
|
var copyright = Get("copyright");
|
|
var blogUrl = Get("blogUrl");
|
|
|
|
// 앱 이름 (헤더)
|
|
if (!string.IsNullOrWhiteSpace(appName))
|
|
AppNameText.Text = appName;
|
|
|
|
// 회사명 (조직명만 표시 — 이름/직급은 하단에 별도 표시)
|
|
if (!string.IsNullOrWhiteSpace(company))
|
|
CompanyNameText.Text = company;
|
|
|
|
// 목적
|
|
if (!string.IsNullOrWhiteSpace(purpose))
|
|
PurposeText.Text = purpose;
|
|
|
|
// 저작권 + 빌드 정보
|
|
if (!string.IsNullOrWhiteSpace(copyright))
|
|
{
|
|
var ver = version != null ? $"v{version.Major}.{version.Minor}.{version.Build}" : "v1.0";
|
|
BuildInfoText.Text = $"{appName} \u00b7 {ver} \u00b7 Commander + Agent \u00b7 {copyright}";
|
|
}
|
|
|
|
// 블로그 URL
|
|
if (!string.IsNullOrWhiteSpace(blogUrl) && BlogLinkBtn != null)
|
|
BlogLinkBtn.Content = blogUrl;
|
|
|
|
// 기여자 목록
|
|
var contributors = Get("contributors");
|
|
if (!string.IsNullOrWhiteSpace(contributors))
|
|
{
|
|
ContributorsText.Text = contributors;
|
|
ContributorsGrid.Visibility = Visibility.Visible;
|
|
}
|
|
}
|
|
catch { /* 브랜딩 로드 실패 시 기본값 유지 */ }
|
|
}
|
|
|
|
private void TryLoadAppIcon()
|
|
{
|
|
try
|
|
{
|
|
var uri = new Uri("pack://application:,,,/Assets/icon.ico");
|
|
var stream = System.Windows.Application.GetResourceStream(uri)?.Stream;
|
|
if (stream != null)
|
|
{
|
|
var bmp = new BitmapImage();
|
|
bmp.BeginInit();
|
|
bmp.StreamSource = stream;
|
|
bmp.CacheOption = BitmapCacheOption.OnLoad;
|
|
bmp.DecodePixelWidth = 176;
|
|
bmp.EndInit();
|
|
bmp.Freeze();
|
|
|
|
AppIconImage.Source = bmp;
|
|
FallbackIcon.Visibility = Visibility.Collapsed;
|
|
}
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
private void TryLoadMascot()
|
|
{
|
|
// 내장 리소스에서 마스코트 로드 (오버레이용, 상단에는 표시 안 함)
|
|
foreach (var name in new[] { "mascot.png", "mascot.jpg", "mascot.webp" })
|
|
{
|
|
try
|
|
{
|
|
var uri = new Uri($"pack://application:,,,/Assets/{name}");
|
|
var stream = System.Windows.Application.GetResourceStream(uri)?.Stream;
|
|
if (stream == null) continue;
|
|
|
|
var bmp = new BitmapImage();
|
|
bmp.BeginInit();
|
|
bmp.StreamSource = stream;
|
|
bmp.CacheOption = BitmapCacheOption.OnLoad;
|
|
bmp.DecodePixelWidth = 400;
|
|
bmp.EndInit();
|
|
bmp.Freeze();
|
|
|
|
MascotImage.Source = bmp;
|
|
return;
|
|
}
|
|
catch { }
|
|
}
|
|
|
|
// 파일 시스템 폴백
|
|
var exeDir = Path.GetDirectoryName(Environment.ProcessPath) ?? AppContext.BaseDirectory;
|
|
foreach (var name in new[] { "mascot.png", "mascot.jpg", "mascot.webp" })
|
|
{
|
|
var path = Path.Combine(exeDir, "Assets", name);
|
|
if (!File.Exists(path)) continue;
|
|
try
|
|
{
|
|
var bmp = new BitmapImage();
|
|
bmp.BeginInit();
|
|
bmp.UriSource = new Uri(path, UriKind.Absolute);
|
|
bmp.CacheOption = BitmapCacheOption.OnLoad;
|
|
bmp.DecodePixelWidth = 400;
|
|
bmp.EndInit();
|
|
|
|
MascotImage.Source = bmp;
|
|
return;
|
|
}
|
|
catch { }
|
|
}
|
|
}
|
|
|
|
private void ShowMascot_Click(object sender, MouseButtonEventArgs e)
|
|
{
|
|
if (MascotImage.Source == null) return;
|
|
MascotOverlayImage.Source = MascotImage.Source;
|
|
MascotOverlay.Visibility = Visibility.Visible;
|
|
e.Handled = true; // DragMove 방지
|
|
}
|
|
|
|
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 { /* 브라우저 열기 실패 무시 */ }
|
|
}
|
|
}
|