Skip to content

Commit fe24e04

Browse files
committed
Add timers
1 parent 12fe301 commit fe24e04

File tree

4 files changed

+87
-9
lines changed

4 files changed

+87
-9
lines changed

cli/commands.go

+13
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ var commandFocusOn = command{
2424

2525
go server.StartAsSubprocess()
2626
m.status = hosts.FocusStatusOn
27+
m.minutesLeft = 0
2728
return m
2829
},
2930
}
@@ -39,6 +40,7 @@ var commandFocusOff = command{
3940

4041
go server.StopSubprocess()
4142
m.status = hosts.FocusStatusOff
43+
m.minutesLeft = 0
4244
return m
4345
},
4446
}
@@ -54,3 +56,14 @@ var commandConfigureBlacklist = command{
5456
return m
5557
},
5658
}
59+
60+
var commandFocusOnWithTimer = command{
61+
Name: "focus on (timer)",
62+
Desc: "Start timed focus window.",
63+
Run: func(m model) model {
64+
m.state = timerView
65+
m.textinput.SetValue("30")
66+
m.textinput.Focus()
67+
return m
68+
},
69+
}

cli/textarea.go cli/inputs.go

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,11 @@ package cli
22

33
import (
44
"github.com/charmbracelet/bubbles/textarea"
5+
"github.com/charmbracelet/bubbles/textinput"
56
"github.com/charmbracelet/lipgloss"
67
)
78

8-
func GetTextareModel() textarea.Model {
9+
func GetTextareaModel() textarea.Model {
910
ti := textarea.New()
1011
tiFocusedStyle := textarea.Style{
1112
Base: lipgloss.NewStyle(),
@@ -33,3 +34,12 @@ func GetTextareModel() textarea.Model {
3334

3435
return ti
3536
}
37+
38+
func GetInputModel() textinput.Model {
39+
ti := textinput.New()
40+
ti.CharLimit = 3
41+
ti.Width = 20
42+
ti.Blur()
43+
44+
return ti
45+
}

cli/model.go

+50-7
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,41 @@
11
package cli
22

33
import (
4+
"errors"
5+
"strconv"
46
"strings"
7+
"time"
58

69
"github.com/charmbracelet/bubbles/textarea"
10+
"github.com/charmbracelet/bubbles/textinput"
711
tea "github.com/charmbracelet/bubbletea"
812
"github.com/plutov/ultrafocus/hosts"
913
)
1014

15+
type TickMsg time.Time
16+
1117
type sessionState uint
1218

19+
func doTick() tea.Cmd {
20+
return tea.Tick(time.Second, func(t time.Time) tea.Msg {
21+
return TickMsg(t)
22+
})
23+
}
24+
1325
const (
1426
menuView sessionState = iota
1527
blacklistView
28+
timerView
1629
)
1730

1831
type model struct {
1932
textarea textarea.Model
33+
textinput textinput.Model
2034
fatalErr error
2135
status hosts.FocusStatus
2236
domains []string
2337
commandsListSelection int
38+
minutesLeft int
2439
state sessionState
2540
}
2641

@@ -32,11 +47,12 @@ func NewModel() model {
3247
}
3348

3449
return model{
35-
textarea: GetTextareModel(),
36-
domains: domains,
37-
state: menuView,
38-
status: status,
39-
fatalErr: err,
50+
textarea: GetTextareaModel(),
51+
textinput: GetInputModel(),
52+
domains: domains,
53+
state: menuView,
54+
status: status,
55+
fatalErr: err,
4056
}
4157
}
4258

@@ -45,15 +61,15 @@ func (m model) Init() tea.Cmd {
4561
return tea.Quit
4662
}
4763

48-
return nil
64+
return doTick()
4965
}
5066

5167
func (m *model) getCommandsList() []command {
5268
if m.status == hosts.FocusStatusOn {
5369
return []command{commandFocusOff, commandConfigureBlacklist}
5470
}
5571

56-
return []command{commandFocusOn, commandConfigureBlacklist}
72+
return []command{commandFocusOn, commandFocusOnWithTimer, commandConfigureBlacklist}
5773
}
5874

5975
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) {
6379
m.textarea, cmd = m.textarea.Update(msg)
6480
cmds = append(cmds, cmd)
6581

82+
m.textinput, cmd = m.textinput.Update(msg)
83+
cmds = append(cmds, cmd)
84+
6685
switch msg := msg.(type) {
6786

87+
case TickMsg:
88+
if m.status == hosts.FocusStatusOn && m.minutesLeft > 0 {
89+
m.minutesLeft--
90+
if m.minutesLeft == 0 {
91+
m = commandFocusOff.Run(m)
92+
}
93+
}
94+
95+
return m, doTick()
6896
case tea.KeyMsg:
6997
commands := m.getCommandsList()
7098
switch msg.String() {
@@ -103,6 +131,21 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
103131
m.state = menuView
104132
m.textarea.Blur()
105133
}
134+
if m.state == timerView {
135+
minutesStr := m.textinput.Value()
136+
minutes, err := strconv.Atoi(minutesStr)
137+
if err != nil || minutes <= 0 {
138+
m.fatalErr = errors.New("Invalid number of minutes")
139+
return m, tea.Quit
140+
}
141+
142+
m = commandFocusOn.Run(m)
143+
144+
m.minutesLeft = minutes
145+
m.commandsListSelection = 0
146+
m.state = menuView
147+
m.textinput.Blur()
148+
}
106149
}
107150
}
108151

cli/view.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package cli
22

33
import (
4+
"fmt"
5+
46
"github.com/charmbracelet/lipgloss"
57
"github.com/charmbracelet/lipgloss/list"
8+
"github.com/plutov/ultrafocus/hosts"
69
)
710

811
var appNameStyle = lipgloss.NewStyle().
@@ -34,13 +37,22 @@ func (m model) View() string {
3437
}
3538

3639
s := appNameStyle.Render("ultrafocus") + faint.Render(" - Reclaim your time.") + "\n\n"
37-
s += statusStyle.Render("STATUS") + errorInfoStyle.Render(string(m.status)) + "\n\n"
40+
statusMsg := string(m.status)
41+
if m.status == hosts.FocusStatusOn && m.minutesLeft > 0 {
42+
statusMsg += fmt.Sprintf(" (%d mins left)", m.minutesLeft)
43+
}
44+
s += statusStyle.Render("STATUS") + errorInfoStyle.Render(statusMsg) + "\n\n"
3845

3946
if m.state == blacklistView {
4047
s += "Edit/add domains:\n\n" + m.textarea.View() + "\n\n"
4148
s += "press Esc to save.\n"
4249
}
4350

51+
if m.state == timerView {
52+
s += "Enter amount of minutes:\n\n" + m.textinput.View() + "\n\n"
53+
s += "press Esc to save.\n"
54+
}
55+
4456
if m.state == menuView {
4557
commands := m.getCommandsList()
4658

0 commit comments

Comments
 (0)