Skip to content

feat(tui): v0.3.0 - entry templates, log notes, word navigation, daily totals#106

Open
alxhall wants to merge 57 commits intoponbac:masterfrom
alxhall:feat/tui-v0.3
Open

feat(tui): v0.3.0 - entry templates, log notes, word navigation, daily totals#106
alxhall wants to merge 57 commits intoponbac:masterfrom
alxhall:feat/tui-v0.3

Conversation

@alxhall
Copy link
Collaborator

@alxhall alxhall commented Mar 12, 2026

Summary

A collection of new features and improvements for the TUI. Closes #102.

New features

Entry templates

Define reusable presets in config.toml via [[template]] sections (name, project, activity, note). Press T in the timer view to open a fuzzy picker and apply a template to the current entry.

[[template]]
name = "Standups"
project = "My Project"
activity = "Meeting"
note = "Daily standup"

Log notes

Attach a local markdown file to any time entry. Press Ctrl+L in the description editor to create/open the log, Ctrl+R to remove the link. The link is stored as a tag embedded in the note field ([log:XXXXXX]) and stripped in all display locations — only the clean summary is shown.

Log files live in ~/.local/share/toki-tui/logs/ and are never synced to Milltime. Ctrl+L is also available from the timer and history views to open a linked log directly without entering edit mode.

Word-boundary navigation

Ctrl+←/→ and Ctrl+Backspace for word-level cursor movement and deletion across all text inputs (description, note, project/activity search, CWD, template search).

Daily totals in history separators

Date separators in the history view and this-week panel now show total logged hours for that day, e.g. Monday 2026-03-10 (04h30m).

Key binding changes

Old New Action
R Ctrl+R Resume last / selected entry
Y Removed; merged into Ctrl+R (copies when timer running)
G X Toggle timer size
T T Now opens template picker (was toggle size)

Other

  • Force full redraw on FocusGained to recover from corruption after
    sleep/wake
  • Remove cursor block artifact from note field in inline history edit row
  • Rename "Stats" → "Statistics" in hint bar and view title
  • Add Ratatui render tests and action handler unit tests

alxhall added 30 commits March 12, 2026 09:50
…r bool arg, attest_level, timer_size assertions)
alxhall added 26 commits March 12, 2026 12:55
- Timer view Note box: show muted '[...]' indicator instead of green dot
- Timer/History entry rows: show '[...]' in white instead of '·' bullet
- Fix raw log tag visible in edit-row Note field when focused (cursor view)
- Notes view: add read-only Log box showing linked log file content
- Notes view Info box: add 'Log file:' line when log is linked; grow to 4 lines
- Notes view Controls: simplify Ctrl+L hint; add Shift+Ctrl+L for detach
- Keybinding: Shift+Ctrl+L detaches log from current note (clears description_log_id)
- Replace ▏ block cursor with proper set_cursor_position() in full-screen inputs (Notes view, CWD, search views)
- Replace ▏ in inline note widgets with underlined-char spans (no extra-width character)
- Fix running timer log bleeding into entry edit Notes view (use set_note_from_raw)
- Fix Enter and Ctrl+X dropping description_log_id in edit_description view
- clear_note() and clear_timer() now also clear description_log_id
- Simplify log file frontmatter to id + date only (drop stale fields)
- Fix log path display (~/... format)
- Ctrl+R replaces Shift+Ctrl+L to remove/detach log
- Remove unused TextInput import in actions.rs
- cwd_delete_word_back: clear completions consistently with other input mutators
- editor: restore TUI (enable_raw_mode + EnterAlternateScreen) even when
  the editor process fails to launch, preventing broken terminal state
- log_notes: validate id is hex-only in log_path to prevent path traversal
- log_notes: capture SystemTime::now() once to avoid a theoretical race
- log notes render: cache log file content on App, eliminating per-frame
  synchronous file I/O in the description editor render path
- template selection: show status message when project is not found instead
  of navigating back silently

Rejected: reviewer suggestion to assert status_message after
handle_confirm_delete — navigate_to() calls clear_status() so the
original assertion (is_none) is correct.
- editor: split $EDITOR/$VISUAL on whitespace so 'code -w' works correctly
- editor: capture restoration errors separately; prefer original editor
  launch error over TUI restore error in the return value
- log_notes: doc comment accurately describes timestamp-based derivation
- log_notes: add AtomicU64 monotonic counter to generate_id to avoid
  collisions on rapid successive calls within the same process
- log_path: enforce lowercase hex only (reject A-F) to match generate_id output
- template apply: show status when activity name is not found instead of
  silently skipping
- template apply: use full_note_value() when syncing running timer so any
  linked log tag is included, consistent with other sync sites
- event_loop: move needs_full_redraw clear+draw before terminal.draw() to
  prevent a flash frame after sleep/wake or editor return

Rejected: test assertion for 'Entry deleted' — navigate_to() calls
clear_status(), so status_message is None after handle_confirm_delete returns;
original is_none() assertion is correct.
Rejected: cursor adjustment in description_editor — description_input.value
never contains the tag (architecture invariant), cursor is already correct.
@vercel
Copy link

vercel bot commented Mar 12, 2026

@alxhall is attempting to deploy a commit to the ponbac's projects Team on Vercel.

A member of the Team first needs to authorize it.

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.

1 participant