* 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>
OpenLess All-Platform
This is the current cross-platform OpenLess workspace.
App Directory
The runnable Tauri app lives in app/. The macOS build links a vendored C ASR engine (Open-Less/qwen-asr, forked from antirez/qwen-asr) tracked as a git submodule under app/src-tauri/vendor/qwen-asr/, so initialize submodules on first clone.
# First clone only — pull in vendored submodules
git submodule update --init --recursive
cd app
npm ci
npm run tauri dev
macOS Build
Use the project build script instead of calling tauri build directly:
cd app
INSTALL=0 ./scripts/build-mac.sh
Generated macOS artifacts:
app/src-tauri/target/release/bundle/macos/OpenLess.appapp/src-tauri/target/release/bundle/dmg/OpenLess_1.1.0_aarch64.dmg
For local install during development:
cd app
./scripts/build-mac.sh
Windows Build
The runnable Tauri app is still app/. Windows contributors should run a
preflight before building so missing MSVC, Windows SDK, or MinGW tools fail
with actionable messages.
cd app
powershell -ExecutionPolicy Bypass -File .\scripts\windows-preflight.ps1
MSVC Route
Use this route when Visual Studio Build Tools and the Windows SDK are installed.
Open a Developer PowerShell, or call vcvars64.bat, then run:
cd app
npm ci
npm run tauri -- build
Required Visual Studio Installer components:
Microsoft.VisualStudio.Workload.VCTools- MSVC v143 x64/x86 build tools
- Windows 10/11 SDK that provides
kernel32.lib
If link.exe or kernel32.lib is missing, rerun:
powershell -ExecutionPolicy Bypass -File .\scripts\windows-preflight.ps1 -Toolchain msvc
GNU / MinGW Route
Use this route when MSVC/Windows SDK is unavailable. The app now lives under
the no-space openless-all directory to avoid GNU/MinGW path quoting issues
while generating import libraries. Use the helper script to keep the GNU build
environment and target setup consistent.
cd app
scoop install rustup mingw
rustup toolchain install stable-x86_64-pc-windows-gnu
rustup target add x86_64-pc-windows-gnu
powershell -ExecutionPolicy Bypass -File .\scripts\windows-preflight.ps1 -Toolchain gnu
powershell -ExecutionPolicy Bypass -File .\scripts\windows-build-gnu.ps1
Generated GNU artifacts:
%TEMP%\openless-windows-gnu\src-tauri\target\x86_64-pc-windows-gnu\release\openless.exe%TEMP%\openless-windows-gnu\src-tauri\target\x86_64-pc-windows-gnu\release\bundle\msi\OpenLess_*_x64_en-US.msi%TEMP%\openless-windows-gnu\src-tauri\target\x86_64-pc-windows-gnu\release\bundle\nsis\OpenLess_*_x64-setup.exe
Hotkey Injection Gate
Use this gate before/after Windows hotkey changes when a physical keyboard
regression is unavailable. It injects a dev/test-only hotkey click through the
coordinator handle_pressed / handle_released path, asserts the log contains
[coord] hotkey pressed, and cancels the dry-run session automatically.
cd app
npm run check:hotkey-injection
Windows Runtime Notes
- Windows does not need the macOS Accessibility permission. Use Settings -> Permissions -> Global hotkey to inspect listener status.
- Microphone permission is checked by opening a short-lived input stream, so a device-format query alone is not treated as permission granted.
- Text insertion through
Ctrl+Vis treated as copy fallback unless the app can confirm insertion.
Release Signing
Tagged releases (v*-tauri) must be Developer ID signed and notarized so users can download and open the macOS app without manually removing quarantine attributes.
Required GitHub secrets:
APPLE_CERTIFICATEAPPLE_CERTIFICATE_PASSWORDAPPLE_IDAPPLE_PASSWORDAPPLE_TEAM_ID
Optional:
APPLE_PROVIDER_SHORT_NAMEKEYCHAIN_PASSWORD
Manual workflow runs can still produce ad-hoc signed test builds, but tagged macOS releases fail if signing/notarization secrets are missing.
Ignored Local Output
The following are intentionally local-only:
app/node_modules/app/dist/app/src-tauri/target/app/src-tauri/gen/.DS_Store