using System.IO; using System.Windows; using System.Windows.Media.Imaging; using AxCopilot.SDK; using AxCopilot.Services; using QRCoder; namespace AxCopilot.Handlers; /// /// L27-3: QR 코드 생성 핸들러. "qr" 프리픽스로 사용합니다. /// /// 예: qr https://google.com → QR 코드 생성 (Enter: 클립보드 복사) /// qr 안녕하세요 → 한국어 텍스트 QR 생성 /// qr save https://... → QR PNG 파일 저장 /// Enter → QR 이미지를 클립보드에 복사 (붙여넣기로 사용). /// public class QrHandler : IActionHandler { public string? Prefix => "qr"; public PluginMetadata Metadata => new( "QR 코드", "QR 코드 생성 — 텍스트/URL → 클립보드 PNG 복사", "1.0", "AX"); private const int PixelsPerModule = 10; public Task> GetItemsAsync(string query, CancellationToken ct) { var q = query.Trim(); var items = new List(); if (string.IsNullOrWhiteSpace(q)) { items.Add(new LauncherItem( "QR 코드 생성", "qr {텍스트 또는 URL} → Enter: QR PNG 클립보드 복사", null, null, Symbol: "\uE8C8")); return Task.FromResult>(items); } // save 명령 감지 bool saveToFile = false; var text = q; if (q.StartsWith("save ", StringComparison.OrdinalIgnoreCase)) { saveToFile = true; text = q[5..].Trim(); } if (string.IsNullOrWhiteSpace(text)) { items.Add(new LauncherItem("QR 생성할 텍스트를 입력하세요", "qr {텍스트} 또는 qr save {텍스트}", null, null, Symbol: "\uE8C8")); return Task.FromResult>(items); } int byteLen = System.Text.Encoding.UTF8.GetByteCount(text); var typeHint = Uri.TryCreate(text, UriKind.Absolute, out _) ? "URL" : "텍스트"; items.Add(new LauncherItem( $"QR 생성: {(text.Length > 60 ? text[..60] + "…" : text)}", saveToFile ? $"{typeHint} · {byteLen}바이트 · Enter: PNG 파일 저장" : $"{typeHint} · {byteLen}바이트 · Enter: PNG 클립보드 복사", null, (saveToFile ? "save" : "copy", text), Symbol: "\uE8C8")); if (!saveToFile) { items.Add(new LauncherItem( "qr save ...", "PNG 파일로 저장하려면 qr save {텍스트} 입력", null, null, Symbol: "\uE74E")); } return Task.FromResult>(items); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { if (item.Data is not (string action, string text)) return Task.CompletedTask; try { byte[] png = GenerateQrPng(text); if (action == "save") { var path = Path.Combine(Path.GetTempPath(), $"qr_{DateTime.Now:yyyyMMdd_HHmmss}.png"); File.WriteAllBytes(path, png); // 탐색기에서 파일 선택 상태로 열기 System.Diagnostics.Process.Start("explorer.exe", $"/select,\"{path}\""); NotificationService.Notify("qr", $"QR 저장: {path}"); } else { // PNG → BitmapImage → 클립보드 using var ms = new MemoryStream(png); var bitmap = new BitmapImage(); bitmap.BeginInit(); bitmap.CacheOption = BitmapCacheOption.OnLoad; bitmap.StreamSource = ms; bitmap.EndInit(); bitmap.Freeze(); Application.Current.Dispatcher.Invoke(() => Clipboard.SetImage(bitmap)); NotificationService.Notify("qr", "QR 이미지가 클립보드에 복사되었습니다."); } } catch (Exception ex) { NotificationService.Notify("qr", $"QR 생성 실패: {ex.Message}"); } return Task.CompletedTask; } private static byte[] GenerateQrPng(string text) { using var generator = new QRCodeGenerator(); using var data = generator.CreateQrCode(text, QRCodeGenerator.ECCLevel.M); using var code = new PngByteQRCode(data); return code.GetGraphic(PixelsPerModule); } }