feat(app): 初始化自动关机工具首个版本
实现基于 WPF 的 AutoShutdown 主界面,支持关机、重启、睡眠、休眠、唤醒、锁屏和注销等电源任务。 支持指定时间和倒计时计划、执行前提醒、系统关机撤销、Windows 唤醒任务、托盘运行、自定义图标以及 OmniNotify 通知适配。 修复关闭到托盘时的运行提醒,并支持单击托盘图标打开或收起主界面。 补充 README、发布配置和 win-x64 Release 输出要求。 Release: win-x64
This commit is contained in:
220
NotificationSettingsWindow.cs
Normal file
220
NotificationSettingsWindow.cs
Normal file
@@ -0,0 +1,220 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using AutoShutdown.Models;
|
||||
using AutoShutdown.Services;
|
||||
using WpfBrush = System.Windows.Media.Brush;
|
||||
using WpfBrushes = System.Windows.Media.Brushes;
|
||||
using WpfButton = System.Windows.Controls.Button;
|
||||
using WpfCursors = System.Windows.Input.Cursors;
|
||||
using WpfFontFamily = System.Windows.Media.FontFamily;
|
||||
using WpfOrientation = System.Windows.Controls.Orientation;
|
||||
using WpfRadioButton = System.Windows.Controls.RadioButton;
|
||||
using WpfTextBox = System.Windows.Controls.TextBox;
|
||||
|
||||
namespace AutoShutdown;
|
||||
|
||||
internal sealed class NotificationSettingsWindow : Window
|
||||
{
|
||||
private readonly NotificationService _notificationService;
|
||||
private readonly WpfRadioButton _localMode = new() { Content = "软件本身" };
|
||||
private readonly WpfRadioButton _omniNotifyMode = new() { Content = "OmniNotify" };
|
||||
private readonly WpfTextBox _endpoint = new();
|
||||
private readonly WpfTextBox _channel = new();
|
||||
private readonly TextBlock _status = new();
|
||||
|
||||
public NotificationSettings Settings { get; private set; }
|
||||
|
||||
public NotificationSettingsWindow(NotificationSettings settings, NotificationService notificationService)
|
||||
{
|
||||
_notificationService = notificationService;
|
||||
Settings = new NotificationSettings
|
||||
{
|
||||
Mode = settings.Mode,
|
||||
OmniNotifyEndpoint = settings.OmniNotifyEndpoint,
|
||||
Channel = settings.Channel
|
||||
};
|
||||
|
||||
Title = "OmniNotify 适配设置";
|
||||
Width = 640;
|
||||
SizeToContent = SizeToContent.Height;
|
||||
MinWidth = 640;
|
||||
MaxWidth = 640;
|
||||
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
||||
ResizeMode = ResizeMode.NoResize;
|
||||
Background = BrushFrom("#F6F8FC");
|
||||
FontFamily = new WpfFontFamily("Microsoft YaHei UI");
|
||||
FontSize = 14;
|
||||
|
||||
Content = BuildContent();
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
private UIElement BuildContent()
|
||||
{
|
||||
var host = new Grid
|
||||
{
|
||||
Background = BrushFrom("#F6F8FC")
|
||||
};
|
||||
|
||||
var root = new Border
|
||||
{
|
||||
Background = BrushFrom("#FFFFFF"),
|
||||
CornerRadius = new CornerRadius(12),
|
||||
Padding = new Thickness(26),
|
||||
Margin = new Thickness(22)
|
||||
};
|
||||
|
||||
var stack = new StackPanel();
|
||||
root.Child = stack;
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "通知方式",
|
||||
FontSize = 22,
|
||||
FontWeight = FontWeights.Bold,
|
||||
Foreground = BrushFrom("#111827")
|
||||
});
|
||||
|
||||
stack.Children.Add(new TextBlock
|
||||
{
|
||||
Text = "选择提示由 AutoShutdown 弹窗显示,或发送给本机 OmniNotify。",
|
||||
Margin = new Thickness(0, 4, 0, 20),
|
||||
Foreground = BrushFrom("#64748B"),
|
||||
TextWrapping = TextWrapping.Wrap
|
||||
});
|
||||
|
||||
stack.Children.Add(MakeLabel("提示模式"));
|
||||
var modeRow = new StackPanel { Orientation = WpfOrientation.Horizontal, Margin = new Thickness(0, 8, 0, 18) };
|
||||
StyleRadio(_localMode);
|
||||
StyleRadio(_omniNotifyMode);
|
||||
_localMode.Margin = new Thickness(0, 0, 22, 0);
|
||||
modeRow.Children.Add(_localMode);
|
||||
modeRow.Children.Add(_omniNotifyMode);
|
||||
stack.Children.Add(modeRow);
|
||||
|
||||
stack.Children.Add(MakeLabel("监听地址"));
|
||||
StyleInput(_endpoint, 536);
|
||||
_endpoint.Margin = new Thickness(0, 8, 0, 14);
|
||||
stack.Children.Add(_endpoint);
|
||||
|
||||
stack.Children.Add(MakeLabel("频道名"));
|
||||
StyleInput(_channel, 260);
|
||||
_channel.Margin = new Thickness(0, 8, 0, 12);
|
||||
stack.Children.Add(_channel);
|
||||
|
||||
_status.Text = "OmniNotify 模式需要先在 OmniNotify 中创建对应频道。";
|
||||
_status.Foreground = BrushFrom("#64748B");
|
||||
_status.TextWrapping = TextWrapping.Wrap;
|
||||
_status.Margin = new Thickness(0, 0, 0, 20);
|
||||
stack.Children.Add(_status);
|
||||
|
||||
var buttons = new StackPanel
|
||||
{
|
||||
Orientation = WpfOrientation.Horizontal,
|
||||
HorizontalAlignment = System.Windows.HorizontalAlignment.Right
|
||||
};
|
||||
var test = MakeButton("测试发送", BrushFrom("#475569"));
|
||||
test.Click += async (_, _) => await TestAsync();
|
||||
var cancel = MakeButton("取消", BrushFrom("#64748B"));
|
||||
cancel.Click += (_, _) => DialogResult = false;
|
||||
var save = MakeButton("保存", BrushFrom("#2563EB"));
|
||||
save.Click += (_, _) => SaveAndClose();
|
||||
buttons.Children.Add(test);
|
||||
buttons.Children.Add(cancel);
|
||||
buttons.Children.Add(save);
|
||||
stack.Children.Add(buttons);
|
||||
|
||||
host.Children.Add(root);
|
||||
return host;
|
||||
}
|
||||
|
||||
private void LoadSettings()
|
||||
{
|
||||
_localMode.IsChecked = Settings.Mode == NotificationMode.Local;
|
||||
_omniNotifyMode.IsChecked = Settings.Mode == NotificationMode.OmniNotify;
|
||||
_endpoint.Text = Settings.OmniNotifyEndpoint;
|
||||
_channel.Text = Settings.Channel;
|
||||
}
|
||||
|
||||
private async Task TestAsync()
|
||||
{
|
||||
var testSettings = ReadSettings();
|
||||
_status.Text = "正在发送测试消息...";
|
||||
_status.Foreground = BrushFrom("#64748B");
|
||||
var ok = await _notificationService.TestOmniNotifyAsync(testSettings);
|
||||
_status.Text = ok
|
||||
? "测试消息已发送。"
|
||||
: "测试失败,请确认 OmniNotify 正在运行、监听地址正确,并且频道已创建。";
|
||||
_status.Foreground = ok ? BrushFrom("#008060") : BrushFrom("#DC2626");
|
||||
}
|
||||
|
||||
private void SaveAndClose()
|
||||
{
|
||||
Settings = ReadSettings();
|
||||
DialogResult = true;
|
||||
}
|
||||
|
||||
private NotificationSettings ReadSettings()
|
||||
{
|
||||
return new NotificationSettings
|
||||
{
|
||||
Mode = _omniNotifyMode.IsChecked == true ? NotificationMode.OmniNotify : NotificationMode.Local,
|
||||
OmniNotifyEndpoint = string.IsNullOrWhiteSpace(_endpoint.Text) ? "http://127.0.0.1:19845/notify" : _endpoint.Text.Trim(),
|
||||
Channel = string.IsNullOrWhiteSpace(_channel.Text) ? "default" : _channel.Text.Trim()
|
||||
};
|
||||
}
|
||||
|
||||
private static TextBlock MakeLabel(string text)
|
||||
{
|
||||
return new TextBlock
|
||||
{
|
||||
Text = text,
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
Foreground = BrushFrom("#111827")
|
||||
};
|
||||
}
|
||||
|
||||
private static void StyleRadio(WpfRadioButton radio)
|
||||
{
|
||||
radio.Foreground = BrushFrom("#111827");
|
||||
radio.FontSize = 14;
|
||||
radio.Cursor = WpfCursors.Hand;
|
||||
}
|
||||
|
||||
private static void StyleInput(WpfTextBox input, double width)
|
||||
{
|
||||
input.Height = 34;
|
||||
input.Width = width;
|
||||
input.HorizontalAlignment = System.Windows.HorizontalAlignment.Left;
|
||||
input.Padding = new Thickness(10, 5, 10, 5);
|
||||
input.BorderBrush = BrushFrom("#CBD5E1");
|
||||
input.BorderThickness = new Thickness(1);
|
||||
input.Background = WpfBrushes.White;
|
||||
input.Foreground = BrushFrom("#111827");
|
||||
}
|
||||
|
||||
private static WpfButton MakeButton(string text, WpfBrush background)
|
||||
{
|
||||
var button = new WpfButton
|
||||
{
|
||||
Content = text,
|
||||
Height = 38,
|
||||
MinWidth = 92,
|
||||
Margin = new Thickness(10, 0, 0, 0),
|
||||
Padding = new Thickness(16, 0, 16, 0),
|
||||
Background = background,
|
||||
Foreground = WpfBrushes.White,
|
||||
BorderThickness = new Thickness(0),
|
||||
FontWeight = FontWeights.SemiBold,
|
||||
Cursor = WpfCursors.Hand
|
||||
};
|
||||
return button;
|
||||
}
|
||||
|
||||
private static WpfBrush BrushFrom(string hex)
|
||||
{
|
||||
return (WpfBrush)new BrushConverter().ConvertFromString(hex)!;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user