uttrflow / uttrflow/uttrflow-swift
VoiceOver's label for a clipboard row leaves out whether it is pinned, a picture's size or that its file is gone, and a note's checklist progress
- Dominant language
- Swift
- Stars
- 4
- Forks
- 17
- Avg merge
- 3h 32m
- Merged PRs (30d)
- 277
Description
## What happens
`QuickPanelSpeech.label(for:)` (`Sources/Uttrflow/Panel/QuickPanelRowAppearance.swift:42-48`) builds a row's spoken label from four parts: kind, alias, summary (or "hidden") and time.
```swift
[noun(for: row.kind), row.alias, body, row.when]
```
The row's children are ignored for accessibility (`QuickPanelView.swift:464`), so anything drawn on the row but missing from this list is invisible to VoiceOver:
- **Pinned.** The pin glyph (`QuickPanelView.swift:538-542`). `PanelRow.isPinned` is not spoken.
- **A picture's measurements.** A picture row's summary is empty, so it reads only "Image, 2 minutes ago". The "2880 × 1800 · 1 MB" or source and size text (`PanelRow.measurements`) is not spoken.
- **A missing picture.** "The picture is no longer on this Mac" is also `measurements`, so a broken row sounds like a working one.
- **Checklist progress.** "2 of 5" (`PanelRow.checklist`) is not spoken.
- **Collection.** `PanelRow.category` is not spoken while browsing a tab that mixes collections.
The code language chip has its own label ("swift code", `:521`), but it is a child of the ignored element, so it is not heard either.
## Why it matters
Picture rows are indistinguishable from each other by ear, and a missing picture sounds pasteable. A VoiceOver user cannot tell which clips they pinned.
## Acceptance criteria
- The label includes, where present: "pinned", the picture's measurements (or the missing-picture sentence), checklist progress, the code language, and the collection.
- A masked row still speaks nothing of the clip's content: no language, no checklist.
- New cases in `QuickPanelSpeechTests` (`Tests/UttrflowTests/QuickPanelRowAppearanceTests.swift:77`) cover a pinned row, a picture row, a missing-picture row, a note with boxes and a masked row with a language.
## Where to start
- `Sources/Uttrflow/Panel/QuickPanelRowAppearance.swift:40-67`
- Test to extend: `Tests/UttrflowTests/QuickPanelRowAppearanceTests.swift` (`QuickPanelSpeechTests`)
- Before pushing, run `make verify` (export `DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer` first). It is the same command CI runs, and it enforces the 95% coverage floor per module.
- Read [CONTRIBUTING.md](https://github.com/uttrflow/uttrflow-swift/blob/main/CONTRIBUTING.md) first, and say on this issue that you are taking it.
**Size:** S, about 1 to 2 hours.
Contributor guide
Research direction
Read CONTRIBUTING.md first, then inspect QuickPanelSpeech.label(for:) in Sources/Uttrflow/Panel/QuickPanelRowAppearance.swift:40-67 and the QuickPanelSpeechTests in Tests/UttrflowTests/QuickPanelRowAppearanceTests.swift. Add the specified accessibility-label cases, including masking behavior, and run make verify with DEVELOPER_DIR set as described.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- macos, swift
- Domain
- accessibility, desktop
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 88/100