Files
openless/openless-all
TRIPandbaiqing ce21d99f05 feat(settings): hide local ASR behind new Advanced tab + confirm dialog (#400)
* feat(settings): hide local ASR behind new Advanced tab + system confirm dialog

Move local ASR options (local-qwen3 / foundry-local-whisper) out of
the main Providers → ASR dropdown into a new "Advanced" Settings tab,
so first-time users can't accidentally enable CPU inference and get
slower / less-accurate transcription than they expected. Enabling
local ASR now requires reading a strong yellow/amber warning and
confirming a system-level dialog (@tauri-apps/plugin-dialog ask()
with kind:'warning') — the in-page modal pattern wasn't loud enough.

Behavior changes:
- visibleAsrPresets now excludes local-qwen3 and foundry-local-whisper
  (the dropdown is cloud-only)
- useEffect lookup uses ASR_PRESETS (all) so committedAsrProvider can
  still resolve to a local provider when one is active
- When committedAsrProvider is local, the ASR Card replaces the
  dropdown with a plain notice ("Local ASR (X) is currently active —
  switch / disable in the Advanced tab"); existing
  LocalAsrProviderHint rendering for the Card body is preserved
- New AdvancedSection component:
  - Strong warning block (amber background + amber border + amber text,
    fontWeight 500, ⚠️ icon) — meets user's "yellow/red obvious" ask
  - Per-platform engine selector:
      macOS  : Qwen3-ASR only
      Windows: Qwen3-ASR + Foundry Local Whisper
      Linux  : "Local ASR model integration is not supported on this platform"
  - Enable buttons trigger Tauri ask() confirm dialog before switching
  - When already on local: shows a "Disable local ASR" button
    (switches to volcengine, no confirm needed) plus the existing
    LocalAsrProviderHint for model status / download navigation
- SettingsSectionId gains 'advanced'; SECTION_ORDER appends it after
  language so it sits last in the sidebar (matches macOS conventions
  for Advanced/Experimental panes)

i18n: 5 locales (zh-CN, zh-TW, en, ja, ko) gain
- settings.sections.advanced
- settings.providers.localAsrActiveNotice
- settings.advanced.{localAsrTitle, localAsrDesc, localAsrWarningStrong,
  qwen3Desc, foundryDesc, enable, alreadyActive, disableLocalLabel,
  disableLocalDesc, disable, platformNotSupported,
  confirmEnableLocalTitle, confirmEnableLocalBody}

Test plan:
- npm run build (tsc + vite) — green; the typeof zhCN constraint
  catches any locale that drifted out of shape
- Manual: switch Settings tab to "Advanced", verify warning is
  amber-on-amber and clearly visible, click "Enable" on Qwen3-ASR,
  verify a system dialog (not a React modal) appears with kind:warning
  iconography, cancel — verify nothing changed; confirm — verify the
  Providers tab now shows "Local ASR is currently active" instead of
  the dropdown
- Manual on macOS: confirm Foundry option does NOT appear
- Manual on Linux (if available): confirm "platform not supported"
  message renders

* feat(advanced): inline LocalAsr model UI + page-top confirm popup + concise warning

User feedback: the standalone "Models" page (LocalAsr.tsx as a main
nav tab) was redundant once Advanced settings exists, the inline
amber warning was a wall of text, and clicking Enable triggered an
OS-native dialog that didn't feel like part of the app. Refactor
the whole local-ASR surface around what users actually need:

- "Models" main-nav tab removed (FloatingShell + NAVIGATE_LOCAL_ASR_EVENT
  listener gone). Model management is now exclusively reachable via
  Settings → Advanced.
- LocalAsr.tsx gains an `embedded` prop. When embedded, the outer
  page padding/height, PageHeader, and standalone warning Card are
  skipped — the host (AdvancedSection) supplies the chrome.
- AdvancedSection no longer calls @tauri-apps/plugin-dialog ask().
  Enabling local ASR sets pendingTarget which renders a single
  amber-bordered Card at the very top of the section with
  Confirm / Cancel buttons. One box, in-app, dismissable. Disable
  is direct (no confirm needed — going back to cloud is safe).
- Persistent inline warning shrunk to one line. The longer wording
  (including the new "may drop words on under-spec hardware" risk
  the user asked for) lives in the popup body so it's only seen
  when actually consequential.
- ProvidersSection ASR Card body returns null when active is
  local — the dropdown row's localAsrActiveNotice already points
  to Advanced, no need to duplicate manage UI here.

i18n (5 locales): localAsrWarningStrong replaced by
localAsrWarningShort; confirmEnableLocalBody / Title shortened;
new `confirm` key for the popup CTA.

LocalAsrProviderHint and NAVIGATE_LOCAL_ASR_EVENT in Settings.tsx
are now unused but left in place to keep the diff focused; will
clean up in a follow-up commit if pr_agent flags them.

Test plan:
- npm run build (tsc + vite) — green
- Manual on macOS: Settings → Advanced shows one short amber line +
  Enable Qwen3-ASR button + LocalAsr model UI inline. Click Enable
  → page-top popup appears (no OS dialog), with Confirm / Cancel.
  Cancel → no change. Confirm → switches; Disable button appears,
  still single-click no confirm.
- Manual: Providers → ASR with active=local-qwen3 shows only the
  "Local ASR is currently active — switch in Advanced" notice,
  no manage UI.

* fix(advanced): pr_agent #400 follow-up — keep disable accessible on unsupported platform

If a user enables local-qwen3 (or foundry-local-whisper) on a machine
that supports it, then their preferences sync to a Linux/unsupported
machine, the previous Advanced UI rendered only the
"platformNotSupported" message and hid the disable button — they had
no in-app path to switch back to cloud and dictation would fail
silently on every press.

Move the disable SettingRow out of the platformSupported branch.
It's gated only on isOnAnyLocal now, so:
- Supported platform + on local → enable Qwen3/Foundry rows + disable row
- Supported platform + on cloud → enable rows only
- Unsupported platform + on local → "not supported" notice + disable row
- Unsupported platform + on cloud → "not supported" notice only

This is the pr_agent advisory from PR #400 review @ d0a425a1.

---------

Co-authored-by: baiqing <lbx12309@icloud.com>
2026-05-10 18:06:28 +08:00
..

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 (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.app
  • app/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+V is 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_CERTIFICATE
  • APPLE_CERTIFICATE_PASSWORD
  • APPLE_ID
  • APPLE_PASSWORD
  • APPLE_TEAM_ID

Optional:

  • APPLE_PROVIDER_SHORT_NAME
  • KEYCHAIN_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