Commit Graph
1315 Commits
Author SHA1 Message Date
sim 8d74b3e0eb chore(release): prepare 1.3.13-Beta.1 2026-06-25 14:59:31 +08:00
浩彬(^-^) ee0f746324 feat(windows): add SendInput insertion and keyboard list controls
Merge PR #740 after review and full CI. This supersedes PR #734 by including its SendInput insertion mode work plus the keyboard-list visibility preference for #738.
2026-06-25 13:51:11 +08:00
浩彬(^-^) fa09eaf605 feat(hotkey): support side-specific modifier combos
Add side-aware combo detection for dictation on macOS/Windows, shortcut recording support for side-specific modifiers, overlap validation, and tests.
2026-06-25 13:41:28 +08:00
NarwhalChen 346942e1bb style(ui): improve dark theme polish
Rework dark theme tokens, replace hardcoded dark-mode colors with theme variables, and remove the redundant overview metrics wrapper border.
2026-06-25 13:41:06 +08:00
Yu Peng Zheng c10ef381cb fix(ui): clean up late Tauri listener subscriptions
Immediately unsubscribe Tauri listeners if their async listen() call resolves after component unmount, preventing leaked handlers in AudioCue and Linux window chrome.
2026-06-25 13:39:58 +08:00
TRIP b4636f9620 fix(audio-cue): recover degraded AudioContext
Recreate closed AudioContext instances and resume interrupted/suspended contexts before scheduling generated record-start cues. Includes state classification tests.
2026-06-25 13:39:10 +08:00
TRIP 124a49ca05 fix(macos): recover stuck Accessibility onboarding
Fix macOS Accessibility onboarding getting stuck after TCC prompt/identity drift. Request permission only from onboarding, add targeted Accessibility TCC reset + restart recovery, and mirror the flow in settings.
2026-06-25 13:38:52 +08:00
sim 8563e707ba [cask] openless 1.3.12 (auto from release) [skip ci] 2026-06-24 13:56:50 +08:00
sim a4df800d66 chore(release): publish 1.3.12
- add OpenCode CLI provider support for voice agent workflows

- improve updater fallback/error visibility and compatibility

- bump app, Tauri, and Cargo versions to 1.3.12
2026-06-24 12:42:25 +08:00
e1c1be2942 feat(coding-agent): OpenCode CLI 适配器,语音 Agent 可选 OpenCode 后端 (Refs #579) (#638)
* feat(coding-agent): OpenCode CLI 适配器,语音 Agent 可选 OpenCode 后端 (issue #579)

把 OpenCode 当作与 Claude Code 同类的 coding agent CLI 接入,照既有 coding_agent
适配模式(不另造架构),复用同一套 CodingAgentRequest / CodingAgentEvent /
CodingAgentError / 审批护栏链路。

后端:
- coding_agent/opencode.rs(新):detect_opencode(opencode --version)、
  build_opencode_args(opencode run --format json --model --dir
  [--dangerously-skip-permissions],prompt 作为 argv)、parse_opencode_json_line
  (NDJSON:text/tool_use/error;text 块累计,EOF 合成 Completed)、
  run_opencode_agent(取消/超时 kill,护栏经 OPENCODE_CONFIG_CONTENT 注入)。
- coding_agent/args.rs:CodingAgentProvider 枚举(claude-code-cli/opencode-cli,
  未知回落 Claude)+ from_pref/default_exe。
- coding_agent/guard.rs:build_opencode_guard_config —— 把高风险 bash 前缀翻译成
  OpenCode permission.bash deny glob + webfetch deny,审批放行的前缀显式 allow。
- coordinator/dictation_voice_agent: run_less_computer_once 按 coding_agent_provider
  分派 Claude / OpenCode 运行器;两路都 fail-closed(护栏生成失败即中止,不裸跑)。
  审批拦截探测/重跑放行链路 provider 无关,自动复用。
- commands: coding_agent_detect_opencode 命令(已注册 lib.rs)。

前端:
- CodingAgentSection: OpenCode 选项从「即将支持」改为可用 + 选中后探测安装状态并提示。
- ipc: codingAgentDetectOpencode + OpenCodeDetection。
- i18n: opencodeReady / opencodeMissing(5 语言,替换 providerOpenCodeSoon)。

验证:cargo check + cargo test(492 通过)+ npm run build 均通过。

Refs #579
(#579 还含「语音润色模型配置」:prefs 字段已存在但全链路未实现/未接 UI,
转写直接进 agent 未经语音润色模型整理 —— 故用 Refs 不用 Closes。)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(coding-agent): OpenCode 防参数注入 + 可配置 Agent 可执行文件路径 (#638)

注入风险(@H-Chris233 评审):`opencode run` 的 prompt 作为最后位置参数,但之前缺
end-of-options 分隔。以 `-` / `--` 开头的 prompt(语音转写或被 prompt 注入诱导)会被
OpenCode 当作 flag 解析,可绕过护栏(混入 --dangerously-skip-permissions、--dir 改写
工作目录等)。修复:build_opencode_args 末尾追加 `--`,运行器把 prompt 接在其后;新增单测。

可配置路径(@PR-Agent 指出之前 hardcode "opencode"):新增 prefs.coding_agent_exe,
语音 Agent 路径据此取 exe(留空回退默认 claude / opencode),检测命令亦用配置路径;
设置「高级 → Less Computer」新增「可执行文件路径」输入;补 5 语言 i18n。

---------

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: Chris233 <h-chris233@outlook.com>
2026-06-24 12:30:12 +08:00
Haoqian 0881338e2e fix(asr): route Apple Speech dictation locally (#741) 2026-06-24 12:29:54 +08:00
jmr 95920a6b41 Merge pull request #729 from Open-Less/fix/issue-643-traditional-chinese-output
fix(ime): 繁中用户语音输入始终输出繁体 / enforce 简繁 script on output (#643)
2026-06-21 20:57:47 +08:00
Andy Jiang 48e190be20 fix(ime): always enforce 简/繁 script preference on dictation output (#643)
Traditional-Chinese users got Simplified output. finalize_polished_text only ran
the deterministic OpenCC conversion for Raw mode / polish failures, leaving
successful polish modes to the LLM — which defaults to Simplified for Chinese.
The streaming-insert path bypassed the conversion entirely.

- finalize_polished_text: for non-translation dictation, always apply
  apply_chinese_script_preference. It is a no-op for ChineseScriptPreference::Auto
  (the default), so zero impact on users who didn't pick a script; for Simplified/
  Traditional it now guarantees the output script instead of trusting the LLM.
- streaming_insert_eligible: gains the script preference and disables streaming
  insert when it is non-Auto, so the one-shot path runs (streaming types live and
  has no finished text to post-process).

Tests: polish_output_honors_chinese_script_preference (S2t actually converts;
Auto is a no-op) + streaming_disabled_for_non_auto_script_so_opencc_runs. 470 lib
tests pass.

Closes #643
2026-06-21 19:22:46 +08:00
github-actions[bot] e55ac03fa2 [cask] openless 1.3.11 (auto from release) [skip ci] 2026-06-21 06:49:44 +00:00
Andy Jiang 950ad58006 chore(release): 1.3.11 2026-06-21 13:55:15 +08:00
Andy Jiang 65361606f7 feat(dictation): failure-resilience, record-next queue, manual re-transcribe
- preserve audio on ASR failure + auto silent retry: always-archive recordings
  (delete on success unless debug), route all engine failure arms through a single
  fail_dictation -> recoverable transcribeFailed history; auto-retry re-feeds the
  archived WAV via retranscribe_pcm; fix empty-transcript id mismatch (#613)
- hotkey: queue-chain -- a press buffered during processing auto-starts the next
  recording (grace window distinguishes it from the #545 post-session cooldown)
- history: wire the manual re-transcribe button for transcribeFailed/emptyTranscript
  entries with audio

Rebased onto beta 1.3.10; my capsule multi-monitor fix dropped (superseded by #714).
2026-06-21 13:53:56 +08:00
Chris233 b07f78bc1d Merge pull request #723 from H-Chris233/fix/whisper-dynamic-timeout-721
fix(asr): Whisper/OpenRouter 动态超时 + 全局兜底 15→30s
2026-06-21 13:26:07 +08:00
Chris233 e1f24b61a4 test: 修复 local_qwen_timeout 测试 + 新增 whisper_transcribe_timeout 测试
- local_qwen_timeout_ceils_partial_seconds: 10.1s 音频原期望 17s,全局常量
  提升到 30s 后改为期望 COORDINATOR_GLOBAL_TIMEOUT_SECS
- 更新相关注释中的 15→30
- 新增 3 个 whisper_transcribe_timeout 测试:短音频兜底、长音频缩放、ceil
2026-06-21 12:50:41 +08:00
Chris233 3ec8c5ef0c fix(asr): Whisper/OpenRouter 动态超时 + 全局兜底 15→30s
- COORDINATOR_GLOBAL_TIMEOUT_SECS 从 15 改为 30,为云端 batch ASR 留网络预算
- 新增 whisper_transcribe_timeout(audio_secs):max(30, ceil(audio×0.5)+20)
- WhisperBatchASR 新增 buffer_duration_ms() 供 coordinator 计算动态超时
- dictation.rs Whisper 路径从固定 15s 切到动态超时,超时日志包含音频时长

Closes #721
2026-06-21 20:48:38 +08:00
TRIPandsim 323f44d450 feat(less-computer): 边缘发光改用 EdgeGlow 式四层模糊堆叠 + iridescent 配色 (#720)
把 Less Computer 全屏彩虹边缘发光从原来「两条都带模糊的软光带」改成
EdgeGlow(github.com/vector4wang/EdgeGlow,MIT)的实现方式,让彩虹「实线」
更清晰、发光更有层次。

- 4 层模糊堆叠:最内一条 0.5px 锐利彩虹实线(对应 EdgeGlow blur=0 那层,
  定义边缘),外面叠 3 层逐渐变宽、变虚的光晕(blur 3/8/15px),得到
  霓虹灯管式发光。原生用 CAShapeLayer + 高斯模糊,这里用 CSS「边框遮罩环
  + filter:blur」等价复刻。
- 配色移植 EdgeGlow 默认的 iridescent(Apple Intelligence 高饱和霓虹:
  紫→蓝→青→绿→金→橙→红→粉),按 12 段均匀铺满 360°。
- 流光整圈 8s/圈通过 --lcg-angle 旋转(只动渐变角度不动元素形状,GPU 友好),
  光晕层各带不同周期呼吸;实线用 normal 保色准,光晕用 screen 叠加增亮。

保留 issue #470 的隐藏即卸载发光层(零 GPU)逻辑、pointer-events:none、
prefers-reduced-motion 降级与 --lcg-radius 圆角变量。纯视觉、仅 macOS、单文件。

Co-authored-by: sim <sim@local>
2026-06-21 10:04:35 +08:00
GanAO da9bf15795 fix(asr): add MiMo provider to credential gate validation (#713)
ensure_asr_credentials() 的 if-else 链未处理 MiMo provider,fall through 到末尾被火山引擎凭证检查误拦。本 PR 把 is_mimo_provider(&active_asr) 加入 API Key 验证分支(+4 行),与 build_qa_asr_start / active_asr_provider_kind 的处理保持一致。

Claude 审核:修复正确且最小化,无副作用,可合并。四平台 CI 全绿。
2026-06-21 00:27:47 +08:00
TRIP 50274d1acd fix(insertion): macOS 让「恢复剪贴板」开关真正生效,修复被回退的 #525 (#683)
#525 的 macOS 剪贴板恢复被 Android 移植 commit 1ea467a 用 cfg(not(any(macos,android,ios))) 误伤排除。本 PR 把 40+ 处 cfg 放宽为 not(any(android,ios)),macOS 重新纳入;insert() 改为「保存原剪贴板 → 写转写 → Cmd+V → 按开关决定是否恢复」。

已解决与 beta(#712 安卓集成)在 insert() 签名上的冲突,cargo check 通过,四平台 CI 全绿。
Claude 审核:cfg 边界清晰、三态逻辑正确,无阻塞性问题。Closes #525
2026-06-21 00:27:39 +08:00
TRIP cfb09b14f8 fix(capsule): 胶囊跟随鼠标光标所在屏,修复多屏/多 Space 只在第一块屏显示 (#714)
新增 CGEventGetLocation 取鼠标光标位置(零权限),focused_input_target_monitor → capsule_target_monitor,定位与去重快照统一走光标优先选屏,消除「定位用 AX caret、去重用 current_monitor」两套选屏不一致导致的锁屏。

Claude 审核:5 个核心确认点(坐标系一致/选屏逻辑/快照统一/零权限/平台隔离)全部通过,可合并。
2026-06-21 00:05:45 +08:00
TRIP 7a33db0605 fix(less-computer): 护栏高危系统命令设为不可批准,修批准注入畸形规则 (#688)
deny_rule_for_pattern 只对可安全前缀化的命令(rm -rf / git push --force 等)返回精确 deny 规则;sudo/dd/mkfs/chmod/shutdown 等返回 None,即使被点批准也保持拦截、不注入 allow。修复旧代码 format!("Bash({p}:*)") 对 "sudo " 生成 Bash(sudo :*) 与 deny 规则 Bash(sudo:*) 不匹配导致批准静默失效的问题。

Closes #679

Claude 审核:方向正确,核心修复逻辑无误,无阻塞性问题。
2026-06-21 00:03:56 +08:00
TRIP fbe40ab583 feat(android): 集成 #704 安卓自动更新 + 同步 PC updater 修复(#705/#708)到安卓 (#712)
合并 #704(安卓应用内自动更新 + JNI 修复)并把 PC updater 修复同步到安卓:①安卓公钥回退 6F4B5994→1DEAA803(同步#705)②installError 安装失败兜底+去 throw(同步#708)③还原被自动合并误删的桌面 logClientError。桌面机制零变更。CI 全绿 + @claude 审核通过。取代 #704 及 #694 安卓部分。
2026-06-19 13:55:53 +08:00
github-actions[bot] 6c34e0e579 [cask] openless 1.3.10 (auto from release) [skip ci] 2026-06-18 03:50:17 +00:00
github-actions[bot] a5d1b0b579 [cask] openless 1.3.10 (auto from release) [skip ci] 2026-06-17 16:59:48 +00:00
sim dbdc73f278 chore(release): 1.3.10 (stable / 正式版) 2026-06-18 00:33:00 +08:00
sim 412dc9968a chore(release): 1.3.10-4 (beta) 2026-06-17 23:30:58 +08:00
TRIPandsim 6c99ddf1f7 fix(updater): revert signing pubkey to 1DEAA803 to repair auto-update (#705)
Auto-update was broken on every platform: builds since aaf4ccc embed pubkey
6F4B5994, but shipped 1.3.8 stable users trust 1DEAA803 and CI now signs with
1DEAA803 again. A key the installed app doesn't trust => download succeeds,
install() signature verification fails => "downloads but never updates".

Revert the desktop updater pubkey to 1DEAA803 so it matches both the CI
signing key and android/updater.rs (which already hardcodes 1DEAA803). This
also repairs Android auto-update, which was signing-vs-verifying mismatched.
One line, no logic change.

Co-authored-by: sim <sim@local>
2026-06-17 23:30:01 +08:00
sim f94f9be07a chore(release): 1.3.10-3 (beta)
Re-cut of the 1.3.10-2 beta from the synced cloud beta branch (supersedes the
-2 pre-release, which was deleted). Identical code to 1.3.10-2 — version-number
bump only. Bundles #701 persistence split, #702 top-bar unification, #703
onboarding accessibility gate, on top of 1.3.10-1 audit fixes.
2026-06-17 18:57:05 +08:00
sim aa643b972d chore(release): 1.3.10-2 (beta) — macOS top-bar unification + onboarding accessibility gate
Bundles the two macOS UX fixes already merged into beta:
- #702 unify macOS shell top inset with sidebar/background surface
- #703 require macOS Accessibility grant before first-run onboarding completes

Version synced across package.json, package-lock.json, tauri.conf.json,
Cargo.toml, Cargo.lock. Local release build verified (1.3.10-2 installs and
runs; top bar seamless; first-run requires Accessibility).
2026-06-17 17:54:09 +08:00
TRIPandsim f3467ae5f9 fix(onboarding): require macOS Accessibility grant before first-run completes (#703)
On macOS the hotkey needs Accessibility, but first-run onboarding could finish
after Microphone only and drop users into the main UI with a dead hotkey
("nothing happens when I press the key").

Cause: desktop onboarding gated completion on the hotkey *capability* flag
(requiresAccessibilityPermission). That flag is null while the capability IPC
loads, so requiresAccessibility was briefly false — if Mic got granted in that
window, refresh() called onComplete() before Accessibility was ever requested.
App.tsx's startup gate, by contrast, always requires Accessibility, so the two
disagreed.

Fix: gate completion on the real permission status, mirroring App.tsx — macOS
returns granted/denied, every other platform returns notApplicable, so this is
timing-independent and cross-platform safe. Also surface the Accessibility step
whenever it is denied (macOS-only state) and drop the capability dependency from
its grant button, so the step always appears and is actionable even before the
capability finishes loading.

No change on Windows/Linux/Android (Accessibility = notApplicable there).

Co-authored-by: sim <sim@local>
2026-06-17 17:39:16 +08:00
TRIPandsim 4903f4442e fix(ui): unify macOS shell top inset with sidebar/background surface (#702)
The 28px top inset that clears the macOS overlay traffic lights sat on the
content wrapper with no background, so it exposed the lighter WindowChrome
glass (--ol-window-bg) as a full-width band above the sidebar and panel —
reading as an extra top row that the Windows build (no inset) doesn't have.

Paint that wrapper with the same --ol-app-shell-bg the sidebar/background
already use, so the inset blends into one continuous surface with the panel
card floating on top. One property; token carries its own light + dark
values; no layout, token, or other UI changes.

Co-authored-by: sim <sim@local>
2026-06-17 17:27:15 +08:00
TRIPandsim a94ea3d05a refactor(persistence): split persistence.rs into domain modules behind a barrel (#701)
Behavior-unchanged decomposition of the 2757-line `persistence.rs` god-file
into a `persistence/` module, one file per concern. Everything is re-exported
via glob (`pub use <submodule>::*`) so the `crate::persistence::*` public
surface is byte-for-byte identical and no call site changes.

Layout:
- mod.rs         shared fs/io helpers (data_dir, ensure_dir, atomic_write,
                 read_or_default) + the two cross-cutting consts + re-exports
- paths.rs       models / recordings / Foundry roots + migration helpers
- credentials.rs OS credential vault (CredsRoot model, keyring/android/legacy,
                 CredentialAccount, CredentialsSnapshot, CredentialsVault)
- history.rs     HistoryStore
- preferences.rs read_preferences + PreferencesStore
- style_pack.rs  StylePackStore + ZIP import/export + prefs reconciliation
- dictionary.rs  DictionaryStore + vocab presets
- correction.rs  CorrectionRuleStore

Pure move + re-export: no logic, signatures, public API, or UI changed. Unit
tests moved next to the code they now cover. Shared helpers stay private in
`mod.rs` (parent items are visible to child modules), and glob re-exports keep
cfg-gated items (Android/Windows) resolution-safe across every target —
avoiding the explicit-`pub use` breakage seen in the earlier types.rs split.

Verified on macOS: cargo fmt/check/clippy clean (no new persistence warnings),
446 lib tests green. Android/Windows cfg paths verified by CI.

Part of #697.

Co-authored-by: sim <sim@local>
2026-06-17 16:08:26 +08:00
TRIP b98e353a2b refactor(ipc): split lib/ipc.ts into domain modules behind a barrel (#700)
Behavior-preserving: 1765-line ipc.ts → 22 domain modules + barrel index.ts; all ~118 exports preserved, 0 consumer changes, tsc/build/all-platform CI green. Part of #697.
2026-06-17 13:38:34 +08:00
appergb 6aad6e814f chore(release): 1.3.10-1 (beta) — audit fixes batch 1+2 (critical Android updater, security hardening, correctness bugs) 2026-06-17 11:45:38 +08:00
TRIP 5aed1e46ed fix: audit batch 2 — correctness bugs + Android robustness (#696)
7 medium findings: corrupt-timestamp context truncation, voice_agent flag timing, Volcengine/Bailian ASR cancel-on-error, graceful store-init fallback (no startup panic), Android OVERLAY_VISIBLE desync (Rust+Kotlin onDestroy), JNI null-check, accessibility clipboard restore. All-platform CI green; 446 tests pass.
2026-06-17 11:39:55 +08:00
TRIP 121bb11447 fix: audit batch 1 — critical Android updater + security hardening + bug fixes (#695)
14 confirmed audit findings: critical Android auto-update fix (SUPPORTED_ABIS), security hardening (exe allowlist, window-scoped approval, update-URL validation, remote PIN rate-limit/entropy, mirror order, prompt sanitization), correctness bugs (prefs race, hotkey spawn race, voice-agent focus clear), build-hygiene, and Android robustness. All-platform CI green; 446 tests pass.
2026-06-17 11:13:27 +08:00
TRIP 0eb69fc0f4 chore: codebase cleanup + behavior-preserving refactor (#693)
Audit-driven cleanup: 6 issue fixes (#689/#686/#680/#691/#678/#612), Aura skin removal (visually-neutral), dead-code cleanup (98→87 warnings), behavior-preserving modularization (coordinator.rs 6961→3083 + LocalAsr/ + polish/ submodules), and RELEASING.md (admin-only release policy). Gates: cargo test --lib 446 passed, tsc, all-platform build + contract checks green. Supersedes #685/#687/#690/#692/#682/#681.
2026-06-16 23:22:21 +08:00
appergb 4f73dbd5e4 fix(cask): revert openless to 1.3.8 — v1.3.9 unpublished (unauthorized buggy release) [skip ci] 2026-06-16 21:08:08 +08:00
TRIPand吕柏青 ee42d1a2e7 perf(onboarding,settings): 权限/热键状态纯事件驱动,去掉高频轮询 (#673)
* perf(onboarding,settings): 权限/热键状态纯事件驱动,去掉所有高频轮询

issue #470:引导页桌面(1s)/Android(3s)、设置页热键(1s) 的 setInterval 高频权限/热键轮询
全部改为 window focus / visibilitychange 事件驱动,连低频兜底也去掉(纯事件驱动)。
覆盖论证:麦克风前台原生弹窗授予由申请结果回调 + 800ms 兜底覆盖;辅助功能授予必经系统
设置 App、切回 OpenLess 必触发 focus/visibilitychange。并给 onGrantAccessibility 补对称的
void refresh() + 800ms 兜底(与 onRequestMicrophone 对齐)。PermissionsSection 的
refreshPermissions(10s)/refreshNetwork(30s) 保留不动。

* fix(onboarding): DesktopOnboarding effect 内 refresh() 统一加 void

@claude 审查 #673 指出:DesktopOnboarding 的 useEffect 里 refresh()/onFocus/onVisibility
三处 refresh() 是 floating promise(与上方 Android 段的 void refresh() 不一致,IPC 失败会
静默)。统一加 void 明确 fire-and-forget。issue #470。

---------

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
2026-06-16 11:10:53 +08:00
TRIPand吕柏青 001615ebf4 perf(local-asr): 引擎状态改后端事件驱动,前端零轮询 (#672)
* perf(local-asr): 引擎状态改后端事件驱动,前端零轮询

issue #470:LocalAsr 前端原本 setInterval 每 5s 轮询 refreshEngineStatus。改为后端在每个
状态转换点主动 emit `local-asr:engine-changed`(load: build_local_qwen3 / preload;idle
释放: schedule_local_asr_release 的 release_if_idle==true;手动释放: release_local_asr_engine
汇聚点;keepLoadedSecs 变更),前端 listen 该事件增量更新、删掉 5s 轮询与 engineStatusTimer。
挂载时仍拉一次初值,listener 在 cleanup unlisten。LocalAsrEngineStatus 加 Clone 供 emit 复用。
helper 只用跨平台符号,不碰 Foundry/Sherpa。

* fix(local-asr): emit_local_asr_engine_status 加 Android no-op stub

CI Android cargo check 失败:LocalAsrEngineStatus 不在 android target 编译。给 helper 加
#[cfg(not(target_os="android"))] 真实现 + #[cfg(target_os="android")] no-op stub,
各调用点在所有平台统一编译。issue #470 / #6。

---------

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
2026-06-16 11:10:29 +08:00
TRIPand吕柏青 49a6dc800f perf(tray): 托盘麦克风设备监听改 OS 原生通知,空闲零唤醒 + 60s 兜底 (#670)
* perf(tray): 托盘麦克风设备监听改 OS 原生通知,空闲零唤醒 + 60s 兜底

issue #470:原 watcher 每 10s 轮询 list_input_devices()(CoreAudio/WASAPI 全枚举)永不
停歇。新增 device_watch 模块用 OS 原生设备变更通知替代:macOS CoreAudio
AudioObjectAddPropertyListener(kAudioHardwarePropertyDevices) 专用 CFRunLoop 线程常驻;
Windows IMMNotificationClient 经 IMMDeviceEnumerator 注册端点通知。回调复用现有去抖
(microphone_device_signature) + refresh_tray_microphone_menu + emit 收尾。

works 保证:保留一条 60s 全平台慢速兜底轮询无条件运行——原生注册失败/Linux 无原生路径
时退化到它,三平台永远能检测到设备。coreaudio-sys 提升为 macOS 直接依赖(本就在依赖树)。

注:Windows IMMNotificationClient 分支开发机(macOS)无法本地编译,靠 CI 三平台 cargo check
+ 真机验证;60s 兜底保证即使该分支失效也不会漏检设备。Cargo.lock 未提交(macOS check 会
引入大量与本改动无关的环境性条目),cargo 构建时自愈。

* fix(tray): 砍掉无法本机验证的 Windows IMMNotificationClient 原生路径

CI Windows checks 失败:windows-rs 的 IMMNotificationClient_Impl / Win32_UI_Shell_PropertiesSystem
feature 与 implement 宏的 windows_core 路径在开发机(macOS)无法编译验证,靠 CI 反复试代价大。

简化为:macOS 走 CoreAudio 原生通知(已验证),Windows / Linux 统一返回 false → 走 lib.rs
的 60s 慢速兜底轮询(仍比原 10s 少 6 倍唤醒、保证三平台编译通过)。Windows 原生设备通知
留作后续单独项(需 Windows 开发机验证)。issue #470。

---------

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
2026-06-16 11:10:22 +08:00
TRIPand吕柏青 2d783ce337 perf(coordinator): 可选热键 supervisor 注册成功即退出,彻底消除稳态轮询 (#671)
issue #470:combo/translation/action 三类可选热键 supervisor 原本注册成功后不退出,稳态
每 5s 醒来读 prefs,多线程常驻空转。改为对齐主 hotkey_supervisor_loop 的 exit-on-success
模式——到达「已安装」或「已主动停用」稳态即 return 退出,零轮询。

安全前提(已逐函数确认):用户启用/改/停这些热键时,set_*_hotkey 命令与 persist_settings
diff 都会调 update_*_hotkey_binding,其覆盖「monitor 为 None → 从零 start+spawn」安装路径,
故退出后启停改键无需重启即时生效;ComboHotkeyMonitor 注册后驻留、无运行中自注销,monitor
不会自己死,无需 supervisor 守护。失败重试 sleep(3s)/recv_timeout(5s)/app未就绪 sleep(1s)
等有界路径全部保留。

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
2026-06-16 10:56:37 +08:00
TRIPand吕柏青 16e0f27685 perf(marketplace,localasr): 清理冗余定时器 (#674)
issue #470:
- Marketplace 上传后双重 setTimeout(1.5s+5s) 去重为单次 5s——乐观更新已即时反映「我的
  发布」,延时刷新仅做服务端状态校准,1.5s 那次纯冗余。
- LocalAsr scheduleScrollGuardRestore 三连 setTimeout(0/80/200ms) 仅删等价的 0ms 那枪
  (已被紧随的 rAF 覆盖),保留 80/200ms 兜住 rAF 之后的异步重排,避免滚动跳变回归。

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
2026-06-16 10:56:32 +08:00
TRIPand吕柏青 9f3eebcb88 perf(less-computer-glow): 隐藏时卸载全屏发光层,消除空闲 GPU 占用 (#675)
issue #470:彩虹描边 glow 是全屏 transparent 浮层 + 4 条无限动画(lcg-spin/breathe/
spin-reverse/flow)。原组件无状态无监听,窗口 .hide() 后 webview 仍持续合成发光层、
跑满 4 条动画,GPU 永不释放(Windows 尤其不释放)。

改为后端 show/hide 主动 emit `less-computer-glow:active` 驱动可见状态(不依赖在隐藏
窗口上失灵的 WebView2 visibilitychange):可见时渲染与原来完全一致的 DOM(视觉零变化),
不可见时返回 null 卸载发光层 → 零 GPU。另加 document.hidden 二级兜底(只停不启)。

注:glow 当前为 macOS-only(Windows show/hide 是 no-op),本修复消除 macOS 隐藏态泄漏,
并让组件具备跨平台「隐藏即零 GPU」安全性,为后续 Windows 重启用铺路。

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
2026-06-16 10:56:27 +08:00
TRIPand吕柏青 28ea5123b4 perf(capsule): 删除无效的 translation 徽章 backdrop-filter (#676)
issue #470:该 backdrop-filter:blur(20px) 作用在浮于透明窗口之上的 translation 徽章
pill 上,背后只有透明窗口=桌面,而 webview 模糊不了窗口背后的桌面(Tauri 上游限制,
本文件上方 pill 已有同款注释)。故它不产生任何模糊效果、纯空耗一次合成。删除零视觉变化。

Co-authored-by: 吕柏青 <lubaiqing9@gmail.com>
2026-06-16 10:56:22 +08:00
github-actions[bot] ec6a03d016 [cask] openless 1.3.9 (auto from release) [skip ci] 2026-06-15 14:09:40 +00:00
Andy Jiang e05025a7e7 chore(release): 1.3.9 (stable / 正式版)
内存优化:webview 代码分割 + i18n 按需加载(index 440→285KB) + 胶囊录音帧节流 + qa/less-computer/glow 窗口懒创建(idle WebKit 进程 5→2)。含 #661 暗色模式。
2026-06-15 21:39:49 +08:00