From fe24e0422ed0b57c49cf8358431cb0cd50d2af8f Mon Sep 17 00:00:00 2001 From: Alex Pliutau Date: Fri, 30 Aug 2024 12:45:16 +0200 Subject: [PATCH] Add timers --- cli/commands.go | 13 ++++++++ cli/{textarea.go => inputs.go} | 12 ++++++- cli/model.go | 57 +++++++++++++++++++++++++++++----- cli/view.go | 14 ++++++++- 4 files changed, 87 insertions(+), 9 deletions(-) rename cli/{textarea.go => inputs.go} (84%) diff --git a/cli/commands.go b/cli/commands.go index 6181bd5..db0aae5 100644 --- a/cli/commands.go +++ b/cli/commands.go @@ -24,6 +24,7 @@ var commandFocusOn = command{ go server.StartAsSubprocess() m.status = hosts.FocusStatusOn + m.minutesLeft = 0 return m }, } @@ -39,6 +40,7 @@ var commandFocusOff = command{ go server.StopSubprocess() m.status = hosts.FocusStatusOff + m.minutesLeft = 0 return m }, } @@ -54,3 +56,14 @@ var commandConfigureBlacklist = command{ return m }, } + +var commandFocusOnWithTimer = command{ + Name: "focus on (timer)", + Desc: "Start timed focus window.", + Run: func(m model) model { + m.state = timerView + m.textinput.SetValue("30") + m.textinput.Focus() + return m + }, +} diff --git a/cli/textarea.go b/cli/inputs.go similarity index 84% rename from cli/textarea.go rename to cli/inputs.go index b1aa2ea..31e8f15 100644 --- a/cli/textarea.go +++ b/cli/inputs.go @@ -2,10 +2,11 @@ package cli import ( "github.com/charmbracelet/bubbles/textarea" + "github.com/charmbracelet/bubbles/textinput" "github.com/charmbracelet/lipgloss" ) -func GetTextareModel() textarea.Model { +func GetTextareaModel() textarea.Model { ti := textarea.New() tiFocusedStyle := textarea.Style{ Base: lipgloss.NewStyle(), @@ -33,3 +34,12 @@ func GetTextareModel() textarea.Model { return ti } + +func GetInputModel() textinput.Model { + ti := textinput.New() + ti.CharLimit = 3 + ti.Width = 20 + ti.Blur() + + return ti +} diff --git a/cli/model.go b/cli/model.go index b2d25e2..ae5bfe8 100644 --- a/cli/model.go +++ b/cli/model.go @@ -1,26 +1,41 @@ package cli import ( + "errors" + "strconv" "strings" + "time" "github.com/charmbracelet/bubbles/textarea" + "github.com/charmbracelet/bubbles/textinput" tea "github.com/charmbracelet/bubbletea" "github.com/plutov/ultrafocus/hosts" ) +type TickMsg time.Time + type sessionState uint +func doTick() tea.Cmd { + return tea.Tick(time.Second, func(t time.Time) tea.Msg { + return TickMsg(t) + }) +} + const ( menuView sessionState = iota blacklistView + timerView ) type model struct { textarea textarea.Model + textinput textinput.Model fatalErr error status hosts.FocusStatus domains []string commandsListSelection int + minutesLeft int state sessionState } @@ -32,11 +47,12 @@ func NewModel() model { } return model{ - textarea: GetTextareModel(), - domains: domains, - state: menuView, - status: status, - fatalErr: err, + textarea: GetTextareaModel(), + textinput: GetInputModel(), + domains: domains, + state: menuView, + status: status, + fatalErr: err, } } @@ -45,7 +61,7 @@ func (m model) Init() tea.Cmd { return tea.Quit } - return nil + return doTick() } func (m *model) getCommandsList() []command { @@ -53,7 +69,7 @@ func (m *model) getCommandsList() []command { return []command{commandFocusOff, commandConfigureBlacklist} } - return []command{commandFocusOn, commandConfigureBlacklist} + return []command{commandFocusOn, commandFocusOnWithTimer, commandConfigureBlacklist} } func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { @@ -63,8 +79,20 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.textarea, cmd = m.textarea.Update(msg) cmds = append(cmds, cmd) + m.textinput, cmd = m.textinput.Update(msg) + cmds = append(cmds, cmd) + switch msg := msg.(type) { + case TickMsg: + if m.status == hosts.FocusStatusOn && m.minutesLeft > 0 { + m.minutesLeft-- + if m.minutesLeft == 0 { + m = commandFocusOff.Run(m) + } + } + + return m, doTick() case tea.KeyMsg: commands := m.getCommandsList() switch msg.String() { @@ -103,6 +131,21 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { m.state = menuView m.textarea.Blur() } + if m.state == timerView { + minutesStr := m.textinput.Value() + minutes, err := strconv.Atoi(minutesStr) + if err != nil || minutes <= 0 { + m.fatalErr = errors.New("Invalid number of minutes") + return m, tea.Quit + } + + m = commandFocusOn.Run(m) + + m.minutesLeft = minutes + m.commandsListSelection = 0 + m.state = menuView + m.textinput.Blur() + } } } diff --git a/cli/view.go b/cli/view.go index 6f5dd0f..f5e86aa 100644 --- a/cli/view.go +++ b/cli/view.go @@ -1,8 +1,11 @@ package cli import ( + "fmt" + "github.com/charmbracelet/lipgloss" "github.com/charmbracelet/lipgloss/list" + "github.com/plutov/ultrafocus/hosts" ) var appNameStyle = lipgloss.NewStyle(). @@ -34,13 +37,22 @@ func (m model) View() string { } s := appNameStyle.Render("ultrafocus") + faint.Render(" - Reclaim your time.") + "\n\n" - s += statusStyle.Render("STATUS") + errorInfoStyle.Render(string(m.status)) + "\n\n" + statusMsg := string(m.status) + if m.status == hosts.FocusStatusOn && m.minutesLeft > 0 { + statusMsg += fmt.Sprintf(" (%d mins left)", m.minutesLeft) + } + s += statusStyle.Render("STATUS") + errorInfoStyle.Render(statusMsg) + "\n\n" if m.state == blacklistView { s += "Edit/add domains:\n\n" + m.textarea.View() + "\n\n" s += "press Esc to save.\n" } + if m.state == timerView { + s += "Enter amount of minutes:\n\n" + m.textinput.View() + "\n\n" + s += "press Esc to save.\n" + } + if m.state == menuView { commands := m.getCommandsList()