diff options
| author | Paul Buetow <paul@buetow.org> | 2026-04-26 19:06:12 +0300 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-04-26 19:06:12 +0300 |
| commit | ca680540998776c2b42f6d1a827102b20139f8cf (patch) | |
| tree | 3bad6a131d7bd1efb369fab821d46ef30299951a | |
| parent | 1528fbd588262bcd39130ab0829219254ca371d9 (diff) | |
Release v0.16.0
Add d (mark done) and U (undo last done) hotkeys to the task detail
view opened with Enter, mirroring the table-view behavior.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
| -rw-r--r-- | internal/ui/detail_handlers.go | 40 | ||||
| -rw-r--r-- | internal/ui/taskdetail.go | 1 | ||||
| -rw-r--r-- | internal/version.go | 2 |
3 files changed, 42 insertions, 1 deletions
diff --git a/internal/ui/detail_handlers.go b/internal/ui/detail_handlers.go index 0f5a208..05ea7c4 100644 --- a/internal/ui/detail_handlers.go +++ b/internal/ui/detail_handlers.go @@ -77,6 +77,10 @@ func (m *Model) handleTaskDetailMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) { return m, nil case "o": return m.handleOpenURL() + case "d": + return m.handleDetailMarkDone() + case "U": + return m.handleDetailUndo() case "i", "enter": // Check if current field is editable return m.handleDetailFieldEdit() @@ -85,6 +89,42 @@ func (m *Model) handleTaskDetailMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) { return m, nil } +// handleDetailMarkDone marks the task currently displayed in the detail view +// as done. The detail view is closed first so the underlying table is visible +// for the blink animation and so the (now-completed) task isn't shown as +// pending after the reload triggered by startBlink. +func (m *Model) handleDetailMarkDone() (tea.Model, tea.Cmd) { + if m.currentTaskDetail == nil { + return m, nil + } + id := m.currentTaskDetail.ID + m.closeDetailView() + return m, m.startBlink(id, true) +} + +// handleDetailUndo restores the most recently completed task from the undo +// stack. The detail view is closed first because the undone task generally +// differs from the one currently displayed, and handleUndo blinks the +// restored row in the table. +func (m *Model) handleDetailUndo() (tea.Model, tea.Cmd) { + if len(m.undoStack) == 0 { + return m, nil + } + m.closeDetailView() + return m.handleUndo() +} + +// closeDetailView resets the detail-view state so the table view is shown +// again. Used by detail-view actions that intentionally exit the view (mark +// done, undo). +func (m *Model) closeDetailView() { + m.showTaskDetail = false + m.currentTaskDetail = nil + m.detailSearching = false + m.detailSearchRegex = nil + m.detailSearchInput.SetValue("") +} + // handleDetailFieldEdit starts editing for the currently-selected field in the // detail view. Fields 0-2 (ID, UUID, Status) and 6, 8 (Start, Entry) are // read-only; all others delegate to the appropriate activation helper. diff --git a/internal/ui/taskdetail.go b/internal/ui/taskdetail.go index 94e2ea9..eaf0b45 100644 --- a/internal/ui/taskdetail.go +++ b/internal/ui/taskdetail.go @@ -297,6 +297,7 @@ func (m *Model) renderDetailFooter(lines []string) []string { lines = append(lines, ist.Render("Press ESC or q to return to table view")) lines = append(lines, ist.Render("Use ↑/k and ↓/j to navigate fields")) lines = append(lines, ist.Render("Press i or Enter to edit (Priority, Tags, Due, Recurrence, Description)")) + lines = append(lines, ist.Render("Press d to mark task done, U to undo last done")) if m.detailSearching { lines = append(lines, ist.Render("Type to search, Enter to confirm")) } else { diff --git a/internal/version.go b/internal/version.go index 14fba0b..79440c2 100644 --- a/internal/version.go +++ b/internal/version.go @@ -1,4 +1,4 @@ package internal // Version is the current version of Task Samurai. -const Version = "0.15.0" +const Version = "0.16.0" |
