Skip to content

feat: add optional session categories - #514

Open
561emir wants to merge 8 commits into
Splode:mainfrom
561emir:feat/session-categories
Open

561emir wants to merge 8 commits into
Splode:mainfrom
561emir:feat/session-categories

Conversation

@561emir

@561emir 561emir commented Sep 26, 2026 •

Copy link
Copy Markdown

Closes #371

Adds optional categories for focus rounds. It's off by default, so nothing changes until it's turned on in Settings → Categories.

  • Pick the category for focus rounds from the titlebar
  • Add (up to 10), rename, recolor or delete categories in Settings
  • Filter the stats by category
  • Rounds without a category (recorded while the feature was off, or from a deleted category) show as "Uncategorized"
  • New strings added for all 8 languages

Database: migration 7 adds a categories table and a nullable sessions.category_id column.

npm run check, cargo clippy -- -D warnings and cargo test pass.

1-titlebar-picker 2-settings-categories 3-stats-filter

Add an opt-in way to file focus rounds under categories so that, for
example, work and leisure sessions can be tracked separately.

- MIGRATION_7 adds a `categories` table seeded with three built-in
  categories (work, study, leisure) and a nullable `sessions.category_id`.
  Existing sessions stay uncategorized. Built-in categories keep a NULL
  name until renamed so the frontend can show a localized name.
- New settings: `categories_enabled` (default false), `active_category_id`
  and `stats_hidden_categories`.
- When enabled, a completed focus round is recorded under the active
  category, falling back to the first category if the stored one was
  deleted. Breaks are never categorized.
- Deleting a category moves its rounds to uncategorized instead of
  deleting them.
- Stats commands accept an optional filter that hides categories and/or
  uncategorized rounds; without a filter the results are unchanged.
- New commands: categories_list/create/update/delete/round_count and
  stats_uncategorized_count. Category changes emit `categories:changed`.
Add the strings used by the categories UI (settings section, titlebar
switcher, stats filter and delete confirmation) to every locale: en, es,
fr, de, ja, zh, pt and tr. Built-in category names (Work, Study, Leisure)
are localized; user-created names are shown as typed.
- New Categories section (between Timer and Appearance) with the opt-in
  toggle and a note that turning it off only hides categories.
- List of up to 10 categories with a color palette, inline renaming and
  delete with a confirmation that says how many rounds will move to
  Uncategorized. Clearing a built-in category's name restores its
  localized default; user-created categories always need a name.
- The settings window can open at a section via `?section=` or a
  `settings:navigate` event from another window.
- Shared frontend plumbing: Category/StatsFilter types, IPC wrappers, a
  per-window categories store kept in sync by `categories:changed`, and
  category helpers.
When categories are enabled, a small switcher next to the settings and
statistics buttons shows the active category and lets you change it;
its menu also links to the Categories settings. In the compact window
only the color dot is shown and the tooltip names the category.
When categories are enabled, a row of chips under the tabs chooses which
categories the Today, This Week and All Time views include. The
selection is saved in settings; an Uncategorized chip appears when there
are rounds without a category. With categories off, the stats are
unchanged.
A round that was reset before it finished was left without a category,
so it counted as Uncategorized and skewed the Today completion rate
whenever a category filter was active. The category is now stored when
the round starts and still updated when it ends.

resolve_active_category also no longer hides database errors.
- Keep one trigger button so keyboard focus isn't lost when the menu
  opens or closes, and give it an accessible name, since the compact
  window hides the category name.
- Don't open an empty menu once every category has been deleted.
- Clearing the name of a built-in category that was never renamed shows
  its name again instead of leaving the field blank.
Wrap the new Rust lines like the surrounding code and list the
categories:changed event in CLAUDE.md.

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.

FR: Statistics for Different Activities

1 participant