summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-06-23 06:53:20 +0300
committerPaul Buetow <paul@buetow.org>2026-06-23 06:53:20 +0300
commitf3b64f706e2df8ceffafdef916a127e8e22c296b (patch)
tree32b51da23581c28461d98578fcf27107bcab44ad
parent811a4f70fcaa6d806feb03b7b69fb6cb18d19142 (diff)
Refactor status auto-clear helper for xq0
-rw-r--r--internal/ui/editor_handlers.go19
-rw-r--r--internal/ui/handlers.go31
-rw-r--r--internal/ui/helpers.go16
-rw-r--r--internal/ui/helpers_test.go14
-rw-r--r--internal/ui/table.go2
5 files changed, 39 insertions, 43 deletions
diff --git a/internal/ui/editor_handlers.go b/internal/ui/editor_handlers.go
index 857e3c7..e85acf4 100644
--- a/internal/ui/editor_handlers.go
+++ b/internal/ui/editor_handlers.go
@@ -4,7 +4,6 @@ import (
"fmt"
"os"
"strings"
- "time"
tea "charm.land/bubbletea/v2"
)
@@ -34,21 +33,13 @@ func (m *Model) handleDescEditDone(msg descEditDoneMsg) (tea.Model, tea.Cmd) {
}
if msg.err != nil {
- m.statusMsg = fmt.Sprintf("Edit error: %v", msg.err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showStatusTimed(fmt.Sprintf("Edit error: %v", msg.err))
}
// Read the edited content
content, err := os.ReadFile(msg.tempFile)
if err != nil {
- m.statusMsg = fmt.Sprintf("Error reading file: %v", err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showStatusTimed(fmt.Sprintf("Error reading file: %v", err))
}
// Update the description
@@ -58,11 +49,7 @@ func (m *Model) handleDescEditDone(msg descEditDoneMsg) (tea.Model, tea.Cmd) {
err = m.taskwarriorClient().SetDescriptionContext(ctx, m.currentTaskDetail.ID, newDesc)
cancel()
if err != nil {
- m.statusMsg = fmt.Sprintf("Error updating description: %v", err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showStatusTimed(fmt.Sprintf("Error updating description: %v", err))
}
// Reload and start blinking
diff --git a/internal/ui/handlers.go b/internal/ui/handlers.go
index cc11f89..cd6b9de 100644
--- a/internal/ui/handlers.go
+++ b/internal/ui/handlers.go
@@ -3,7 +3,6 @@ package ui
import (
"fmt"
"strings"
- "time"
"charm.land/bubbles/v2/textinput"
tea "charm.land/bubbletea/v2"
@@ -15,11 +14,7 @@ func (m *Model) handleTextInput(msg tea.KeyPressMsg, input *textinput.Model, onE
case "enter":
value := input.Value()
if err := onEnter(value); err != nil {
- m.statusMsg = fmt.Sprintf("Error: %v", err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showErrorTimed(err)
}
input.Blur()
onExit()
@@ -172,11 +167,7 @@ func (m *Model) handleDueEditMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
err := m.taskwarriorClient().SetDueDateContext(ctx, m.dueID, m.dueDate.Format("2006-01-02"))
cancel()
if err != nil {
- m.statusMsg = fmt.Sprintf("Error: %v", err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showErrorTimed(err)
}
m.dueEditing = false
if !m.reloadAndReport() {
@@ -273,21 +264,13 @@ func (m *Model) handlePriorityMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
case "enter":
priority := priorityOptions[m.priorityIndex]
if err := validatePriority(priority); err != nil {
- m.statusMsg = fmt.Sprintf("Error: %v", err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showErrorTimed(err)
}
ctx, cancel := m.taskOperationContext()
err := m.taskwarriorClient().SetPriorityContext(ctx, m.priorityID, priority)
cancel()
if err != nil {
- m.statusMsg = fmt.Sprintf("Error: %v", err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showErrorTimed(err)
}
m.prioritySelecting = false
if !m.reloadAndReport() {
@@ -362,11 +345,7 @@ func (m *Model) handleAddTaskMode(msg tea.KeyPressMsg) (tea.Model, tea.Cmd) {
err := m.taskwarriorClient().AddLineContext(ctx, m.addInput.Value())
cancel()
if err != nil {
- m.statusMsg = fmt.Sprintf("Error: %v", err)
- cmd := tea.Tick(2*time.Second, func(time.Time) tea.Msg {
- return struct{ clearStatus bool }{true}
- })
- return m, cmd
+ return m, m.showErrorTimed(err)
}
m.addingTask = false
diff --git a/internal/ui/helpers.go b/internal/ui/helpers.go
index bebc937..5d753ab 100644
--- a/internal/ui/helpers.go
+++ b/internal/ui/helpers.go
@@ -6,6 +6,7 @@ import (
"strings"
"time"
+ tea "charm.land/bubbletea/v2"
"github.com/google/shlex"
"codeberg.org/snonux/tasksamurai/internal/task"
@@ -16,6 +17,21 @@ import (
// to qualify every parse/format call with the package name.
const taskDateFormat = task.DateFormat
+const statusClearDelay = 2 * time.Second
+
+type clearStatusMsg struct{}
+
+func (m *Model) showStatusTimed(message string) tea.Cmd {
+ m.statusMsg = message
+ return tea.Tick(statusClearDelay, func(time.Time) tea.Msg {
+ return clearStatusMsg{}
+ })
+}
+
+func (m *Model) showErrorTimed(err error) tea.Cmd {
+ return m.showStatusTimed(fmt.Sprintf("Error: %v", err))
+}
+
// parseTaskDate parses a date string in Taskwarrior format
func parseTaskDate(dateStr string) (time.Time, error) {
if dateStr == "" {
diff --git a/internal/ui/helpers_test.go b/internal/ui/helpers_test.go
index 7245145..8e58b63 100644
--- a/internal/ui/helpers_test.go
+++ b/internal/ui/helpers_test.go
@@ -434,6 +434,20 @@ func TestHandleTextInputKeepsStateOnEnterError(t *testing.T) {
}
}
+func TestClearStatusMsgClearsStatus(t *testing.T) {
+ m := Model{statusMsg: "temporary"}
+
+ mv, cmd := (&m).Update(clearStatusMsg{})
+ m = *mv.(*Model)
+
+ if cmd != nil {
+ t.Fatalf("clear status returned command")
+ }
+ if m.statusMsg != "" {
+ t.Fatalf("status message was not cleared: %q", m.statusMsg)
+ }
+}
+
func TestActivateDueEditFallsBackToNowOnInvalidDate(t *testing.T) {
m := Model{windowHeight: 20}
before := time.Now().Add(-time.Second)
diff --git a/internal/ui/table.go b/internal/ui/table.go
index be775fb..f7e9ed6 100644
--- a/internal/ui/table.go
+++ b/internal/ui/table.go
@@ -659,7 +659,7 @@ func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
return m.handleOpenURLDone(msg)
case blinkMsg:
return m.handleBlinkMsg()
- case struct{ clearStatus bool }:
+ case clearStatusMsg:
m.statusMsg = ""
return m, nil
case tea.KeyPressMsg: