Skip to content

Add template recall, keyboard navigation, and saved entry management - #43

Open
nedimperva wants to merge 12 commits into
masterfrom
claude/app-improvement-ideas-axv4kt
Open

Add template recall, keyboard navigation, and saved entry management#43
nedimperva wants to merge 12 commits into
masterfrom
claude/app-improvement-ideas-axv4kt

Conversation

@nedimperva

Copy link
Copy Markdown
Owner

Summary

This PR introduces three major features to enhance the command bar experience: template recall via #slug syntax, keyboard-driven navigation between views, and improved saved entry management with automatic tagging, staleness detection, and template sharing.

Key Changes

Template Recall System

  • New src/lib/saved/template-ref.ts: Core template reference parsing and expansion
    • parseTemplateRef() parses #slug or #slug x3 syntax from queries
    • findTemplateSource() resolves slugs to saved entries with prefix matching and freshness-based tie-breaking
    • expandTemplateReference() reconstructs canonical queries from saved entries, enabling zero-UI library access
    • Comprehensive unit tests in src/lib/saved/template-ref.test.ts

Saved Entry Enhancements

  • New src/lib/saved/tags.ts: Automatic tagging and staleness detection
    • suggestTags() derives zero-keystroke tags from profile family and material grade
    • isStaleSaved() flags unused entries older than ~6 months for proactive cleanup
    • daysSince() utility for age calculations
    • Full test coverage in src/lib/saved/tags.test.ts
  • Duplicate-aware saves: useSaved() now deduplicates plain single-calc saves by fingerprint, bumping existing entries instead of creating twins
  • Tag filtering UI: Desktop saved view gains tag chips for one-click filtering of the library
  • Staleness indicators: Unused old saves display a "unused" badge in the grid
  • Template sharing: New onShare action copies/shares saved entries as ?q= URLs for WhatsApp-friendly distribution

Keyboard Navigation

  • Desktop workspace shortcuts:
    • ? opens/closes a keyboard shortcuts overlay
    • g + c/s/p/k/, navigates to Calculator, Saved, Projects, Compare, Settings
    • Shortcuts work outside the input field without interfering with normal typing
  • New DeskShortcutsOverlay component: Displays available shortcuts with visual key indicators

Changelog & Version Management

  • New src/hooks/useWhatsNew.ts: Manages "What's new" gate that shows changelog once per version upgrade
  • New src/components/command/sheets/changelog-sheet.tsx: Renders changelog entries with categorized bullets (Added/Changed/Fixed)
  • Updated src/lib/changelog.ts: Added v3.7.0 entry with feature descriptions in English and Bosnian
  • Settings sheet gains "What's new" button to manually reopen changelog

Supporting Infrastructure

  • New src/hooks/useNow.ts: Pure wall-clock time hook for staleness checks
  • Updated useSaved() return type: saveCalculation() now returns SaveOutcome with bumped flag for toast differentiation
  • Internationalization: Added message keys for new features in messages/en.json and messages/bs.json
  • Updated CHANGELOG.md: Documents unreleased features

Implementation Details

  • Template recall reuses the existing inputToQuery() reconstruction path, ensuring consistency with click-to-load behavior
  • Staleness detection is pure (no side effects) and works across mobile/desktop without storage coupling
  • Tag suggestions are deterministic and capped at 2 to keep the UI clean
  • Keyboard navigation uses a 1.2s window for the g chord leader, preventing accidental triggers
  • The "What's new" gate silently records the current version on first run, only nagging on upgrades

https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ

claude added 5 commits July 24, 2026 10:45
Make the Saved library self-maintaining without adding new screens:

- Duplicate-aware saving: a plain save that matches an existing single-part
  entry (by result fingerprint) bumps that entry — use tick, refreshed
  recency, floated to the top — instead of leaving a near-identical twin.
  saveCalculation now reports the outcome so the toast can distinguish a
  fresh save from a bump. Multi-part templates always create a fresh entry.
- Automatic tags: new saves with no explicit tags are seeded with the
  profile family + grade (pure suggestTags helper, unit-tested).
- Tag filter on the desktop Saved grid: one-click chips derived from the
  library's distinct tags keep a growing library navigable.
- Staleness: entries never reused and aged past ~6 months show a subtle
  "unused" marker on both the mobile sheet and desktop grid — the proactive
  half of an archive flow. isStaleSaved/suggestTags live in a small pure
  lib with tests; a useNow hook reads the clock after mount to keep render
  pure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
Type `#gate` (or `#gate x3`) and press Enter to expand the saved entry named
"gate" into the command bar — the library becomes a first-class citizen of the
input line with no new UI. Expansion reuses inputToQuery, so a `#reference`
recalls anything the click-to-load path can, and nothing it can't.

- Pure, tested template-ref lib: slugify names, parse `#slug [xN]`, resolve
  (exact slug wins, else the freshest prefix match), and rebuild the query
  with the quantity overridden by the multiplier.
- Wired into all three input surfaces (phone keypad, medium card, wide
  workspace) via a shared commitTemplate handler threaded through the desktop
  props. Enter triggers expansion so `#gate x3` can be typed in full first;
  any other query keeps its existing commit behaviour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
The structured CHANGELOG data was rendered nowhere and APP_VERSION was stale
(3.6.2 while package.json is 3.7.0). Build a what's-new flow on top of it:

- useWhatsNew: records the current version on first run (never nags a new
  install) and opens the sheet once when the stored version differs after an
  upgrade; close marks the version seen. Manual reopen from Settings and the
  PWA update banner's "What's new" button (previously wired but never given a
  handler).
- ChangelogSheet: renders every entry since the last-seen version (localized
  EN/BS, falls back to the newest entry) via the existing SheetShell.
- changelog.ts: add the 3.7.0 entry (EN + BS) so APP_VERSION is current again,
  plus changelogSince() and entryBullets() helpers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
Add Gmail-style go-to navigation to the wide workspace: `g` then c/s/p/k/,
switches to Calculator, Saved, Projects, Compare, or Settings, and `?` opens a
shortcuts overlay that also documents `#name ↵` template recall. Chords are
handled in the existing global keydown listener and only fire outside the
command input, so typing `g` in a query is unaffected.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
Add a link action to the desktop Saved grid that reconstructs the entry's
canonical query and shares a ?q= URL — native share on a phone, clipboard
elsewhere. The recipient gets the calculation pre-filled in their own bar to
use or save, so shops can trade templates over WhatsApp. Falls back to a toast
when the entry can't be expressed as a query (same limit as click-to-load).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
@vercel

vercel Bot commented Jul 24, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
ferroscale Ready Ready Preview, Comment Jul 24, 2026 12:02pm

Mark a saved calculation's length as variable, then recall it with everything
remembered except the length — the user lands in the bar ready to type a fresh
length and watch the result recompute live. No modal, no re-entering profile.

- SavedEntry.variableParam ("length"), persisted through normalizeSavedEntry
  and toggled via updateSaved; preserved across sync.
- stripLengthToken() drops the length token from a canonical query (sheet-like
  families, which bake length into the size, are returned unchanged). Applied
  in both #template recall (expandTemplateReference) and click-to-load
  (loadInput gains a stripLength option), with unit tests.
- Desktop Saved card: an L? toggle (single-calc entries only) plus a badge so
  parametric templates read at a glance.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
Replace the generic family glyph on each desktop Saved card with a small,
undimensioned cross-section of the entry's real profile, so a saved calc is
recognisable by its shape.

- ProfileDrawing's renderSection gains a `bare` flag that omits the dimension
  callouts; a new ProfileMiniShape export renders just the shape cropped to a
  square around the content box (~34px), returning null when geometry can't be
  drawn.
- DeskSavedView reconstructs a parse result per entry (canonical query round-
  trip, memoized) to feed the thumbnail, falling back to the glyph otherwise.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
Surface numbers derived from data the app already keeps locally — no tracking,
no network, the user is the only audience.

- computeInsights (pure, tested): calculations recorded, distinct/most-used
  queries, most-used materials, library weight, and value grouped by currency
  (mixed currencies are never summed together). Honest by construction — no
  per-event history means no fabricated "busiest day".
- readUsageSnapshot exposes the raw usage stats; InsightsSheet assembles saved
  + project records and renders the metrics via SheetShell.
- Reachable from Settings (mobile sheet + desktop view) and `g i` on the
  desktop workspace; documented in the ? shortcuts overlay.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
- computeCompareDeltas takes an optional baselineId (falls back to the heaviest
  item, the historical default); unit-tested for the pinned and unknown-id
  cases.
- Desktop Compare view: every column past the first shows a "Set as base"
  action; the pinned column becomes the base all weight/cost deltas, the base
  badge, and the accent bar read from.
- "Save set" stores the current comparison as a multi-part entry in the Saved
  library (auto-named from the first couple of profiles) to revisit or rename.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
Group a project's lines by profile size + grade (length-agnostic) into total
pieces, total length, and total weight per item — a purchasing/cut-list view
that answers "what do I order" instead of a flat line list.

- computeProjectMaterials (pure, tested): folds project calculations into
  grouped rows sorted by weight, stripping per-piece length so different
  lengths of the same profile group together (sheet specs, which bake length
  in, pass through). Templates expand into their parts scaled by the quantity
  multiplier.
- Desktop project cards gain an expandable "Materials to order" section.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
The desktop projects view could only create, open, and remove lines. Add the
lifecycle controls the hook already supported (duplicate/delete) plus a new
status field:

- Project.status ("draft" | "quoted" | "won"), persisted through
  normalizeProject and synced; setProjectStatus added to useProjects.
- Desktop project cards gain a cyclable status badge and hover-revealed
  duplicate/delete actions, threaded through the desktop props. Delete is a
  soft-delete but has no in-view undo, so it requires a confirming second
  click within a few seconds.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
Auto-tags seed the library, but tags still need housekeeping. Add an "Edit
tags" mode to the desktop Saved view: the filter chips become inline editors.

- useSaved.renameTag(from, to) rewrites the tag on every entry — an empty
  target removes it, a target that already exists merges (deduped, order
  preserved).
- The active filter follows a rename so the view doesn't go blank.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017vrFRR75ma5jhRBzxotcMZ
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