Skip to content

fix: 加固多窗口全局事件副作用与通知声音去重#112

Open
MiunaQwQ wants to merge 6 commits into
lehhair:mainfrom
MiunaQwQ:fix/global-event-singleton
Open

fix: 加固多窗口全局事件副作用与通知声音去重#112
MiunaQwQ wants to merge 6 commits into
lehhair:mainfrom
MiunaQwQ:fix/global-event-singleton

Conversation

@MiunaQwQ

@MiunaQwQ MiunaQwQ commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

变更说明

修复多开 OpenCodeUI 窗口时,同一个全局事件可能在多个窗口重复触发一次性副作用的问题,重点包括通知声音、当前会话提示音、toast 以及部分全局自动批准路径。

这个分支的 6 个提交分两轮完成了同一条能力链路:

  1. 先基于 localStorage TTL claim 建立跨窗口的全局副作用认领机制;
  2. 再把通知声音和当前会话提示音进一步收敛到带 Web Locks 的锁定认领流程,降低竞态下的重复播放概率。

主要改动

1. 建立全局副作用认领基础设施

  • 新增全局副作用认领工具,用 localStorage TTL claim 对一次性副作用做跨窗口 best-effort 去重。
  • 覆盖过期、损坏存储、不可用存储和延迟清理等场景。

2. 让通知声音按事件级 key 去重

  • notificationStore.push 增加可选 soundKey
  • 后台通知声音复用事件级 key,避免多个窗口对同一事件重复播放提示音。
  • 增补通知声音桥接测试,覆盖已被其他窗口认领时不重复播放的路径。

3. 将全局事件中的一次性副作用接入认领机制

  • 将音频、toast、全局自动批准等一次性副作用接入跨窗口认领。
  • 保留消息、会话状态和 pane consumer 的逐窗口更新,避免影响各窗口 UI 同步。
  • 补充全局事件测试,覆盖当前会话与后台窗口混合分类时的重复音频场景。

4. 为声音认领增加 Web Locks 串行化

  • 在原有 claim 机制上新增 claimGlobalSideEffectLocked
  • 优先通过 Web Locks 串行化同一 soundKey 的认领,避免多个窗口同时通过本地存储检查。
  • Web Locks 不可用或请求失败时,回退到带 token 确认延迟的 localStorage claim。

5. 将通知声音桥接改为“先认领,再播放”

  • 新增 claimed sound bridge 播放入口。
  • 通知声音在真正播放前先完成锁定认领。
  • 让后台通知声音和当前会话声音共用同一套 soundKey 认领路径。

6. 将当前会话提示音统一接入声音桥接

  • 将当前会话的 errorpermissionquestioncompleted 提示音交给通知声音桥接统一认领。
  • 复用后台通知的 soundKey,避免同一事件在当前窗口和后台窗口重复响铃。
  • 更新全局事件测试,断言桥接调用和共享认领 key 的行为。

验证

  • LSP diagnostics: clean(本次修改涉及文件)
  • Targeted tests passed:
    • src/hooks/useGlobalEvents.test.tsx
    • src/utils/globalEventSideEffects.test.ts
    • src/utils/notificationSoundBridge.test.ts

注意

该方案仍然是前端侧的跨窗口 best-effort 去重,不是严格分布式锁。

  • Web Locks 可用时,会提供更强的同浏览器上下文串行化能力;
  • Web Locks 不可用时,会回退到 localStorage claim;
  • 当存储不可用时,仍保留副作用执行,避免漏掉通知或声音。

MiunaQwQ added 6 commits June 2, 2026 04:54
- 新增基于 localStorage TTL 的全局副作用认领工具,避免多窗口重复执行一次性事件
- 为过期、损坏存储、不可用存储和延迟清理场景补充单元测试
- 为 notificationStore.push 增加可选 soundKey,并在通知声音桥接中复用该 key
- 补充通知声音桥接测试,确保已被其他窗口认领的声音不会重复播放
- 将音频、toast 和全局自动批准等一次性副作用接入跨窗口认领
- 保留消息、会话状态和 pane consumer 的逐窗口更新,避免影响各窗口 UI 同步
- 补充全局事件测试,覆盖当前会话与后台窗口混合分类时的重复音频场景
为全局副作用认领增加 Web Locks 串行化,避免多窗口同时通过本地存储检查。

在 Web Locks 不可用或请求失败时,通过延迟确认本地存储 token 降低竞态下重复副作用的概率。

补充锁定认领和 fallback 路径的单元测试。
将通知声音桥接改为先完成锁定认领,再播放实际提示音。

让后台通知声音和当前会话声音共用同一套 soundKey 认领路径。

更新通知声音桥接测试,覆盖认领成功、认领失败和当前会话播放入口。
将当前会话的错误、权限、问题和完成提示音交给通知声音桥接统一认领。

复用后台通知的 soundKey,避免同一事件在多个窗口重复播放声音。

更新全局事件测试,断言桥接调用和当前会话/后台通知共享认领 key。
@lehhair lehhair force-pushed the main branch 2 times, most recently from 31bb0ac to 9686ff2 Compare June 7, 2026 03:45
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