Skip to content

feat(settings): hide local ASR behind new Advanced tab + confirm dialog#400

Merged
appergb merged 3 commits intobetafrom
feat/advanced-settings-local-asr
May 10, 2026
Merged

feat(settings): hide local ASR behind new Advanced tab + confirm dialog#400
appergb merged 3 commits intobetafrom
feat/advanced-settings-local-asr

Conversation

@appergb
Copy link
Copy Markdown
Collaborator

@appergb appergb commented May 10, 2026

User description

Summary

  • New Advanced Settings tab containing local ASR (local-qwen3 + foundry-local-whisper). They are removed from the main Providers → ASR dropdown so a fresh user can't accidentally enable CPU inference and get slower / less accurate transcription than expected. Tab sits last in the sidebar (matches macOS Advanced/Experimental conventions).
  • System-level confirm dialog before enabling local ASR. Uses @tauri-apps/plugin-dialog ask({ kind: 'warning' }) — the OS draws the warning iconography. An in-page React modal wasn't loud enough for the user's "obvious popup" requirement.
  • Strong amber warning block in the Advanced tab (amber background + amber border + amber text + ⚠️ + fontWeight: 500). Meets the "yellow / red, clearly visible" ask.
  • Per-platform visibility preserved. macOS: Qwen3-ASR only. Windows: Qwen3-ASR + Foundry Local Whisper. Other platforms (Linux): "Local ASR model integration is not supported on this platform."
  • Existing behavior when already on local preserved: Providers Card replaces the cloud dropdown with a notice ("Local ASR (X) is active — switch in Advanced") and keeps the existing LocalAsrProviderHint (model status, navigate to Models page). Advanced tab adds a Disable local ASR button to switch back to cloud (no confirm needed).

Code shape

  • Settings.tsx:

    • SettingsSectionId adds 'advanced'; SECTION_ORDER appends it
    • visibleAsrPresets excludes both local options (dropdown is cloud-only)
    • useEffect ASR lookup switches from visibleAsrPresetsASR_PRESETS so committedAsrProvider still resolves a local provider when active
    • ASR Card dropdown is replaced with a plain notice when committedAsrProvider is local
    • New AdvancedSection component with the warning, per-platform enable buttons, and confirm dialog
  • 5 i18n locales (zh-CN as source-of-truth, zh-TW + en + ja + ko mirrored): settings.sections.advanced, settings.providers.localAsrActiveNotice, full settings.advanced.* group. The typeof zhCN constraint catches any locale that drifts.

Test plan

  • npm run build (tsc + vite) — green
  • Manual on macOS: open Settings → Advanced; confirm only Qwen3-ASR option visible (no Foundry); click Enable on Qwen3, system dialog appears with warning iconography, cancel → no change, confirm → Providers tab now shows Local ASR is currently active instead of the dropdown
  • Manual on macOS: while on local ASR, click Disable local ASR in Advanced — switches to volcengine, no confirm dialog (only enabling needs confirm)
  • Manual on Windows (cross-check only): both Qwen3 + Foundry options visible; same confirm flow for each
  • Manual on Linux (if available): Local ASR model integration is not supported on this platform renders, no enable buttons

PR Type

Enhancement


Description

  • Introduce new Advanced settings tab for local ASR

    • Remove local ASR from main Providers dropdown
    • Show notice when local ASR is active
  • Add confirmation popup before enabling local ASR

  • Embed LocalAsr model management into Advanced tab

  • Add i18n for all locales (en, ja, ko, zh-CN, zh-TW)


Diagram Walkthrough

flowchart LR
  A["User opens Settings"] --> B["Advanced tab (new)"]
  B --> C["Local ASR cards: Qwen3-ASR, Foundry Whisper"]
  C -- "Enable" --> D["Confirmation popup (amber warning)"]
  D -- "Confirm" --> E["Switch active ASR to local"]
  B --> F["Embedded LocalAsr model management"]
  G["Providers ASR dropdown"] --> H["Cloud-only options"]
Loading

File Walkthrough

Relevant files
Enhancement
8 files
FloatingShell.tsx
Remove LocalAsr navigation tab and event listener               
+6/-12   
en.ts
Add English i18n for Advanced settings and local ASR notices
+18/-0   
ja.ts
Add Japanese i18n for Advanced settings                                   
+18/-0   
ko.ts
Add Korean i18n for Advanced settings                                       
+18/-0   
zh-CN.ts
Add Simplified Chinese i18n for Advanced settings               
+18/-0   
zh-TW.ts
Add Traditional Chinese i18n for Advanced settings             
+18/-0   
LocalAsr.tsx
Support embedded mode and remove standalone page layout   
+39/-15 
Settings.tsx
Add Advanced section, filter local ASR from dropdown, and add
confirmation popup
+213/-14

…rm 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
@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 10, 2026

PR Reviewer Guide 🔍

(Review updated until commit 64353a7)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 2 🔵🔵⚪⚪⚪
🧪 No relevant tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Unused import

SettingsSectionId is imported here but no longer referenced after the local-ASR navigation handler was removed. If the project runs TypeScript or ESLint with unused-local checks enabled, this will fail the build.

import { type SettingsSectionId } from '../pages/Settings';

…oncise 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.
@github-actions
Copy link
Copy Markdown

Persistent review updated to latest commit d0a425a

…nsupported 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 @ d0a425a.
@github-actions
Copy link
Copy Markdown

Persistent review updated to latest commit 64353a7

@appergb appergb merged commit ce21d99 into beta May 10, 2026
4 checks passed
@appergb appergb deleted the feat/advanced-settings-local-asr branch May 10, 2026 10:14
appergb added a commit that referenced this pull request May 10, 2026
* feat(settings): cross-platform parity for local ASR

- AdvancedSection: warning collapses to inline 11px amber badge in
  the title row's top-right; the enable-confirm popup is now a
  centered fixed modal with backdrop blur(8px) and click-outside-
  to-cancel (busy-guarded).
- Symmetric rows by platform — fixes the #400 bug where the Qwen3
  row was rendered on Windows even though all qwen_engine /
  local_provider / cache modules are #[cfg(target_os = "macos")],
  so Enable on Windows would always error:
    macOS:   Qwen3 row enabled / Foundry row hidden
    Windows: Foundry row enabled / Qwen3 row disabled with
             notSupportedHere desc
- Providers ASR Card: replaces the plain-text localAsrActiveNotice
  branch with an always-rendered dropdown that includes the
  platform-native local engine (macOS=Qwen3, Windows=Foundry) as a
  disabled option, plus a takeover hint underneath. Entire
  dropdown locks when a local engine is active, so it can only be
  released via Advanced (matches "启动之后供应商将被接管" UX).
- onLlmProviderChange / onAsrProviderChange now emit saving →
  saved through emitSaved. Data was already being persisted; the
  saved-toast was missing.
- LocalAsr embedded: hide Qwen3 model management (mirror /
  engine-status / model list) on Windows — dead UI without the
  Qwen3 backend. The shared error Card is kept unconditional
  since Foundry handlers also call setError.
- i18n × 5 (zh-CN/zh-TW/en/ja/ko): shorten localAsrWarningShort;
  rewrite qwen3Desc and foundryDesc to '启动之后,ASR 提供商将被接管';
  add notSupportedHere and localAsrTakeoverHint.

* fix(settings): clear saving toast on provider-switch failure

pr_agent #403 caught: emitSaved('saving') with no try/catch — if
setActiveLlmProvider / setActiveAsrProvider / any later credential
write throws, the right-corner toast stays stuck on saving forever.

Wrap both onLlmProviderChange and onAsrProviderChange bodies in
try/catch. On error, emit 'failed' (and re-throw) only if seq still
matches — stale calls superseded by a newer switch shouldn't
overwrite the newer call's own saving state.

* fix(settings): provider-card visual cleanup + log-export permission + pr_agent #403

Fixes piled up in user feedback during local verify of the previous
commit; bundled into one commit to keep #403 small.

- capabilities/default.json: add `dialog:default` permission. The
  About → Export error log button always failed because the Tauri 2
  capabilities did not allow `tauri-plugin-dialog`'s `save()` command;
  the JS rejected before export_error_log was ever invoked.

- ProvidersSection ASR Card (pr_agent #403 'Wrong active label'):
  when committedAsrProvider is a local engine, selectedValue now
  reflects the actually-active engine instead of being forced to
  platformLocalAsr. Cross-machine config sync (macOS profile with
  foundry-local-whisper / Windows profile with local-qwen3) used to
  make the dropdown lie about which backend is running. Anomalous
  local engines are added as disabled <option>s so the controlled
  <select> still finds its value and doesn't fall back to the first
  option.

- ProvidersSection: drop verbose desc on LLM and ASR provider rows.
  '选择后将自动填入 Base URL 默认值。' is ~16 Chinese chars and
  always wraps inside the 180px label column, leaving a stranded
  second line on the left — the dropdown itself already conveys the
  semantic, the desc was redundant.

- AdvancedSection: replace the [启用] / [已启用] Btn with the
  shared Toggle component for Qwen3 and Foundry rows. Toggle off
  switches back to volcengine. The Qwen3 row's Toggle truthfully
  reflects committed state on Windows (so a cross-platform anomaly
  shows ON even though it is non-interactive there). The standalone
  '禁用本地 ASR' escape row is now only rendered when no inline
  Toggle can disable the active engine — i.e., Linux / unsupported
  platform, or anomaly where the row for the foreign engine is
  hidden / non-interactive.

- PermissionsSection: every status pill (microphone, accessibility,
  hotkey, Windows IME, network) now right-aligns inside its row via
  `justifyContent: flex-end` + `width: 100%`. Pill text moved to the
  right of inline messages so the green '已授权' / 'Authorized'
  reads as a right-edge badge — closer to macOS System Settings
  convention.

* fix(settings): keep Windows Qwen3 toggle visually OFF (pr_agent #403)

pr_agent 'Stale Windows state' caught: previous commit had `on=
{isOnLocalQwen3}` which truthfully reflected committed state, so a
profile synced from macOS with activeAsrProvider=local-qwen3 would
render Toggle ON next to a desc that says '本平台暂不支持'. The
visual contradiction was the concern.

Switch to `on={isMac && isOnLocalQwen3}` — Windows always renders
the row OFF + non-interactive, matching the unsupported desc. The
cross-platform anomaly state surfaces via the standalone '禁用本地
ASR' escape row, which is rendered exactly when no inline Toggle
can disable the active engine.

Comment updated to match the new behavior and document the
tradeoff.

* fix(localasr): scope Qwen3 mgmt UI to macOS only (pr_agent #403)

pr_agent 'Linux regression' caught: previous wrap was `!IS_WINDOWS`,
so a hypothetical Linux render path would still expose the Qwen3
mirror / model-list / engine-status UI even though Qwen3's backend
is `#[cfg(target_os = "macos")]`.

Swap the two wrappers to `IS_MAC` so the management cards only
materialize on macOS. Today's AdvancedSection guards LocalAsr
embedded with `platformSupported = isMac || isWin`, so Linux already
short-circuits before LocalAsr renders — but defense in depth here
costs nothing and keeps the comment accurate.

---------

Co-authored-by: baiqing <lbx12309@icloud.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant