using System.Drawing; using System.IO; using System.Windows.Forms; namespace WindowsGotify.Tray; public sealed class TrayIconService : IDisposable { private readonly NotifyIcon _notifyIcon; private readonly Action _onShowSettings; private readonly Func _onTest; private readonly Action _onReconnect; private readonly Action _onExit; public TrayIconService( Action onShowSettings, Func onTest, Action onReconnect, Action onExit) { _onShowSettings = onShowSettings; _onTest = onTest; _onReconnect = onReconnect; _onExit = onExit; var menu = new ContextMenuStrip(); var showItem = new ToolStripMenuItem("打开设置 / 查看历史"); showItem.Click += (_, _) => _onShowSettings(); var testItem = new ToolStripMenuItem("测试通知"); testItem.Click += async (_, _) => await _onTest(); var reconnectItem = new ToolStripMenuItem("重新连接"); reconnectItem.Click += (_, _) => _onReconnect(); var exitItem = new ToolStripMenuItem("退出"); exitItem.Click += (_, _) => _onExit(); menu.Items.Add(showItem); menu.Items.Add(testItem); menu.Items.Add(reconnectItem); menu.Items.Add(new ToolStripSeparator()); menu.Items.Add(exitItem); _notifyIcon = new NotifyIcon { Icon = LoadMascotIcon(), Visible = true, Text = "Windows Gotify", ContextMenuStrip = menu }; _notifyIcon.DoubleClick += (_, _) => _onShowSettings(); } public void SetStatus(string status) { try { var text = $"Gotify: {status}"; _notifyIcon.Text = text.Length <= 63 ? text : text[..63]; } catch { // ignore tray update failures } } public void Dispose() { _notifyIcon.Visible = false; _notifyIcon.Dispose(); } private static Icon LoadMascotIcon() { // EXE 同目录下优先(发布后),其次源码 Assets 目录(dev),最后回退到系统默认图标 var exeDir = AppContext.BaseDirectory; var candidates = new[] { Path.Combine(exeDir, "Assets", "gotify-mascot.ico"), Path.Combine(exeDir, "gotify-mascot.ico"), }; foreach (var p in candidates) { if (File.Exists(p)) { try { return new Icon(p); } catch { /* 损坏的 ICO 文件,继续找下一个 */ } } } return SystemIcons.Application; } }