Skip to content

feat: 新增提醒判定源框架与热键确认链路 - #11

Open
Starsky16 wants to merge 14 commits into
Yeson38:masterfrom
Starsky16:pr/6-alert-decision-source
Open

Starsky16 wants to merge 14 commits into
Yeson38:masterfrom
Starsky16:pr/6-alert-decision-source

Conversation

@Starsky16

@Starsky16 Starsky16 commented Sep 19, 2026 •

Copy link
Copy Markdown

概述

为插件新增「提醒判定源」框架与热键确认链路:分贝提醒从单一阈值判断升级为可分别启用的判定源(自动提醒 / 热键确认),判定源按全局优先级顺序交由仲裁模块统一裁定,并与现有通知提供方对接发出强调通知。

这是分贝监测插件重构与提醒功能拆分系列的后续扩展(相对 #10 的独立上新):

变更

  • 判定源框架(Alerting/):新增 IAlertDecisionSource 接口、平均音量判定评估器、仲裁模块 AlertDecisionCoordinator(统一与通知提供方通信并发强调通知);判定源不在内部接触通知。
  • 判定源①自动提醒(AutoThresholdDecisionSource):到阈值立即提醒,独立启用开关、阈值、冷却。
  • 判定源②热键确认(HotkeyConfirmDecisionSource):到阈值只开启筛选窗口(纯逻辑、不弹 UI),窗口期内按下配置热键才提醒,窗口内没有按键则不提醒。
  • 提醒运行时编排(Alarm/AlertRuntimeService):固定节拍采样→平均分贝→仲裁→接入 DecibelNotificationProvider 发通知;执行提醒后强制暂停分贝检测 3 秒防自激。
  • 热键接入(Alarm/HotkeyWindowMonitor):动态解析 IKeyboardCaptureService(KeyboardCapture.Abstractions 0.2.0),无安装时每 2 秒重试,按键事件封送回 UI 线程再交给判定源。
  • 设置页扩充(DecibelMonitorSettingsPage):新增「提醒判定」分区——平均窗口时长、判定源优先级排序(可上移/下移,运行时生效)、自动提醒与热键确认各自的设置项;热键判定源在 KeyboardCapture 未安装时整体禁用。
  • 通知提供方精简:DecibelNotificationProviderSettings 只保留提醒文字,阈值/冷却统一上收到各判定源,消除双门槛。
  • 组件显示侧:分贝组件改为纯粹读取 AlertRuntimeService 状态,组件上只保留一个提醒状态点——绿=正常,红=提醒触发中(超阈值或处于冷却期),红绿闪动=热键筛选窗口已开启、正在等待按键确认;原先的红色提示文字已移除。
  • 新依赖:Starsky16.KeyboardCapture.Abstractions(清单中声明为可选依赖 isRequired:false,未安装时不影响其余功能)。

验证

dotnet build Decibel_Monitor.csproj -c Release
# 已成功生成:0 个警告 0 个错误

dotnet test Tests/Decibel_Monitor.Tests/Decibel_Monitor.Tests.csproj -c Release
# 已通过! - 失败: 0,通过: 79,已跳过: 0,总计: 79

已在本机 ClassIsland 实机验证(仅 Windows):

  • 自动提醒:超阈值触发“请保持安静”强调通知(遮罩/波纹特效),防自激生效。
  • 热键确认:超阈值开窗口(状态点红绿交替闪动)→ 按下配置热键 → 触发强调通知,窗口关闭后状态点变为静态红。
  • 冷却期:执行提醒后分贝回落到阈值以下时,状态点仍保持红色。
  • 设置页「提醒判定」分区渲染正常,无 XAML/绑定错误。

无头 CI 无法覆盖音频采样与 UI 交互,需实机确认。

说明

本 PR 由 AI 辅助生成。

- 新增 Services:AudioPeakMeter(门面)、AudioDeviceEnumerator(设备枚举与缓存)、ContinuousPeakCapture(常驻静默捕获流)、OneShotPeakCapture(一次性三级回退采样)、DecibelCalculator(线性峰值与显示刻度换算)、PeakSample(采样结果纯数据)。

- 新增插件全局设置 DecibelMonitorGlobalSettings 与持久化服务 DecibelMonitorSettingsService(整体反序列化,新增设置项无需同步维护)。

- Plugin.Initialize 注册全局设置服务与共享采样服务;组件将在后续 PR 切换为该服务。

- 新增 Tests/Decibel_Monitor.Tests(xunit),覆盖计算换算与采样数据纯逻辑,共 28 条用例全绿。

由 VS Code 中的 Cline 辅助生成。
- DecibelComponent 从宿主 DI 获取 AudioPeakMeter 与 DecibelMonitorSettingsService,改用 DecibelCalculator 做线性峰值到显示刻度的换算,不再自行枚举设备并三级回退采样。

- 数值改用 AvaloniaProperty(StyledProperty)绑定,移除手写的 INotifyPropertyChanged;采样 Tick 增加节流,避免异步任务堆积;放大倍数取自全局设置,同一麦克风所有组件数值一致。

- 组件设置控件精简为显示侧偏好(分贝前缀、更新频率);测量/校准与提醒设置分别移至插件设置页与通知提供方设置。

- Plugin 移除重复的 GetVoicePeakValue()。

- 编译警告由 3 个降为 0 个(原 CS0108/CS4014 随旧实现一并移除)。

由 VS Code 中的 Cline 辅助生成。
- 新增 DecibelNotificationProvider:继承 NotificationProviderBase<DecibelNotificationProviderSettings>
  以获得宿主自动持久化的通知侧设置,注册「超过分贝阈值」渠道并通过 Channel(...) 发送,与内置通知提供方保持一致。
- 提醒判定抽为纯函数 DecibelAlertEvaluator.Evaluate(...):严格大于阈值才触发、冷却期内不重复通知;
  配套 9 条边界单元测试(等于阈值不触发、冷却中不通知、冷却刚过可通知、冷却下限 1 分钟等),单元测试总数 37 条全绿。
- 新增通知侧设置控件:启用提醒、阈值(dB)、提醒文字、冷却时间(分钟)。
- 组件展示评估结果:超阈值时显示红色提示文字,可用组件设置里的「组件内提示」关闭(关闭后仍照常发送通知);
  提供方实例动态读取,避免组件先于 IHostedService 创建导致提醒永久失效。
- README 补充阈值提醒的使用方式、设置项与排查说明。

由 VS Code 中的 Cline 辅助生成。
- 新增插件设置页(设置 → Decibel_Monitor,External 分类):全局校准(参考 dB 0..150、放大倍数、校准按钮)、
  持续监听麦克风与采样参数、默认捕获设备信息与捕获设备列表诊断。
- 校准改为调用 AudioPeakMeter.CaptureSamplePeakAsync 显式采样一次,结果写入全局放大倍数,
  插件内所有组件立即生效(同一麦克风各组件数值一致)。
- Plugin 注册设置页;Decibel_Monitor.csproj 补充设置页 XAML 与代码后置的 DependentUpon。
- README 更新:设置分布(组件设置 / 通知设置 / 插件设置页三处)、校准位置由组件设置改为插件设置页、
  补充全局设置项与故障排查说明。

由 VS Code 中的 Cline 辅助生成。
- IntegrationTest.yml:下载官方 ClassIsland 2.1.0.1 folder 包,用 -epp 加载本插件并启动,
  轮询等待插件写入 loaded.marker 以确认 Initialize 完整执行(注册组件与提醒提供方无异常);
  超时或进程提前退出即失败,并在失败时打印 AppRoot 目录便于排查。
- Plugin:设置 DECIBEL_MONITOR_CI_MARKER=1 时向插件配置目录写入 loaded.marker,供上述工作流判定加载成功;
  未设置该环境变量时行为与原来完全一致。
- Build.yml / Test.yml:构建与单元测试步骤对齐现有工程(tools/publish.ps1、Tests/Decibel_Monitor.Tests)。

由 VS Code 中的 Cline 辅助生成。
组件由宿主从 DI 根容器以瞬态方式解析且从不调用释放方法,原实现在构造函数中启动 DispatcherTimer:已启动的定时器被 Dispatcher 强引用,Tick 闭包会永久钉住组件实例,导致组件重建后旧实例与定时器都无法回收。改为随视觉树附着/分离启停定时器,并移除不再需要的 IDisposable。

已知行为变化:组件不在视觉树上时不再采样,依赖 Tick 的阈值提醒在组件离树期间不会触发。
- 新增 AverageVolumeAlertEvaluator(滑动窗口平均判定,严格大于阈值)

- 新增判定源抽象 IAlertDecisionSource 与 AlertContext/AlertDecision 契约

- 新增判定源①AutoThresholdDecisionSource:超阈值且冷却已过即提醒

- 新增判定源②HotkeyConfirmDecisionSource:超阈值开筛选窗口,窗口内命中热键才提醒

- 新增仲裁模块 AlertDecisionCoordinator:自持优先级配置、统一归口发出通知事件

- 测试工程链接上述纯逻辑源文件,新增 43 条用例(共 80 条全绿)
- Alarm/HotkeyWindowMonitor:经 IAppHost 动态解析 KeyboardCapture 全局键盘服务
  (非必需依赖,未解析到则定时重试降级为空转),把筛选窗口期间的 KeyDown
  封送回 UI 线程并映射修饰键后转发给热键判定源,暴露窗口开关状态事件供组件红绿点。
- Alarm/AlertRuntimeService:周期采样构造判定上下文交由仲裁模块裁定,
  经 NotifyRequested 统一接入现有通知提供方发出强调通知(语音由宿主负责),
  执行提醒后进入 3 秒防自激暂停分贝采样判定并清空样本窗口。
- Plugin.cs:注册自动/热键两个判定源、仲裁模块及两个宿主服务(默认均未启用)。
- 通知提供方设置只保留提醒文字,阈值与冷却统一由判定源负责,消除双重门槛
- 插件设置页新增“提醒判定”分区:平均窗口时长、判定源优先级排序、自动提醒与热键确认设置
- 分贝组件改为纯显示侧,新增热键筛选窗口红/绿点指示,只读取提醒运行时服务状态
- 仲裁模块支持运行时应用判定源优先级顺序
- 组件不再显示提醒文字,统一为单一状态点:绿=正常,红=提醒触发中(含筛选窗口开启与冷却期)
- 判定源接口新增 Description 与 IsCoolingDown,供设置页展示与状态点判定
- 设置页补全判定源分组名(判定源①/②)、阈值与冷却/窗口时长滑块的数值显示、优先级列表说明
- 组件设置项 ShowAlertTextOnComponent 改为 ShowStatusIndicator(组件上不再有提醒文字)
- 窗口开启期间状态点在红绿之间交替(400ms 半周期),与静态红/绿区分开
- 窗口开启时组件更新节拍收紧到闪烁半周期,避免更新频率设置高时看不出闪动
- 组件设置说明与设置页描述同步补充闪动含义
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant