Document service account choices for AD-aware hooks #1
@@ -1,13 +1,5 @@
|
||||
using System.Configuration;
|
||||
using System.Data;
|
||||
using System.Windows;
|
||||
|
||||
namespace WebhookServer.Gui;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for App.xaml
|
||||
/// </summary>
|
||||
public partial class App : Application
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Media;
|
||||
using Brush = System.Windows.Media.Brush;
|
||||
using Brushes = System.Windows.Media.Brushes;
|
||||
|
||||
namespace WebhookServer.Gui.Converters;
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
// Enabling UseWindowsForms (for the system tray NotifyIcon) brings the WinForms
|
||||
// namespace into scope, which conflicts with WPF for several common type names.
|
||||
// Alias the most-used types to their WPF variants project-wide so existing code
|
||||
// keeps compiling. Files that genuinely need a WinForms type import it explicitly
|
||||
// (System.Windows.Forms.NotifyIcon etc. in Services/TrayIcon.cs).
|
||||
|
||||
global using Application = System.Windows.Application;
|
||||
global using MessageBox = System.Windows.MessageBox;
|
||||
global using Clipboard = System.Windows.Clipboard;
|
||||
global using TextBox = System.Windows.Controls.TextBox;
|
||||
global using RadioButton = System.Windows.Controls.RadioButton;
|
||||
global using MessageBoxButton = System.Windows.MessageBoxButton;
|
||||
global using MessageBoxImage = System.Windows.MessageBoxImage;
|
||||
global using MessageBoxResult = System.Windows.MessageBoxResult;
|
||||
global using Binding = System.Windows.Data.Binding;
|
||||
@@ -8,12 +8,37 @@ namespace WebhookServer.Gui;
|
||||
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
private readonly TrayIcon _tray;
|
||||
private readonly MainViewModel _vm;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
var vm = new MainViewModel(new AdminPipeClient());
|
||||
DataContext = vm;
|
||||
Loaded += async (_, _) => await vm.RefreshCommand.ExecuteAsync(null);
|
||||
_vm = new MainViewModel(new AdminPipeClient());
|
||||
DataContext = _vm;
|
||||
|
||||
_tray = new TrayIcon(
|
||||
resolveMainWindow: () => Application.Current.MainWindow,
|
||||
restartServiceAsync: async () => await new AdminPipeClient().RestartListenerAsync());
|
||||
|
||||
Loaded += async (_, _) => await _vm.RefreshCommand.ExecuteAsync(null);
|
||||
StateChanged += OnStateChanged;
|
||||
Closed += (_, _) => _tray.Dispose();
|
||||
}
|
||||
|
||||
private void OnStateChanged(object? sender, EventArgs e)
|
||||
{
|
||||
// Minimize-to-tray: hide the window when the user minimizes; restoring is
|
||||
// via the tray icon's double-click or context menu.
|
||||
if (WindowState == WindowState.Minimized)
|
||||
{
|
||||
Hide();
|
||||
ShowInTaskbar = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowInTaskbar = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnLogTailChanged(object sender, TextChangedEventArgs e)
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
using System.Drawing;
|
||||
using System.Runtime.Versioning;
|
||||
using System.Windows;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace WebhookServer.Gui.Services;
|
||||
|
||||
/// <summary>
|
||||
/// Minimal system tray icon using Windows Forms NotifyIcon. Owns a context menu
|
||||
/// (Open / Restart service / Exit) and toggles the main window visibility on
|
||||
/// double-click. Hide-to-tray on minimize is wired in MainWindow.xaml.cs.
|
||||
/// </summary>
|
||||
[SupportedOSPlatform("windows")]
|
||||
public sealed class TrayIcon : IDisposable
|
||||
{
|
||||
private readonly NotifyIcon _icon;
|
||||
private readonly Func<Window?> _resolveMainWindow;
|
||||
private readonly Func<Task> _restartServiceAsync;
|
||||
|
||||
public TrayIcon(Func<Window?> resolveMainWindow, Func<Task> restartServiceAsync)
|
||||
{
|
||||
_resolveMainWindow = resolveMainWindow;
|
||||
_restartServiceAsync = restartServiceAsync;
|
||||
|
||||
_icon = new NotifyIcon
|
||||
{
|
||||
Icon = LoadEmbeddedIcon(),
|
||||
Text = "Webhook Server",
|
||||
Visible = true,
|
||||
};
|
||||
_icon.DoubleClick += (_, _) => ShowMainWindow();
|
||||
_icon.ContextMenuStrip = BuildMenu();
|
||||
}
|
||||
|
||||
private ContextMenuStrip BuildMenu()
|
||||
{
|
||||
var menu = new ContextMenuStrip();
|
||||
menu.Items.Add("&Open Webhook Server", null, (_, _) => ShowMainWindow());
|
||||
menu.Items.Add(new ToolStripSeparator());
|
||||
menu.Items.Add("&Restart service", null, async (_, _) => await _restartServiceAsync().ConfigureAwait(false));
|
||||
menu.Items.Add(new ToolStripSeparator());
|
||||
menu.Items.Add("E&xit", null, (_, _) => Application.Current.Shutdown());
|
||||
return menu;
|
||||
}
|
||||
|
||||
private void ShowMainWindow()
|
||||
{
|
||||
var w = _resolveMainWindow();
|
||||
if (w is null) return;
|
||||
if (w.WindowState == WindowState.Minimized) w.WindowState = WindowState.Normal;
|
||||
w.Show();
|
||||
w.Activate();
|
||||
w.Topmost = true;
|
||||
w.Topmost = false;
|
||||
}
|
||||
|
||||
private static Icon LoadEmbeddedIcon()
|
||||
{
|
||||
// Pulled from the WPF Resource items in the csproj via the application
|
||||
// pack URI. Falling back to SystemIcons keeps the tray usable if the
|
||||
// resource is somehow missing.
|
||||
try
|
||||
{
|
||||
var uri = new Uri("pack://application:,,,/webhook-server.ico", UriKind.Absolute);
|
||||
using var stream = Application.GetResourceStream(uri).Stream;
|
||||
return new Icon(stream);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return SystemIcons.Application;
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowBalloon(string title, string message)
|
||||
{
|
||||
_icon.BalloonTipTitle = title;
|
||||
_icon.BalloonTipText = message;
|
||||
_icon.ShowBalloonTip(3000);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_icon.Visible = false;
|
||||
_icon.Dispose();
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<UseWPF>true</UseWPF>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<ApplicationIcon>..\..\resources\webhook-server.ico</ApplicationIcon>
|
||||
<AssemblyTitle>Webhook Server</AssemblyTitle>
|
||||
</PropertyGroup>
|
||||
|
||||
Reference in New Issue
Block a user