fix: address stats review follow-ups (persistence, UX, tokenization) - #170
Merged
Conversation
Follow-up to the #148/#168 review. #168 already fixed the timezone and streak bugs; this covers the remaining findings: - UserStats: decode leniently via decodeIfPresent so future schema additions no longer fail to decode and silently wipe saved stats on upgrade (synthesized Codable requires every non-optional key). - StatsManager: count words with the system tokenizer (.byWords) so space-less scripts (Chinese, Japanese, Thai) aren't undercounted as a single word; write stats off the main actor on a serial queue so a busy disk can't hitch the UI; drop the unused dailyDurationSeconds field; and guard the application-support force-unwrap. - StatsSettingsTab: confirm before the destructive "Reset All Statistics"; parse date keys with a fixed POSIX locale; relabel WPM as "Speaking Speed" to match what it measures (words per minute of audio). - Tests for lenient decode and space-less word counting.
Member
Author
|
/build |
|
⏳ PR Build started for Build signed & notarized DMG... this usually takes 10–20 minutes. |
|
✅ PR Build ready!
📥 Install
SHA-256 checksum
|
This was referenced Jul 1, 2026
jatinkrmalik
added a commit
that referenced
this pull request
Jul 2, 2026
* docs(web): document v0.7.0 features on the website Adds website coverage for features shipped since v0.6.2 (audit found 4 of 5 uncovered; Homebrew was already fully covered, left untouched): - New feature pages: Custom Vocabulary (#169) and Usage Statistics (#148/#168/#170), each with a landing-page grid card. - Landing JSON-LD featureList: add custom vocabulary, local usage stats, and selectable audio input device (#156). - Hotkey presets + custom recording (#139): fix stale "key combination" copy in fully-configurable.md, document the Record/custom-key capture and add the Right Control preset in push-to-talk.md, and update the FAQ. - Audio input device (#156): expand fully-configurable.md (System Default, non-invasive pinning, auto-fallback on disconnect, Refresh Devices). - Screenshots gallery: add a Stats tab entry. Two screenshots still needed from a real capture (marked with SCREENSHOT PLACEHOLDER comments): settings-stats.png and settings-vocabulary.png. Verified with `hugo` (build succeeds; new pages render; JSON-LD valid). * polish(web): refine features grid, fix mobile hero overflow, SEO pass Features grid: - Switch from a fixed 4-col grid (which left 2 orphan cards hanging and, via grid-auto-rows:1fr, forced every row to the tallest card's height) to a centered flex-wrap layout: uniform card heights, the short last row centers, and 4/2/1 columns at desktop/tablet/mobile. - Apple-style polish: icon squircle tiles, tighter 1–2 line copy on every card, softer corners, refined heading type, gentler hover. Mobile hero: - The 380px mockup forced the hero column wider than small viewports, clipping the subtext/pills/buttons. Reset min-width and clip the decorative mockup so nothing overflows below ~420px. SEO: - og:type now "article" for content pages (was always "website"). - Enriched the home and features-list meta descriptions. - Verified across all 18 pages: unique titles, one <h1> each, descriptions present, all <img> have alt, sitemap includes the new pages. Screenshots: add settings-stats.png and settings-vocabulary.png (referenced by the new feature pages) and refresh settings-general.png.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Follow-up to the review of #148 (stats feature) by @Mr-Sunglasses. Note that #148 is already merged, and #168 landed the two biggest review findings (UTC-vs-local timezone bucketing and the wall-clock streak dependency), along with tests. This PR cleans up the remaining review findings.
Changes
Persistence / data safety
UserStatsnow decodes leniently (decodeIfPresent+ defaults). SynthesizedCodablerequires every non-optional key, so the day a new field is added, every existingstats.jsonwould fail to decode and silently reset all history. Lenient decoding makes the schema forward/backward compatible. Also ignores now-removed legacy keys.dailyDurationSecondsfield (written on every transcription but never read).Correctness
enumerateSubstrings(options: .byWords)) instead of splitting on whitespace, so space-less scripts (Chinese, Japanese, Thai) are no longer counted as a single word.en_US_POSIXlocale so theyyyy-MM-ddkeys parse correctly regardless of the user's default calendar/locale.UX
Robustness / performance
Tests
testStatsDecodeToleratesMissingAndUnknownKeys— missing keys fall back to defaults; unknown/legacy keys are ignored.testWordCountHandlesSpacelessScripts— a Japanese sentence tokenizes to more than one word.swift test --filter StatsManagerTests→ 11 passed.Not changed
averageWPMsemantics (words per minute of audio) are unchanged — only the UI label was clarified.