Skip to content

feat(capsule): 录音胶囊样式可选(流光 Siri / Openless 默认)+ 修复 beta 构建破坏 - #887

Merged
appergb merged 4 commits into
betafrom
feat/capsule-style
Aug 3, 2026
Merged

feat(capsule): 录音胶囊样式可选(流光 Siri / Openless 默认)+ 修复 beta 构建破坏#887
appergb merged 4 commits into
betafrom
feat/capsule-style

Conversation

@appergb

@appergbappergb commented Aug 3, 2026

Copy link
Copy Markdown
Collaborator

User description

目标

设置 → 录音与输入在「录音胶囊」显示开关下新增「胶囊样式」下拉,用户可自行选择:

  • 流光 Siri 风格(默认,SiriGL 光效舞台,现状不变)
  • Openless 默认风格(恢复 1.3.14 经典毛玻璃药丸:音量条 + 取消/确认按钮 + thinking 扫光 + 翻译徽章)

兼容性

  • 新增偏好 capsuleStyle('siri' 默认 / 'classic'),旧配置缺失字段自动回落 'siri'(Rust/TS 双侧 serde default)
  • 胶囊样式随 capsule:state payload 下发(capsuleStyle 字段),设置里切换后下一次录音即生效,无新权限需求
  • 选区润色轻量提示不受样式影响

评审修复(commit 3)

  1. 经典药丸按钮可点:胶囊窗口自纯光效舞台时代起永久 set_ignore_cursor_events(true)(鼠标穿透),✕/✓ 按钮实际收不到点击。现在主线程闭包按「classic && visible && 非选区润色 && 录音/转写/润色中」关闭穿透(按钮可点;代价是窗口底部 460×180 区域在会话进行中拦截点击——与 1.3.x 经典胶囊同款取舍,终态 toast 立即恢复穿透),值不变时不重复调用系统 API。
  2. 音频线程零偏好锁:emit_capsule 在音频回调线程 ~30Hz 被调,原先直接 prefs.get()(整份克隆 + 偏好锁被 set() 跨磁盘 I/O 持有)。改为 Inner 上 AtomicU8 样式缓存,主线程闭包每帧从 prefs 同步(与 show_capsule 同源),音频线程只读原子。
  3. 恢复「录音胶囊」行 desc 文案(beta 原有)。
  4. Capsule.tsx 注释同步按样式区分的退出动画常量。

附加修复(独立 commit)

beta HEAD 存在构建破坏:SelectionPolishSection 仍传快捷键重构(e12c8dcc)已删除的 alignRecordButton / modifierPresets,tsc 必失败。本 PR 顺带适配新 API(value 可空 + onReset 恢复默认快捷键,等价旧「启用」按钮),恢复 beta 可构建状态。

测试

  • cargo test --manifest-path src-tauri/Cargo.toml:865 passed, 0 failed(注:overlay_elevenlabs_cancel_finishes_idle_without_error_capsule 为 beta 既有 flaky——macOS 非阻塞 socket WouldBlock 时序竞态,未改代码的 base 同样间歇失败,与本文无关)
  • npm run build(tsc + vite):通过
  • npm test:15 个前端契约测试全部通过
  • 手动预览:?style=classic(浏览器胶囊 dev 预览)

证据路径

  • 功能:设置页截图 / 两种胶囊形态录屏(手动 macOS 验证中)

PR Type

Enhancement, Bug fix


Description

  • Add selectable capsule style (Siri default / Classic pill)

  • Fix beta build break in SelectionPolishSection

  • Enable Classic pill Cancel/Confirm click handling

  • Cache capsule style atomically, no audio-thread lock


Diagram Walkthrough

flowchart LR
Settings["Settings UI"] -- "capsuleStyle" --> Prefs["UserPreferences"]
Prefs -- "capsule:state payload" --> Capsule["Capsule.tsx"]
Capsule -- "siri" --> Siri["SiriGL stage"]
Capsule -- "classic" --> Classic["Classic pill + buttons"]
Classic -- "interactive" --> Click["Ignore cursor events off"]
Loading

File Walkthrough

Relevant files
Enhancement
6 files
coordinator.rs
Add atomic style and passthrough state fields
+16/-3
capsule_focus.rs
Propagate capsule style and toggle cursor passthrough
+40/-1
types.rs
Add CapsuleStyle enum and payload fields
+25/-0
Capsule.tsx
Implement Classic pill and style-based rendering
+458/-13
types.ts
Add CapsuleStyle type and payload field
+10/-0
RecordingInputSection.tsx
Add capsule style dropdown to settings
+15/-0
I18n
5 files
en.ts
Add capsule style i18n strings
+3/-0
ja.ts
Add capsule style i18n strings
+3/-0
ko.ts
Add capsule style i18n strings
+3/-0
zh-CN.ts
Add capsule style i18n strings
+3/-0
zh-TW.ts
Add capsule style i18n strings
+3/-0
Miscellaneous
1 files
mock-data.ts
Add capsuleStyle to mock preferences
+1/-0
Tests
1 files
stylePrefs.test.ts
Update test fixture with capsuleStyle
+1/-0
Bug fix
1 files
SelectionPolishSection.tsx
Fix ShortcutRecorder props for new API
+18/-33

sim added 2 commits August 3, 2026 13:53
设置 → 录音与输入新增「胶囊样式」下拉(保留显示开关):
- UserPreferences.capsule_style('siri' 默认 / 'classic')随 capsule:state
payload 下发,切换后下一次录音即生效
- Capsule.tsx 双样式分支:siri 保留 SiriGL 光效舞台;classic 恢复 1.3.14
经典毛玻璃药丸(音量条 + 取消/确认按钮 + thinking 扫光 + 翻译徽章),
取消/确认改走 lib/ipc/dictation.ts,退出动画时长按样式区分
- 预览支持 ?style=classic;i18n 五语言新增胶囊样式文案
beta HEAD 在快捷键录入交互重构(e12c8dcc)合并后遗留的构建破坏:
SelectionPolishSection 仍传已删除的 alignRecordButton / modifierPresets,
tsc 直接报错。改为新 API(value 可空 + onReset 恢复默认快捷键,
等价于旧「启用」按钮),恢复 beta 可构建状态。
@github-actions

github-actionsBot commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

PR Reviewer Guide 🔍

(Review updated until commit 215eef3)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Possible Issue

The set_ignore_cursor_events(true) restore logic only runs inside the deferred (entry-frame) main-thread closure, next to the window.show handling. Mid-session state transitions (Recording → Transcribing → Polishing → Done/Cancelled/Error) go through the non-deferred immediate emit path, so the capsule window keeps ignore_cursor_events=false during the whole ~1.5s terminal toast, swallowing clicks aimed at the app below in the 460×180 area — contrary to the PR description's stated intent that the terminal toast immediately restores mouse passthrough. Passthrough is only restored on the next session's entry frame. This assumes defer_capsule_emit is only set when the window is shown from hidden, as the surrounding comments indicate; if the terminal-state emit is also deferred, this issue would not trigger.

let interactive = classic_style
&& visible
&& !selection_polish
&& matches!(
state,CapsuleState::Recording | CapsuleState::Transcribing | CapsuleState::Polishing);let want_passthrough = !interactive;if inner_for_main
.capsule_cursor_passthrough.swap(want_passthrough,Ordering::SeqCst)
!= want_passthrough
{ifletErr(e) = window.set_ignore_cursor_events(want_passthrough){
log::warn!("[capsule] set_ignore_cursor_events failed: {e}");}}

- 经典样式(Openless 默认)下胶囊窗口长期 set_ignore_cursor_events(true)
(纯光效舞台时代遗留),✕/✓ 按钮实际不可点。现在主线程闭包按
「classic && visible && 非选区润色 && 录音/转写/润色中」关闭鼠标穿透,
终态 toast / 隐藏 / Siri / 选区润色保持穿透;值不变时不重复调用
set_ignore_cursor_events
- emit_capsule 在音频回调线程 ~30Hz 被调,原先直接读 prefs(整份克隆 +
偏好锁被 set() 跨磁盘 I/O 持有)。改为 Inner 上 AtomicU8 样式缓存,
主线程闭包每帧从 prefs 同步(与 show_capsule 同源读取),音频线程零开销
- 恢复「录音胶囊」行的 desc 文案(beta 原有,重构时被误删)
- Capsule.tsx 退出动画注释同步为按样式区分的常量名
@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 1231453

@appergb
appergb merged commit 006cb78 into betaAug 3, 2026
4 of 5 checks passed
@appergb
appergb deleted the feat/capsule-style branch August 3, 2026 06:17
@github-actions

Copy link
Copy Markdown
Contributor

Persistent review updated to latest commit 215eef3

H-Chris233 added a commit that referenced this pull request Aug 3, 2026
Follow latest beta (capsule style #887, fcitx5 crash fix#883); take beta's
SelectionPolishSection rewrite which supersedes the earlier prop cleanup.
H-Chris233 added a commit that referenced this pull request Aug 3, 2026
#887 introduced desktop-only capsule cursor-passthrough logic into the
unconditionally-compiled capsule_focus module, breaking Android cargo check
(E0599: no method set_ignore_cursor_events on tauri::WebviewWindow). Gate the
block to desktop; variables it consumes (classic_style, selection_polish,
visible) are still used on mobile outside the block.
H-Chris233 added a commit that referenced this pull request Aug 3, 2026
)
* fix(less-computer): restore OpenCode model execution
* fix(capsule): gate set_ignore_cursor_events behind #[cfg(not(mobile))]
#887 introduced desktop-only capsule cursor-passthrough logic into the
unconditionally-compiled capsule_focus module, breaking Android cargo check
(E0599: no method set_ignore_cursor_events on tauri::WebviewWindow). Gate the
block to desktop; variables it consumes (classic_style, selection_polish,
visible) are still used on mobile outside the block.
---------
Co-authored-by: sim <sim@local>
Co-authored-by: Chris233 <h-chris233@outlook.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@appergb