Files
notify/Notify/App.axaml.cs
T
chuan cfb1b99162 feat: Avalonia 常驻通知应用(保活 + 弹窗 + 跨桌面)
- 常驻 Host:无主窗口保活 + 系统托盘菜单
- Toast 弹窗:堆叠 / 自动消失 / 悬停暂停 / 淡入淡出 / 点击关闭
- Sticky 常驻弹窗与 InputMode 边框配色
- 跨虚拟桌面显示(源生成 COM PinView,AOT 友好)
- 设置窗口(Semi + Ursa)+ JSON 源生成持久化
- AOT 准备:IsAotCompatible 0 警告
2026-06-22 14:25:14 +08:00

99 lines
2.9 KiB
C#

using System;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Markup.Xaml;
using Notify.Models;
using Notify.Services;
using Notify.ViewModels;
using Notify.Views;
namespace Notify;
public partial class App : Application
{
private SettingsWindow? _settingsWindow;
public static new App Current => (App)Application.Current!;
public SettingsService Settings { get; } = new();
public ToastManager Toasts { get; private set; } = null!;
public override void Initialize() => AvaloniaXamlLoader.Load(this);
public override void OnFrameworkInitializationCompleted()
{
Settings.Load();
Toasts = new ToastManager(Settings);
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
// 无主窗口的常驻进程:仅托盘存在,靠托盘菜单或外部请求驱动
desktop.ShutdownMode = ShutdownMode.OnExplicitShutdown;
// --demo:启动即弹一条 toast 并打开设置,便于无托盘交互地验证
if (desktop.Args is { Length: > 0 } args && System.Array.IndexOf(args, "--demo") >= 0)
{
Avalonia.Threading.Dispatcher.UIThread.Post(RunDemo);
}
}
base.OnFrameworkInitializationCompleted();
}
private void RunDemo()
{
// 普通:会自动消失
Toasts.Show(new ToastRequest { Title = "Claude Code", Message = "任务已完成 — 4 秒后自动消失" });
// 常驻:InputMode 且 Sticky,不点不消失
Toasts.Show(new ToastRequest
{
Title = "需要你的输入",
Message = "权限请求 — 常驻,点击 / ✕ 才关闭",
InputMode = true,
Sticky = true,
});
}
private int _counter;
private void OnTestToastClick(object? sender, EventArgs e)
{
_counter++;
var inputMode = _counter % 2 == 0;
Toasts.Show(new ToastRequest
{
Title = inputMode ? "需要你的输入" : "Claude Code",
Message = inputMode
? $"权限请求 #{_counter} — 点击跳回终端"
: $"任务已完成 #{_counter}",
InputMode = inputMode,
});
}
private void OnOpenSettingsClick(object? sender, EventArgs e)
{
if (_settingsWindow is { } w)
{
w.Activate();
return;
}
_settingsWindow = new SettingsWindow
{
DataContext = new SettingsViewModel(Settings, Toasts),
};
_settingsWindow.Closed += (_, _) => _settingsWindow = null;
_settingsWindow.Show();
}
private void OnExitClick(object? sender, EventArgs e)
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.Shutdown();
}
}
}