Skip to content

merge: sync upstream cjpais/Handy v0.9.5 - #4

Open
github-actions[bot] wants to merge 50 commits into
mainfrom
sync/upstream-v0.9.5
Open

merge: sync upstream cjpais/Handy v0.9.5#4
github-actions[bot] wants to merge 50 commits into
mainfrom
sync/upstream-v0.9.5

Conversation

@github-actions

@github-actions github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

Upstream sync: v0.9.4v0.9.5

自動生成 PR (upstream-sync.yml)。

upstream リリースノート

A bug fix release!

What's Changed

New Contributors

Full Changelog: cjpais/Handy@v0.9.4...v0.9.5

upstream commits

db003f3 fix(audio): skip level meter and resampler while idle in always-on mode (#1873)
3388983 release v0.9.5
b428ae4 appimage packaging fixes (#1867)
09aaf4d fix moonshine streaming giving the wrong results
4b3a969 feat: include streaming and translation filter buttons for easy access of models (#1815)
0f32df7 fix(paste): release the modifier keys after pasting with wtype (#1487)
d961593 fix: update js-yaml to address quadratic parsing (#1865)
6d3239e fix: prevent What's New from blanking settings (#1822)
eba5d9e fix appimage check
d7fc6a0 add appimage version tag to release
12f02e2 fix: add input channel selection for multi-channel audio interfaces (#1254)
3f24f4b fix: prioritize NonPackaged key in Windows mic permission check (#1284) (#1308)
16caad7 fix(overlay): stop rendering animations while hidden (#1445)
4223e7a fix: preserve HTTP transport error causes (#1823)
b4453a2 fix(audio): move blocking cpal work off the main thread + lock-free is_recording (#1716)
7a5f397 pr template: dont submit more than one fix per pr
838f8a2 feat(nix): add Cachix binary cache to CI (#1237)
96afb0c return freed transcription buffers to the OS on Linux (#1846)
2211da6 request stream: false, for post processing
b1b2d9f fix reliable paste (#1847)
a4348be fix: recover microphone stream after the capture worker dies (#1838)
76736d5 fix: link portable update dialog to the correct installer (#1750) (#1753)
05ca5f4 docs: add missing Linux build dependencies to BUILD.md (#1561)
f602ef4 fix cargo.toml up a bit
0902937 use SMAppService so Login Items shows Handy (#1825)
2266b29 remove sigusr1 on linux (#1824)
7032758 bump handy-keys to 0.3.3
a70ac84 add more reliable paste (#1812)
347986b format
099df58 slider-reset: add reset icon following existing UI pattern (#1779)
2f7c2fc Update "Manual Model Installation" documentation with Parakeet Unified (#1668)
76b44d8 fix(audio): recalibrate mic level meter so speech moves the bars (#1813)
148e549 retry without reasoning (#1809)
cf49ab3 run overlay on main thread (#1810)
9aae694 update translations
16e5d48 dont fire bindings when recording (#1811)
d001fcd secure input warning and fallback (#1785)
ea3c20a fix(i18n): resolve zh-Hant-* system locales to Traditional Chinese (zh-TW) (#1798)
292db64  Harden Hugging Face downloads and use mirror fallback (#1773)
09a6a71 fix(i18n): complete zh-TW translations for newer UI strings (#1795)
6cad594 maximize-window: enable maximize and snap support (#1778)
390729a bump handy keys 0.3.2
8a362e9 fix mute bug (#1760)
e1152d8 fix: place Windows overlay on secondary monitors (#1733)
e8c73ba update catalog
3ed2b21 fix: restore clipboard images after paste (#1231)
f4e3587 Add Danish translations (#1747)
b462aa3 feat: windows single left click on tray icon opens handy window (#369)
cdf5028 Refactor Sidebar settings structure (#1720)

機械解決済み

  • .github/workflows/ (ours固定, GITHUB_TOKENはworkflow書換不可)

upstream workflows 差分 (未取込)

 .github/workflows/build.yml     | 190 ++++++++++++++++++++++++----------------
 .github/workflows/nix-check.yml |   9 +-
 2 files changed, 120 insertions(+), 79 deletions(-)

残存コンフリクト (手動解決必要)

  • src-tauri/src/managers/audio.rs
  • src/bindings.ts

ビルド検証 (macos-14)

  • cargo check: skipped
  • lint & format:check: failure

手動対応チェックリスト

  • src-tauri/src/managers/model.rs のセマンティックコンフリクト解決
  • src-tauri/src/managers/transcription.rs のセマンティックコンフリクト解決 (CJK token rate / MoonshineParams 維持)
  • transcribe-rs パッチに API追加が必要か確認 (~/.cargo/registry/src/index.crates-io-*/transcribe-rs-X.Y.Z/src-tauri/transcribe-rs-patch/ の diff)
  • ローカルで bun run tauri dev 起動確認
  • 日本語Moonshineモデルで長文転写確認

MikaKrul and others added 30 commits July 21, 2026 16:52
* Refactor Sidebar settings structure

* re arrange to my liking

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
…is#369)

* feat: add double-click support for tray icon

* windows left click open window

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
Paste-and-restore only ever saved plain text, so a clipboard holding a
screenshot came back as an empty string — the copied image was silently
destroyed by dictating.

Save the image too, but only probe for one when there is no text to
restore, so the common text path costs exactly what it did before and
behaves identically. When the clipboard held nothing at all, clear it
rather than leaving the transcription behind.

Deliberately scoped to text and images via the clipboard plugin already
in the tree: no new dependency, no new setting. HTML formatting and file
lists still aren't preserved — they need arboard directly, and there are
no reports of anyone hitting those.

Fixes cjpais#921

Co-authored-by: CJ Pais <cj@cjpais.com>
Co-authored-by: Egor Sokolov <236158718+egsok@users.noreply.github.com>
Co-authored-by: Nazmus Sayad <87106526+NazmusSayad@users.noreply.github.com>
* fix: place Windows overlay on secondary monitors

* fixes which work on my machine

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
* logging and retry for hf

* mirror backup for dl

* back to parallel dl but backoff

* reorg some of the changes
…h-TW) (cjpais#1798)

* fix(i18n): resolve zh-Hant-* system locales to Traditional Chinese (zh-TW)

On macOS with system language set to Traditional Chinese (Taiwan), the OS
reports the locale with a script subtag (zh-Hant-TW). Both language
resolution paths missed it and fell back to the bare "zh" prefix, i.e.
Simplified Chinese:

- frontend: getSupportedLanguage() in src/i18n/index.ts (webview UI)
- backend: get_tray_translations() in src-tauri/src/tray_i18n.rs (tray menu)

Add a script-aware fallback to both: a zh locale whose second subtag is
"hant" resolves to zh-TW before the language-only prefix match. zh-Hans-*
still resolves to zh via the existing prefix path; saved zh-TW preferences
still exact-match first; other locales are unchanged.

Fixes cjpais#1794

* fix pre-existing bug and add tests

* improve Chinese locale fallbacks

* simplify

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
* secure input warning and fallback

* translations

* change icon to be better

* better secure input dialog

* harden secure input fallback lifecycle
* dont fire bindings when recording

* regen bindings + format
…ais#1813)

The `db` value computed in AudioVisualiser::feed() is not true dBFS: it
is a per-bin average magnitude divided by the FFT window size, which for
speech-shaped input lands roughly 20 dB below the band's actual dBFS.
DB_MIN/DB_MAX were calibrated as if it were dBFS, so the window sat about
20 dB too high:

- src-tauri/src/audio_toolkit/audio/visualizer.rs (level buckets)
- src/overlay/RecordingOverlay.tsx (draws 3 + v^0.7 * 15 px bars)

Normal dictation therefore mapped to ~0.1, which the overlay draws as a
4 px bar against a 3 px floor and an 18 px maximum — roughly one pixel of
travel, which reads as a frozen waveform.

Recalibrate to -68/-30, measured against captured audio on a built-in mic
at 48 kHz (dictation ~-32 dBFS median, room tone ~-48 dBFS) and scored on
rendered pixels: speech gets ~5 px of travel while room tone stays pinned
at the floor. Not lowered to -70, where a noisy room starts making the
idle waveform twitch.

Fixes cjpais#1694

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
cjpais#1668)

* docs: replace Parakeet section with Parakeet Unified EN (huggingface-cli install)

* corrections

---------

Co-authored-by: andrzej.nescior <andrzej.nescior@nielsen.com>
Co-authored-by: CJ Pais <cj@cjpais.com>
* add more reliable paste

* translations

* minor fixes
* drop sigusr1 on linux

Co-authored-by: Murilo Vasconcelos <muriloime@gmail.com>

* consolidate signal setup into signal_handle.rs

---------

Co-authored-by: Murilo Vasconcelos <muriloime@gmail.com>
The Linux dependency lists were missing libraries that several
bundled crates require, so a clean Fedora build failed in three
separate rounds:

- evdev-sys needs libevdev (libevdev-devel / libevdev-dev / libevdev)
- whisper-rs-sys (bindgen) needs libclang (clang + *-devel)
- whisper-rs-sys (ggml-vulkan) needs the glslc shader compiler

Fedora was missing all three; Ubuntu was missing libevdev + libclang;
Arch was missing all three (shaderc provides glslc). Add them so a
fresh Linux checkout builds without hunting down each failure.

Co-authored-by: CJ Pais <cj@cjpais.com>
… (cjpais#1753)

* fix: link portable update dialog straight to the correct installer

Portable installs can't self-update in place (no installer, and Windows
won't let a running exe replace itself), so the update dialog directs
users to download the NSIS setup.exe manually. It previously opened the
generic releases page, forcing the user to hand-pick one of ~27 assets
(issue cjpais#1750: "you need to find it").

Resolve the exact installer for the running architecture from the update
version + `plugin-os` arch() and deep-link that asset directly. Falls
back to the releases page when the version can't be determined. Also
reword the dialog to note the Data/ folder is preserved on reinstall.

URL construction is a pure helper with a standalone assert check
(no unit-test runner in this repo; runnable via bun).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* add proper translations and clean up the pr

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: CJ Pais <cj@cjpais.com>
…1838)

* fix: recover microphone stream after the capture worker dies

run_consumer is driven entirely by the sample channel, so when cpal tears
the stream down mid-session (device unplugged, USB/Bluetooth dropout)
sample_rx.recv() returns Err and the worker thread exits. cmd_tx and
worker_handle stay populated, so both AudioRecorder::open() and
AudioRecordingManager::start_microphone_stream() still report the stream
as open: recording captures nothing, stop() fails on the closed channel,
and the app stays wedged until the on-demand close timeout resets it.

Detect the exited worker and rebuild the stream instead of handing back a
dead recorder.

Fixes cjpais#1743

* fix for always on as well

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
cjpais and others added 20 commits August 5, 2026 13:53
* feat(nix): add Cachix binary cache to CI

Replace magic-nix-cache (GitHub-local only) with cachix-action so build
artifacts are pushed to a public binary cache. Nix users can then pull
pre-built binaries instead of compiling from source (~25 min).

Requires repo owner to:
1. Create the cache: cachix create handy
2. Add CACHIX_AUTH_TOKEN to GitHub repo secrets

* style: fix prettier formatting in nix-check.yml

* fix(nix): use correct cache name 'handy-computer'

* chore(ci): pin Cachix action v17

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
…s_recording (cjpais#1716)

* fix(audio): move blocking cpal work off the main thread + lock-free is_recording

Synchronous #[tauri::command] handlers run inline on the webview/main run
loop, and the audio manager guards its state with a std Mutex held across
blocking CoreAudio syscalls (cpal stream start/stop, device enumeration).
A worker holding that mutex across a slow device open/close (Bluetooth/USB
mic) serializes the main thread, freezing the UI (spinning beachball).

Fix A: is_recording() reads a lock-free Arc<AtomicBool> mirror of the
"state in {Recording, Stopping}" membership, flipped at the state
transitions, instead of locking `state`. The hot-path UI poll can no longer
deadlock against a worker holding `state`.

Fix B: the four cpal-running commands (update_microphone_mode,
get_available_microphones, set_selected_microphone,
get_available_output_devices) become async and run their blocking cpal work
via tokio::task::spawn_blocking. Tauri's invoke is identical for sync/async
commands, so there is no frontend/binding change.

Live verification (Bluetooth/USB mic recording + device change mid-use) is
left to manual testing; concurrency/hardware behavior is not unit-testable.

* add helper function

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
* fix: preserve HTTP transport error causes

* fix: keep HTTP diagnostics free of sensitive data
* This fixes rendering corruption (cropping) after monitor reconfiguration

This prevents rendering corruption/cropping after monitor reconfiguration (display off/on, disconnect/reconnect, or DPI changes while hidden) by reapplying the overlay's logical size (OVERLAY_WIDTH/OVERLAY_HEIGHT).

Refactor overlay listeners and visibility handling

Move listener setup out of an inner async function and track unlisten handles so cleanup runs from the effect. Add an isVisibleRef (kept in sync via an effect) and early-return in the mic-level handler to avoid processing level updates when the overlay is hidden. Reset levels and overlay state when receiving hide-overlay. These changes prevent stale-closure issues, avoid unnecessary mic processing while hidden, and ensure listeners are properly torn down.

* fix for 0.9 version

I didn't have any problems with that. Fix now.

* fix(overlay): render nothing while hidden

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
…is#1284) (cjpais#1308)

On systems where debloaters or privacy tools (O&O ShutUp10, etc.) set
the UWP master key (HKCU\...\ConsentStore\microphone) to "deny", the
app would get stuck on the mic permission onboarding page even though
desktop app access (NonPackaged key) was correctly set to "allow".

Change the priority logic so that desktop_app_access (NonPackaged) takes
precedence over app_access (UWP master) when determining overall mic
permission status, since Handy is a desktop app and only needs the
NonPackaged scope.

Co-authored-by: CJ Pais <cj@cjpais.com>
…jpais#1254)

* fix: add input channel selection for multi-channel audio interfaces

Multi-channel audio interfaces (e.g. Focusrite Scarlett, MOTU M4)
expose loopback/output channels alongside mic inputs. Handy averaged
all channels to mono, causing music and other audio to bleed into
transcription.

Add an "Input Channel" dropdown to settings that only appears when the
selected microphone has more than one channel. Default is "Average all
channels" which preserves the original behavior. Users with
multi-channel interfaces can select their mic's specific channel.

Fixes cjpais#591

* fix: preserve recorder when changing input channel

* add translations

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
…s#1487)

* fix(paste): release the modifier keys after pasting with wtype

* format

---------

Co-authored-by: CJ Pais <cj@cjpais.com>
…s of models (cjpais#1815)

* feat: include streaming and translation filter buttons for easy access of models

* style: standardize model button sizes and add divider

* format + translations

---------

Co-authored-by: vscg <vscg@vscg.com>
Co-authored-by: CJ Pais <cj@cjpais.com>
* remove .so from appimage

* narrow exclusions
…de (cjpais#1873)

In always-on mode the capture stream stays open continuously so recording
can start with no latency. While idle (not recording) each incoming chunk
still entered the level-meter path and the resampler, but handle_frame
returns early when not recording, so the resampled output was discarded and
the level meter has no idle consumer. Skip both while idle to stop doing
unnecessary work whose output is thrown away. Cmd::Start resets the
visualizer and the resampler, so both resume cleanly when recording begins.
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.