162 lines
4.8 KiB
C#
162 lines
4.8 KiB
C#
using System.IO;
|
|
using System.Threading;
|
|
using System.Windows;
|
|
using Forms = System.Windows.Forms;
|
|
|
|
namespace OmniNotify;
|
|
|
|
public partial class App : System.Windows.Application
|
|
{
|
|
private const string SingleInstanceMutexName = @"Local\OmniNotify.SingleInstance";
|
|
private const string ActivateEventName = @"Local\OmniNotify.Activate";
|
|
private Forms.NotifyIcon? _notifyIcon;
|
|
private AppStore? _store;
|
|
private LocalHttpServer? _server;
|
|
private Mutex? _singleInstanceMutex;
|
|
private bool _ownsSingleInstanceMutex;
|
|
private EventWaitHandle? _activateEvent;
|
|
private RegisteredWaitHandle? _activateWait;
|
|
|
|
public AppState State { get; private set; } = new();
|
|
public NotificationRouter Router { get; private set; } = null!;
|
|
public PopupCoordinator PopupCoordinator { get; private set; } = null!;
|
|
public string ListenUrl => _server?.Url ?? "";
|
|
public string? ServerError => _server?.LastError;
|
|
|
|
protected override void OnStartup(StartupEventArgs e)
|
|
{
|
|
_singleInstanceMutex = new Mutex(true, SingleInstanceMutexName, out var createdNew);
|
|
_ownsSingleInstanceMutex = createdNew;
|
|
_activateEvent = new EventWaitHandle(false, EventResetMode.AutoReset, ActivateEventName);
|
|
if (!createdNew)
|
|
{
|
|
_activateEvent.Set();
|
|
Shutdown();
|
|
return;
|
|
}
|
|
|
|
RegisterActivationListener();
|
|
base.OnStartup(e);
|
|
|
|
_store = new AppStore();
|
|
State = _store.Load();
|
|
PopupCoordinator = new PopupCoordinator();
|
|
Router = new NotificationRouter(State, _store, PopupCoordinator);
|
|
Router.StateChanged += UpdateTrayMenu;
|
|
|
|
_server = new LocalHttpServer(Router);
|
|
_server.Start(State.Settings.LocalPort);
|
|
|
|
CreateTrayIcon();
|
|
}
|
|
|
|
public void SaveState()
|
|
{
|
|
_store?.Save(State);
|
|
UpdateTrayMenu();
|
|
}
|
|
|
|
public void ShowMainWindow()
|
|
{
|
|
if (MainWindow is null)
|
|
{
|
|
MainWindow = new MainWindow();
|
|
}
|
|
|
|
MainWindow.Show();
|
|
MainWindow.WindowState = WindowState.Normal;
|
|
MainWindow.Activate();
|
|
}
|
|
|
|
public void ToggleMainWindow()
|
|
{
|
|
if (MainWindow?.IsVisible == true)
|
|
{
|
|
MainWindow.Hide();
|
|
return;
|
|
}
|
|
|
|
ShowMainWindow();
|
|
}
|
|
|
|
private void RegisterActivationListener()
|
|
{
|
|
if (_activateEvent is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_activateWait = ThreadPool.RegisterWaitForSingleObject(
|
|
_activateEvent,
|
|
(_, _) => Dispatcher.Invoke(ShowMainWindow),
|
|
null,
|
|
Timeout.InfiniteTimeSpan,
|
|
false);
|
|
}
|
|
|
|
private void CreateTrayIcon()
|
|
{
|
|
_notifyIcon = new Forms.NotifyIcon
|
|
{
|
|
Icon = System.Drawing.Icon.ExtractAssociatedIcon(Environment.ProcessPath ?? "") ?? System.Drawing.SystemIcons.Application,
|
|
Text = "Omni-Notify",
|
|
Visible = true
|
|
};
|
|
_notifyIcon.MouseClick += (_, args) =>
|
|
{
|
|
if (args.Button == Forms.MouseButtons.Left)
|
|
{
|
|
Dispatcher.Invoke(ToggleMainWindow);
|
|
}
|
|
};
|
|
UpdateTrayMenu();
|
|
}
|
|
|
|
private void UpdateTrayMenu()
|
|
{
|
|
if (_notifyIcon is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var menu = new Forms.ContextMenuStrip();
|
|
menu.Items.Add("打开主控制面板", null, (_, _) => Dispatcher.Invoke(ShowMainWindow));
|
|
menu.Items.Add("全局设置", null, (_, _) => Dispatcher.Invoke(() =>
|
|
{
|
|
ShowMainWindow();
|
|
if (MainWindow is MainWindow window)
|
|
{
|
|
window.FocusSettingsTab();
|
|
}
|
|
}));
|
|
menu.Items.Add(State.Settings.DndEnabled ? "关闭免打扰" : "开启免打扰", null, (_, _) => Dispatcher.Invoke(() =>
|
|
{
|
|
State.Settings.DndEnabled = !State.Settings.DndEnabled;
|
|
SaveState();
|
|
}));
|
|
|
|
var resetBreaker = menu.Items.Add("解除熔断", null, (_, _) => Dispatcher.Invoke(() => Router.ResetCircuitBreaker()));
|
|
resetBreaker.Enabled = State.Settings.CircuitBreakerOpen;
|
|
resetBreaker.ForeColor = State.Settings.CircuitBreakerOpen ? System.Drawing.Color.Firebrick : System.Drawing.SystemColors.ControlText;
|
|
|
|
menu.Items.Add(new Forms.ToolStripSeparator());
|
|
menu.Items.Add("退出软件", null, (_, _) => Dispatcher.Invoke(Shutdown));
|
|
_notifyIcon.ContextMenuStrip = menu;
|
|
}
|
|
|
|
protected override void OnExit(ExitEventArgs e)
|
|
{
|
|
_activateWait?.Unregister(null);
|
|
_activateEvent?.Dispose();
|
|
if (_ownsSingleInstanceMutex)
|
|
{
|
|
_singleInstanceMutex?.ReleaseMutex();
|
|
}
|
|
_singleInstanceMutex?.Dispose();
|
|
_notifyIcon?.Dispose();
|
|
_server?.Dispose();
|
|
_store?.Save(State);
|
|
base.OnExit(e);
|
|
}
|
|
}
|