summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-04-26 19:06:12 +0300
committerPaul Buetow <paul@buetow.org>2026-04-26 19:06:12 +0300
commitca680540998776c2b42f6d1a827102b20139f8cf (patch)
tree3bad6a131d7bd1efb369fab821d46ef30299951a
parent1528fbd588262bcd39130ab0829219254ca371d9 (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.go40
-rw-r--r--internal/ui/taskdetail.go1
-rw-r--r--internal/version.go2
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"