using AxCopilot.Core; using AxCopilot.SDK; using AxCopilot.Services; using AxCopilot.Themes; namespace AxCopilot.Handlers; /// /// L5-1: 전용 핫키 관리 핸들러. /// 예: hotkey → 등록된 전용 핫키 목록 표시 /// hotkey 1doc → 라벨 또는 대상에 "1doc" 포함 항목 필터 /// Enter 시 해당 핫키 항목의 대상을 실행합니다. /// public class HotkeyHandler : IActionHandler { private readonly SettingsService? _settings; public HotkeyHandler(SettingsService? settings = null) { _settings = settings; } public string? Prefix => "hotkey"; public PluginMetadata Metadata => new( "HotkeyManager", "전용 핫키 목록 관리", "1.0", "AX"); public Task> GetItemsAsync(string query, CancellationToken ct) { var items = new List(); var hotkeys = _settings?.Settings.CustomHotkeys ?? new List(); if (hotkeys.Count == 0) { items.Add(new LauncherItem( "등록된 전용 핫키 없음", "설정 → 전용 핫키 탭에서 항목별 글로벌 단축키를 등록하세요", null, "__open_settings__", Symbol: "\uE713")); return Task.FromResult>(items); } var filter = query.Trim().ToLowerInvariant(); foreach (var h in hotkeys) { if (!string.IsNullOrEmpty(filter) && !h.Label.Contains(filter, StringComparison.OrdinalIgnoreCase) && !h.Hotkey.Contains(filter, StringComparison.OrdinalIgnoreCase) && !h.Target.Contains(filter, StringComparison.OrdinalIgnoreCase)) continue; var typeSymbol = h.Type switch { "url" => Symbols.Globe, "folder" => Symbols.Folder, "command" => "\uE756", _ => Symbols.App }; var label = string.IsNullOrWhiteSpace(h.Label) ? System.IO.Path.GetFileNameWithoutExtension(h.Target) : h.Label; items.Add(new LauncherItem( $"[{h.Hotkey}] {label}", h.Target, null, h, Symbol: typeSymbol)); } // 설정 단축키 안내 항목 items.Add(new LauncherItem( "전용 핫키 설정 열기", "설정 → 전용 핫키 탭에서 핫키를 추가하거나 제거합니다", null, "__open_settings__", Symbol: "\uE713")); return Task.FromResult>(items); } public Task ExecuteAsync(LauncherItem item, CancellationToken ct) { if (item.Data is string s && s == "__open_settings__") { System.Windows.Application.Current.Dispatcher.Invoke(() => { var app = System.Windows.Application.Current as AxCopilot.App; app?.OpenSettingsFromChat(); }); return Task.CompletedTask; } if (item.Data is Models.HotkeyAssignment ha) { ExecuteHotkeyTarget(ha.Target, ha.Type); } return Task.CompletedTask; } /// 전용 핫키 대상을 타입에 따라 실행합니다. internal static void ExecuteHotkeyTarget(string target, string type) { try { switch (type) { case "url": System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = target, UseShellExecute = true }); break; case "folder": System.Diagnostics.Process.Start("explorer.exe", target); break; case "command": var parts = target.Split(' ', 2, StringSplitOptions.RemoveEmptyEntries); var cmdFile = parts[0]; var cmdArgs = parts.Length > 1 ? parts[1] : ""; System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = cmdFile, Arguments = cmdArgs, UseShellExecute = true }); break; default: // app System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo { FileName = target, UseShellExecute = true }); break; } Services.LogService.Info($"전용 핫키 실행: {target} ({type})"); } catch (Exception ex) { Services.LogService.Error($"전용 핫키 실행 오류: {target} — {ex.Message}"); } } }