From 9887b8134daa8b6113c6e8a89f24942c6f1d93d4 Mon Sep 17 00:00:00 2001 From: Justin Hawkins Date: Sun, 22 Jun 2025 13:47:25 +0200 Subject: [PATCH] Cancel tracker --- model.go | 70 ++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 61 insertions(+), 9 deletions(-) diff --git a/model.go b/model.go index d7d68ff..6f1df90 100644 --- a/model.go +++ b/model.go @@ -34,7 +34,17 @@ const MODE_FORMENTRY tuiMode = "MODE_FORMENTRY" var version = "dev" +type tickMsg time.Time + +func tick() tea.Cmd { + return tea.Tick(time.Second, func(t time.Time) tea.Msg { + return tickMsg(t) + }) +} + type model struct { + currentTime time.Time + miteAPI mite.APIClient start calendarTime dest calendarTime @@ -97,7 +107,11 @@ func initialModel(miteDomain, miteApiKey string) model { } func (m model) Init() tea.Cmd { - return m.fetchMiteData() + + return tea.Batch( + m.fetchMiteData(), + tick(), + ) } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -106,6 +120,10 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { switch msg := msg.(type) { + case tickMsg: + m.currentTime = time.Time(msg) + return m, tick() // schedule next tick + case miteDataFetchedMsg: if msg.Error != nil { m.statusBarMessage = fmt.Sprintf("Error fetching: %s", msg.Error.Error()) @@ -135,13 +153,14 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } m.debug = append(m.debug, fmt.Sprintf("Got a %#v", msg)) - if m.tuiMode == MODE_TIMEENTRIES { + switch m.tuiMode { + case MODE_TIMEENTRIES: return m.updateEntries(msg) - } else if m.tuiMode == MODE_CAL { + case MODE_CAL: return m.updateCal(msg) - } else if m.tuiMode == MODE_FORMENTRY { + case MODE_FORMENTRY: return m.updateForm(msg) - } else { + default: panic(m.tuiMode) } } @@ -190,13 +209,29 @@ func (m model) updateEntries(msg tea.Msg) (tea.Model, tea.Cmd) { m.formData.form = m.buildForm() m.formData.form.Init() return m, nil + case "c": + if m.timeData.tracker != nil { + m, msg := m.cancelTracker() + return m, msg + } } } newTable, tableCmd := m.timeData.table.Update(msg) m.timeData.table = newTable return m, tableCmd +} +func (m model) cancelTracker() (model, tea.Cmd) { + stopped, err := m.miteAPI.StopTimeTracker(m.timeData.tracker.ID) + if err != nil { + m.statusBarMessage = err.Error() + return m, nil + } else { + m.statusBarMessage = fmt.Sprintf("Stopped tracking: %d", stopped.ID) + m.timeData.tracker = nil + return m, m.fetchMiteData() + } } func (m model) updateCal(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -236,6 +271,12 @@ func (m model) updateCal(msg tea.Msg) (tea.Model, tea.Cmd) { m.statusBarMessage = "Fetching data from API" return m, m.fetchMiteData() + // cancel tracker + case "c": + if m.timeData.tracker != nil { + return m.cancelTracker() + } + // // The "up" and "k" keys move the cursor up // case "up", "k": // if m.cursor > 0 { @@ -277,7 +318,7 @@ func (m model) updateCal(msg tea.Msg) (tea.Model, tea.Cmd) { m.timeData.table.SetRows(m.tableDataForDate(m.dest.Time)) return m, nil } - // The "enter" key and the spacebar (a literal space) toggle + // The "enter" key and the space bar (a literal space) toggle // the selected state for the item that the cursor is pointing at. // case "enter", " ": // _, ok := m.selected[m.cursor] @@ -388,7 +429,7 @@ func (m model) View() string { } else { lhs.WriteString("\n") } - if m.tuiMode != MODE_FORMENTRY { + if m.globalKeyMode() { lhs.WriteString("(a)dd time entry\n") } else { lhs.WriteString("\n") @@ -404,9 +445,14 @@ func (m model) View() string { } if m.timeData.tracker != nil { - activeTime := time.Since(m.timeData.tracker.Since).Truncate(time.Minute).String() - activeTime = strings.Replace(activeTime, "0s", "", 1) + activeTime := time.Since(m.timeData.tracker.Since).Truncate(time.Second).String() + activeTime = strings.Replace(activeTime, "0ms", "", 1) lhs.WriteString("\nTracker active: " + activeTime + "\n") + if m.globalKeyMode() { + lhs.WriteString("(c)ancel\n") + } else { + lhs.WriteString("\n") + } } if m.tuiMode == MODE_TIMEENTRIES { @@ -449,3 +495,9 @@ func (m model) View() string { return out } + +// globalKeyMode indicates when the UI can receive most keystrokes for global operations - +// mostly this means the form is not active +func (m model) globalKeyMode() bool { + return m.tuiMode != MODE_FORMENTRY +}