Skip to content

feat(ios): show lifetime dictation stats - #233

Merged
alexkroman merged 11 commits into
jhe/blurt-designfrom
jhe/ios-stats
Oct 15, 2026
Merged

alexkroman merged 11 commits into
jhe/blurt-designfrom
jhe/ios-stats

Conversation

@he-james

@he-james he-james commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

What & why

Lifetime stats on the Dictate tab, matching the blurt-ios prototype:

  • Dictations, words and time saved. Time saved is measured against 36 wpm, the phone typing average (Palin et al., MobileHCI 2019). The typing test in a later PR will make it personal.
  • Layout: serif numbers with mono units. Time saved shows in full and moves to its own row past an hour. Every value uses the largest of four sizes that fits.
  • Every dictation counts, from the app or the keyboard. Words are counted as inserted, with text shortcuts expanded.
  • How it's measured: the coordinator times the recording phase, then records on the main actor when the dictation's terminal phase renders. That makes the spoken time the current recording's, and a reset can't race a record. A concurrency review flagged the first version, which recorded on the session actor.
  • Privacy: totals stay on the phone (DictationStats in BlurtiOSCore, app defaults). Settings › Data › Reset statistics clears them, after a confirmation.

iPhone only. Stacked on #232.

How it was tested

  • scripts/ios-check.sh: 142 tests (5 new for counting, time saved, persistence and formatting), BlurtiOSCore 96.85%, analyze, periphery and the probe build all pass.

  • design-sync.sh --check and swiftlint --strict are clean.

  • Simulator with seeded totals: the one-row layout in light, and the two-row layout past an hour in dark. The seeded totals were cleared afterwards.

  • scripts/check.sh passes (or CI will, if I'm not on a Mac)

  • I read AGENTS.md and this doesn't reintroduce anything deliberately removed

  • Docs updated if behavior changed

🤖 Generated with Claude Code

he-james and others added 4 commits October 2, 2026 18:11
KeyTerms (parse a comma-separated list, fit it to keyterms_prompt's
caps; was KeytermsBoost plus KeyTermsStore.parse) and TextShortcut with
its on-device TextShortcutExpander now live in Sources/AssemblyAI, so
any app on the SDK gets them. BlurtEngine keeps Blurt's storage:
KeyTermsStore and TextShortcutStore, their UserDefaults keys and limits.

The iPhone's duplicate KeyTermList is replaced by KeyTerms. The Mac app
only gains an import; its behaviour and stored data are unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The app gets Dictate and Words tabs under a brand tab bar, as in the
blurt-ios prototype. MainView owns what works on either tab: Settings
from each tab's gear, the consent sheet and shared key-term lists.

Words, on the AssemblyAI SDK's KeyTerms and TextShortcut:
- Key terms as pills with an inline add field (commas add several,
  duplicates drop, capped at the request's 100), the contact-name
  count, and Share. They move here from Settings.
- Text shortcuts with an inline "When I say / Type this" form;
  re-adding a phrase replaces it. Expanded on the phone, never sent.

BlurtDesign gains BrandTabBar, FlowLayout, brandInput() and
brandFootnote(), and brand buttons fade while disabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A stats card at the top of the Dictate tab, as in the blurt-ios
prototype: dictations, words, and time saved against the 36 wpm phone
typing average, as serif numbers with mono units. Time saved shows in
full and moves to its own row past an hour; every value takes the
largest of four sizes that fits.

Every dictation counts, from the app or the keyboard. The coordinator
times the recording phase and records on the main actor when the
dictation's terminal phase renders, so the spoken time is the right
one and a reset can't race a record. Totals stay on the phone
(DictationStats, BlurtiOSCore); Settings › Data resets them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
he-james and others added 2 commits October 2, 2026 18:30
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
he-james and others added 2 commits October 14, 2026 17:04
* feat(ios): add the easter egg

A quiet "How fast can you type?" link at the foot of Settings opens a
30-second sprint over common words, ported from the blurt-ios
prototype: the clock starts on the first key, turns orange and thumps
through the last five seconds, and the result shows WPM, a rank,
accuracy, the best, and how talking at 150 wpm compares.

The latest result becomes the typing speed time saved is measured
against, in place of the 36 wpm phone average, with a "Reset to
average" link beside it. Scoring and the speed live in BlurtiOSCore
(TypingTest, TypingSpeed) and are tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ios): present the Easter Egg once from Settings

The cover and the reset confirmation were attached to their sections,
and a section's modifiers apply to each of its rows, so the About
section's five rows each tried to present the Easter Egg at once. Both
now hang off the form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
* feat(ios): add a Words tab for key terms and text shortcuts

The app gets Dictate and Words tabs under a brand tab bar, as in the
blurt-ios prototype. MainView owns what works on either tab: Settings
from each tab's gear, the consent sheet and shared key-term lists.

Words, on the AssemblyAI SDK's KeyTerms and TextShortcut:
- Key terms as pills with an inline add field (commas add several,
  duplicates drop, capped at the request's 100), the contact-name
  count, and Share. They move here from Settings.
- Text shortcuts with an inline "When I say / Type this" form;
  re-adding a phrase replaces it. Expanded on the phone, never sent.

BlurtDesign gains BrandTabBar, FlowLayout, brandInput() and
brandFootnote(), and brand buttons fade while disabled.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ios): drop the Words tab pointer from Settings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Base automatically changed from jhe/ios-words to jhe/sdk-text-shortcuts October 15, 2026 00:05
@alexkroman

Copy link
Copy Markdown
Collaborator

@claude resolve conflicts

Base automatically changed from jhe/sdk-text-shortcuts to jhe/blurt-design October 15, 2026 00:15
he-james and others added 2 commits October 14, 2026 17:16
* feat(ios): add the easter egg

A quiet "How fast can you type?" link at the foot of Settings opens a
30-second sprint over common words, ported from the blurt-ios
prototype: the clock starts on the first key, turns orange and thumps
through the last five seconds, and the result shows WPM, a rank,
accuracy, the best, and how talking at 150 wpm compares.

The latest result becomes the typing speed time saved is measured
against, in place of the 36 wpm phone average, with a "Reset to
average" link beside it. Scoring and the speed live in BlurtiOSCore
(TypingTest, TypingSpeed) and are tested.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* fix(ios): present the Easter Egg once from Settings

The cover and the reset confirmation were attached to their sections,
and a section's modifiers apply to each of its rows, so the About
section's five rows each tried to present the Easter Egg at once. Both
now hang off the form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* feat(ios): open on a setup screen, then keep setup in Settings

As in the blurt-ios prototype, a first-run screen replaces the tabs
until Blurt is set up: the wordmark, a headline, and the numbered steps
in a card, with the API key pasted inline (Continue, Get a free key,
where the key and the audio go). Without a key it can't be left; with
one, Start dictating goes to the tabs and the microphone and keyboard
can wait. Whoever was already set up skips it.

The setup card leaves the Dictate tab. Settings › Setup keeps the
steps, hidden behind "Blurt is set up ✓ · Show steps" once everything
is done and open while anything isn't.

The rule is SetupProgress (BlurtiOSCore, tested); -BlurtNoKey shows a
fresh install's screen in debug builds without touching the Keychain.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Conflicts were all the iPhone app's own newer work beside the base's older
copy; kept this branch's side throughout: the stats and typing-test tokens
(tokens.json, DesignTokens.swift, DESIGN.md), RootView and SetupView in place
of the home SetupCard (#236), and the stats/typing state in Settings. The
base's engine changes (inputSilent, the latch key action) and project.yml
came through without conflict.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Tys59LNGo4prHRnc8w28Xy
@alexkroman
alexkroman marked this pull request as ready for review October 15, 2026 00:20
@alexkroman
alexkroman merged commit 6117e24 into jhe/blurt-design Oct 15, 2026
1 check passed
@alexkroman
alexkroman deleted the jhe/ios-stats branch October 15, 2026 00:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants