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.
Immediately unsubscribe Tauri listeners if their async listen() call resolves after component unmount, preventing leaked handlers in AudioCue and Linux window chrome.
Recreate closed AudioContext instances and resume interrupted/suspended contexts before scheduling generated record-start cues. Includes state classification tests.
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.
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
- 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).
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 全绿。
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>
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.
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).
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>
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>
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>