feat: Claude Code 原生 Windows 通知(C# / .NET 10 + Avalonia 12)
为 Claude Code 提供原生 Windows toast 通知:点击跳回原窗口、切回 Windows Terminal 标签、跨虚拟桌面、调用方图标、非阻塞投递;NativeAOT 单文件分发。
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
namespace Notify.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 每会话持久化的状态,由 save 钩子写入、notify 钩子与点击激活读取
|
||||
/// </summary>
|
||||
public sealed class StateData
|
||||
{
|
||||
// 触发时的前台窗口句柄
|
||||
public long Hwnd { get; set; }
|
||||
|
||||
// 用户当次输入的 prompt,用作"任务完成"通知的正文
|
||||
public string Prompt { get; set; } = "";
|
||||
|
||||
// 若前台是 Windows Terminal,记录当时选中标签的 RuntimeId,用于点击后切回
|
||||
public string WtRuntimeId { get; set; } = "";
|
||||
|
||||
// 调用方 App 的 exe 路径,用于提取并显示其图标
|
||||
public string CallerExePath { get; set; } = "";
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
namespace Notify.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 一次弹窗请求(后续由 hook / named pipe 投递)
|
||||
/// </summary>
|
||||
public sealed class ToastRequest
|
||||
{
|
||||
public required string Title { get; init; }
|
||||
|
||||
public required string Message { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// true = 需要输入(黄色边框),false = 任务完成(橙色边框)
|
||||
/// </summary>
|
||||
public bool InputMode { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// true = 常驻:不自动消失,只能点击 / ✕ 关闭
|
||||
/// </summary>
|
||||
public bool Sticky { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 点击 toast 主体时要激活的窗口句柄,0 表示不激活
|
||||
/// </summary>
|
||||
public long TargetHwnd { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 目标若为 Windows Terminal,激活后要切回的标签 RuntimeId
|
||||
/// </summary>
|
||||
public string? WtRuntimeId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 调用方 App 的 exe 路径,用于显示其图标
|
||||
/// </summary>
|
||||
public string? IconPath { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// 覆盖停留秒数;为 null 时用设置里的默认值
|
||||
/// </summary>
|
||||
public int? DurationSecondsOverride { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
namespace Notify.Models;
|
||||
|
||||
/// <summary>
|
||||
/// 水平方向:决定 toast 贴左/居中/贴右
|
||||
/// </summary>
|
||||
public enum HEdge
|
||||
{
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 垂直方向:决定 toast 贴上/居中/贴下,并决定堆叠方向
|
||||
/// </summary>
|
||||
public enum VEdge
|
||||
{
|
||||
Top,
|
||||
Center,
|
||||
Bottom,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 持久化的弹窗设置(纯数据模型,序列化到磁盘)
|
||||
/// </summary>
|
||||
public sealed class ToastSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// 自动消失前的停留秒数
|
||||
/// </summary>
|
||||
public int DurationSeconds { get; set; } = 4;
|
||||
|
||||
/// <summary>
|
||||
/// 目标窗口已在前台时的停留秒数(你正盯着看,弹一下即可)
|
||||
/// </summary>
|
||||
public int FocusedDurationSeconds { get; set; } = 2;
|
||||
|
||||
/// <summary>
|
||||
/// 水平方向
|
||||
/// </summary>
|
||||
public HEdge Horizontal { get; set; } = HEdge.Right;
|
||||
|
||||
/// <summary>
|
||||
/// 垂直方向
|
||||
/// </summary>
|
||||
public VEdge Vertical { get; set; } = VEdge.Bottom;
|
||||
|
||||
/// <summary>
|
||||
/// 与屏幕边缘的留白(DIP)
|
||||
/// </summary>
|
||||
public int Margin { get; set; } = 12;
|
||||
|
||||
/// <summary>
|
||||
/// 不透明度 0–1
|
||||
/// </summary>
|
||||
public double Opacity { get; set; } = 0.96;
|
||||
|
||||
/// <summary>
|
||||
/// 最多同时可见的 toast 数量,超出则排队
|
||||
/// </summary>
|
||||
public int MaxVisible { get; set; } = 5;
|
||||
|
||||
/// <summary>
|
||||
/// 是否播放提示音
|
||||
/// </summary>
|
||||
public bool PlaySound { get; set; } = true;
|
||||
|
||||
/// <summary>
|
||||
/// toast 宽度(DIP)
|
||||
/// </summary>
|
||||
public double Width { get; set; } = 340;
|
||||
|
||||
/// <summary>
|
||||
/// 淡入/淡出时长(毫秒)
|
||||
/// </summary>
|
||||
public int FadeMilliseconds { get; set; } = 300;
|
||||
|
||||
/// <summary>
|
||||
/// 跨所有虚拟桌面显示(未公开 API,失败自动退回单桌面)
|
||||
/// </summary>
|
||||
public bool ShowOnAllDesktops { get; set; } = true;
|
||||
|
||||
public ToastSettings Clone() => (ToastSettings)MemberwiseClone();
|
||||
}
|
||||
Reference in New Issue
Block a user