cfb1b99162
- 常驻 Host:无主窗口保活 + 系统托盘菜单 - Toast 弹窗:堆叠 / 自动消失 / 悬停暂停 / 淡入淡出 / 点击关闭 - Sticky 常驻弹窗与 InputMode 边框配色 - 跨虚拟桌面显示(源生成 COM PinView,AOT 友好) - 设置窗口(Semi + Ursa)+ JSON 源生成持久化 - AOT 准备:IsAotCompatible 0 警告
99 lines
2.9 KiB
C#
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();
|
|
}
|
|
}
|
|
}
|