uttrflow / uttrflow/uttrflow-swift

"Download" and "Finish Setup" for a missing speech model open Settings → Dictation, which has no way to download it

Open
#671 0 comments 0 reactions 0 assignees View on GitHub
area:dictation bug P1
Dominant language
Swift
Stars
4
Forks
17
Avg merge
3h 32m
Merged PRs (30d)
277

Description

## What happens

When the speech model is not installed, every surface offers the same way forward, `RecoveryAction.downloadSpeechModel`:

- a dictation attempt fails with `SpeechEngineError.modelNotInstalled`, whose recovery is `.downloadSpeechModel` (`Sources/UttrflowCore/Errors/SpeechEngineError.swift:37`), drawn as "Download" on the floating button and "Finish Setup" in the menu;
- Diagnostics shows "Speech model · Not downloaded" with the same action (`Sources/UttrflowUX/DiagnosticsPresentation.swift:519-523`).

`AppDelegate.perform(_:)` handles it like this when the model is simply missing (`Sources/Uttrflow/AppDelegate.swift:1815-1817`):

```swift
case .downloadSpeechModel:
// Installing a model needs a window to show progress in. It has one now.
show(.settings(.dictation))
```

Settings → Dictation has no control that downloads the speech model. Its only speech row is "Speed and accuracy", and when no engine is ready it is disabled with "This option needs a download that has not finished yet." (`Sources/UttrflowUX/SettingsPresenter.swift:309-320`). The rest of the tab is clean-up steps, "Where your words go" and "Forget what was learned".

The only place that downloads the model is onboarding, which `perform` opens only for a model that failed to load (`repairSpeechModel`, `:240-246`).

The menu bar does not help either: with the model missing its status line is "Setup hasn't finished" and with a failed load "Speech model didn't load" (`Sources/UttrflowUX/MenuBarPresentation.swift:386-389`), and neither state adds a menu item to act on (the recovery item is added only for `state.failure`, `:437-440`).

This is separate from #530, which is about the load-failure *message* naming a reinstall control. Here the button itself goes to the wrong place.

## Why it matters

The model is missing whenever a user pressed Cancel or "Not now" on the download page, or went past it with "Start Using Uttrflow" on the "One thing still to download" ending. For those users dictation cannot work at all, and every "Download" / "Finish Setup" button they can find opens a Settings tab with nothing to press. Once onboarding has been finished it does not reopen on launch (`OnboardingFlow.isRequired`), and the "Set Up" buttons that do reopen it appear only for a permission that has not been asked (`Sources/UttrflowUX/MainPresentation.swift:188-197`), so there is no route back to the download at all.

## How to reproduce

1. Remove the installed speech model (dev bundle) and relaunch after onboarding has been finished once.
2. Hold the shortcut: the floating button offers "Download". Click it: Settings opens on Dictation with no download.
3. Open Diagnostics and click the action on "Speech model · Not downloaded": same result.
4. Open the menu bar menu: "Setup hasn't finished", and nothing to click.

## Acceptance criteria

- `.downloadSpeechModel` for a model that is not installed opens a surface that downloads it and shows progress (reopening onboarding at its setup page, as `repairSpeechModel` does, is the smallest change).
- The menu bar offers the same action whenever `speechModel` is `.notInstalled` or `.loadFailed`, not only after a failed dictation.
- The stale comment at `AppDelegate.swift:1816` is removed.
- A test covers the intent routing. `AppDelegate` is hard to test today (#145), so at minimum a presenter test pins the menu item for `.notInstalled` and `.loadFailed` in `Tests/UttrflowUXTests/MenuBarPresentationTests.swift`.

Contributor guide

Open the contributing guide

Research direction

Start in Sources/Uttrflow/AppDelegate.swift around perform(_:) and the repairSpeechModel path, then inspect Sources/UttrflowUX/MenuBarPresentation.swift and Tests/UttrflowUXTests/MenuBarPresentationTests.swift. Verify that the missing-model action reaches a downloading surface, menu actions exist for .notInstalled and .loadFailed, the stale comment is removed, and the presenter test covers both states.

Written by the indexing model from the issue text.

Assessment

Tech stack
macos, swift
Domain
desktop, testing
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.