Skip to content

feat(year-review): Year in Review — activity wall, keyboard personality, active hours, achievements (Windows + macOS) - #153

Open
LingyiChen-AI wants to merge 11 commits into
debugtheworldbot:mainfrom
LingyiChen-AI:feature/heatmap-color-scheme
Open

LingyiChen-AI wants to merge 11 commits into
debugtheworldbot:mainfrom
LingyiChen-AI:feature/heatmap-color-scheme

Conversation

@LingyiChen-AI

Copy link
Copy Markdown
Contributor

Summary

Adds a Year in Review window on both Windows and macOS with four tabs: Activity Wall, Keyboard Personality, Active Hours and Achievements. All charts follow the heatmap color scheme from #152.

Entry points:

  • Windows: a "Year in Review" button in the stats popup header, and a tray menu item
  • macOS: a calendar icon in the stats popover toolbar

1. Activity Wall

  • GitHub-style daily grid with columns for weeks and rows for Mon–Sun
  • Range: past 12 months, or any calendar year that has data
  • Metric: key presses or clicks
  • Four quartile color levels that match the legend
  • Summary cards: total, active days, current streak, longest streak, best day

2. Keyboard Personality

Covers today, the last 7 days, the last 30 days or all time.

Metrics: shortcut ratio, regret index (Backspace/Delete share), copy vs. paste, undo count, arrow-key share, clicks per 100 keys and top keys.

Picks one main personality from Shortcut Master, Copy-Paste Engineer, Perfectionist, Arrow Key Walker, Mouse Person, Keyboard Purist and Balanced Player. Any other personalities that also match are shown as secondary tags. The rules live in a pure analyzer that is identical on both platforms.

3. Active Hours

  • 24-hour chart of the daily average per hour
  • Peak hour, night share (22:00–05:00) and chronotype: Night Owl, Early Bird, Afternoon Person or Evening Person
  • Windows: DailyStats gains optional hourlyKeyPresses / hourlyClicks arrays, recorded per local hour.
    • Legacy data reads as zeros
    • Import merge sums the arrays per hour
    • The arrays are not part of the sync protocol
  • macOS: reuses the existing HourlyStats data, so the data layer is unchanged.

4. Achievements

16 milestones:

  • Total keys: 100K / 1M / 10M
  • Keys in a single day: 10K / 30K / 50K
  • Total clicks: 100K / 1M
  • Streaks: 7 / 30 / 100 days
  • Active days: 100 / 365
  • Peak speed: 10 / 15 KPS
  • Mouse Marathon: 42.195 km, using the user's distance calibration

Locked cards show progress. Unlocks are evaluated every 60 s:

  • On the first run, milestones that are already reached are backfilled silently.
  • After that, each new unlock shows a system notification. This can be turned off in notification settings and is on by default.

New settings:

Key Default
unlockedAchievements (id → yyyy-MM-dd) {}
achievementsInitialized false
achievementNotificationsEnabled true

Screenshots

All screenshots use synthetic data.

Windows

Activity Wall Activity Wall (custom palette)
Keyboard Personality Active Hours

Achievements

macOS

Activity Wall Activity Wall (custom palette)
Keyboard Personality Active Hours
Achievements (light) Achievements (dark)

Test plan

  • Windows: dotnet build passes with 0 warnings.
  • Windows: 24 new unit tests pass, covering the persona, chronotype, hourly and achievement rules.
  • Windows: the full suite still has 2 failing sync tests (SingleDeviceCodeWithoutAuthoritativeCount_RemainsAConflict, ManualTransportFailure_AddsSixtySecondRetryDelay). They fail on main too, so this PR does not cause them.
  • macOS: all 134 swift test tests pass.
  • macOS: screenshots were rendered by an offscreen harness built from this branch. Running the app from Xcode has not been checked yet.
  • Windows: an existing settings.json / daily_stats.json without the new fields still loads.
  • Merged with upstream main (fix(stats): attribute activity to foreground apps  #151, feat(heatmap): configurable heatmap color schemes (Windows + macOS) #152). The diff only contains the new features.

LingyiChen-AI and others added 11 commits October 22, 2026 15:44
Add a heatmap color setting with 7 presets (default blue, warm, spectrum,
green, teal, purple, rose) plus a custom low/high color picked from the
system color dialog. The settings card shows a live palette preview and
open heatmap windows repaint immediately. Default palette is unchanged.
Mirror the Windows heatmap color setting: same presets and gradient math,
custom low/high colors via NSColorWell, palette preview in settings, and
live repaint of open heatmap views. Default palette is unchanged.
Add a Year in Review window with an activity wall (GitHub-style daily grid,
past 12 months or calendar year, keys or clicks, quartile color levels that
follow the heatmap palette, streak and best-day summary) and a keyboard
personality tab (shortcut ratio, regret index, copy/paste, undo, arrow keys,
click ratio, top keys). Entry points: stats popup header and tray menu.
Persona rules live in KeyboardPersonaAnalyzer with unit tests.
Mirror the Windows Year in Review window: activity wall and keyboard
personality tabs with the same rules, opened from the stats popover.
Pure logic lives in YearReviewModels.swift (added to KeyStatsCore) with
unit tests.
Record key presses and clicks per local hour in DailyStats (new optional
hourlyKeyPresses/hourlyClicks fields; legacy data reads as zeros, merge
sums per hour, not part of the sync protocol). Year in Review gains an
Active Hours tab (daily-average bar chart, peak hour, chronotype, night
share) and an Achievements tab (16 milestones with progress and unlock
dates). AchievementService evaluates every 60s, backfills silently on
first run and toasts new unlocks; the toast can be turned off in
notification settings.
Mirror the Windows tabs on macOS. Active Hours reuses the existing
HourlyStats data instead of adding new DailyStats fields. AchievementManager
evaluates every 60s, backfills silently on first run and sends unlock
notifications, with a toggle in notification settings.
人格页卡片行高写死 76pt,而「标题 + 数值 + 说明」三行加上下 12pt
内边距实测需要 84pt,导致说明那行被卡片底边截掉一半(深浅色均复现)。
改为 84pt,与活跃时段 / 贡献墙页同款卡片的留白一致。
…ground app attribution debugtheworldbot#151)

# Conflicts:
#	KeyStats.Windows/KeyStats/Models/AppSettings.cs
#	KeyStats.Windows/KeyStats/Properties/Strings.cs
#	KeyStats.Windows/KeyStats/Properties/Strings.resx
#	KeyStats.Windows/KeyStats/Properties/Strings.zh-Hans.resx
#	KeyStats.Windows/KeyStats/Properties/Strings.zh-Hant.resx
#	KeyStats/en.lproj/Localizable.strings
#	KeyStats/zh-Hans.lproj/Localizable.strings
#	KeyStats/zh-Hant.lproj/Localizable.strings
#	Package.swift

This branch has not been deployed

No deployments
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.

2 participants