diff --git a/cmd/client/helper/terminal.go b/cmd/client/helper/terminal.go deleted file mode 100644 index 49049c2..0000000 --- a/cmd/client/helper/terminal.go +++ /dev/null @@ -1,71 +0,0 @@ -package helper - -import ( - "fmt" - - "github.com/alecthomas/colour" - "github.com/charmbracelet/bubbles/progress" - - GoTomato "git.smsvc.net/pomodoro/GoTomato/pkg/models" -) - -var progressBar = progress.New(progress.WithDefaultGradient(), progress.WithoutPercentage()) - -func calc_percentage(message GoTomato.ServerMessage) float64 { - var duration float64 - - switch message.Mode { - case "Work": - duration = float64(message.Settings.Work) - case "ShortBreak": - duration = float64(message.Settings.ShortBreak) - case "LongBreak", "End": - duration = float64(message.Settings.LongBreak) - } - - timeLeft := float64(message.TimeLeft) - return 1.0 - (timeLeft / duration) -} - -// Return terminal output based on the passed ServerMessage -func TerminalOutput(pomodoro GoTomato.ServerMessage) string { - var ( - output string - - modePrefix string - timerOutput string - ) - - // header - output += colour.Sprintf("^D^4Work: %d ◊ Break: %d ◊ Longbreak: %d^R\n\n", - pomodoro.Settings.Work/60, - pomodoro.Settings.ShortBreak/60, - pomodoro.Settings.LongBreak/60, - ) - - //body - switch pomodoro.Mode { - case "Idle": - modePrefix = " " - timerOutput = "" - default: - modePrefix = " " - if pomodoro.Paused { - modePrefix = " " - } - minutes := pomodoro.TimeLeft / 60 - seconds := pomodoro.TimeLeft % 60 - - timerOutput = fmt.Sprintf("⏳ %02d:%02d", minutes, seconds) + "\n" - timerOutput += progressBar.ViewAs(calc_percentage(pomodoro)) - } - - output += fmt.Sprintf("Session: %d/%d\n", - pomodoro.Session, - pomodoro.Settings.Sessions, - ) - output += fmt.Sprintf("%s %s\n", modePrefix, pomodoro.Mode) + "\n" - output += timerOutput - - return output -} diff --git a/cmd/client/helper/notification.go b/cmd/client/notification.go similarity index 93% rename from cmd/client/helper/notification.go rename to cmd/client/notification.go index 956e6a2..7e5dfd6 100644 --- a/cmd/client/helper/notification.go +++ b/cmd/client/notification.go @@ -1,4 +1,4 @@ -package helper +package client import ( "fmt" @@ -8,7 +8,7 @@ import ( ) // Send desktop notifications on the start of each segment -func DesktopNotifications(pomodoro GoTomato.ServerMessage) { +func desktopNotifications(pomodoro GoTomato.ServerMessage) { var ( duration int notification string diff --git a/cmd/client/view.go b/cmd/client/view.go index c7e9eb7..0e7d9b9 100644 --- a/cmd/client/view.go +++ b/cmd/client/view.go @@ -1,26 +1,29 @@ package client import ( + "fmt" "strings" "github.com/alecthomas/colour" - "git.smsvc.net/pomodoro/ChronoTomato/cmd/client/helper" GoTomato "git.smsvc.net/pomodoro/GoTomato/pkg/models" + "github.com/charmbracelet/bubbles/progress" ) +var progressBar = progress.New(progress.WithDefaultGradient(), progress.WithoutPercentage()) + func (a app) View() string { var body string var serverStatus string body = "Waiting for server message..." if a.pomodoro != (GoTomato.ServerMessage{}) { - body = helper.TerminalOutput(a.pomodoro) - helper.DesktopNotifications(a.pomodoro) + body = terminalOutput(a.pomodoro) + desktopNotifications(a.pomodoro) } - serverStatus = colour.Sprintf("^D^1disconnected: %v^R\n", client.LastErr) - if client.Connected() { + serverStatus = colour.Sprintf("^D^1%v^R\n", client.LastErr) + if client.Connected() && client.LastErr == nil { serverStatus = colour.Sprintf("^D^2connected to %s^R\n", client.Server) } @@ -29,3 +32,62 @@ func (a app) View() string { return body + strings.Repeat("\n", height) + serverStatus + helpView } + +// Return terminal output based on the passed ServerMessage +func terminalOutput(pomodoro GoTomato.ServerMessage) string { + var ( + output string + + modePrefix string + timerOutput string + ) + + // header + output += colour.Sprintf("^D^4Work: %d ◊ Break: %d ◊ Longbreak: %d^R\n\n", + pomodoro.Settings.Work/60, + pomodoro.Settings.ShortBreak/60, + pomodoro.Settings.LongBreak/60, + ) + + //body + switch pomodoro.Mode { + case "Idle": + modePrefix = " " + timerOutput = "" + default: + modePrefix = " " + if pomodoro.Paused { + modePrefix = " " + } + minutes := pomodoro.TimeLeft / 60 + seconds := pomodoro.TimeLeft % 60 + + timerOutput = fmt.Sprintf("⏱ %02d:%02d", minutes, seconds) + "\n" + timerOutput += progressBar.ViewAs(calc_percentage(pomodoro)) + } + + output += fmt.Sprintf("Session: %d/%d\n", + pomodoro.Session, + pomodoro.Settings.Sessions, + ) + output += fmt.Sprintf("%s %s\n", modePrefix, pomodoro.Mode) + "\n" + output += timerOutput + + return output +} + +func calc_percentage(message GoTomato.ServerMessage) float64 { + var duration float64 + + switch message.Mode { + case "Work": + duration = float64(message.Settings.Work) + case "ShortBreak": + duration = float64(message.Settings.ShortBreak) + case "LongBreak", "End": + duration = float64(message.Settings.LongBreak) + } + + timeLeft := float64(message.TimeLeft) + return 1.0 - (timeLeft / duration) +} diff --git a/go.mod b/go.mod index da5bc03..a17e81c 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( git.smsvc.net/pomodoro/GoTomato v0.3.1 github.com/alecthomas/colour v0.1.0 github.com/charmbracelet/bubbles v0.20.0 - github.com/charmbracelet/bubbletea v1.2.1 + github.com/charmbracelet/bubbletea v1.2.2 github.com/charmbracelet/log v0.4.0 github.com/gen2brain/beeep v0.0.0-20240516210008-9c006672e7f4 github.com/gorilla/websocket v1.5.3 @@ -18,7 +18,7 @@ require ( github.com/charmbracelet/harmonica v0.2.0 // indirect github.com/charmbracelet/lipgloss v1.0.0 // indirect github.com/charmbracelet/x/ansi v0.4.5 // indirect - github.com/charmbracelet/x/term v0.2.0 // indirect + github.com/charmbracelet/x/term v0.2.1 // indirect github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-toast/toast v0.0.0-20190211030409-01e6764cf0a4 // indirect @@ -35,8 +35,8 @@ require ( github.com/rivo/uniseg v0.4.7 // indirect github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af // indirect golang.org/x/exp v0.0.0-20231006140011-7918f672742d // indirect - golang.org/x/sync v0.8.0 // indirect - golang.org/x/sys v0.26.0 // indirect + golang.org/x/sync v0.9.0 // indirect + golang.org/x/sys v0.27.0 // indirect golang.org/x/text v0.3.8 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) diff --git a/go.sum b/go.sum index 4f15eb3..f34a319 100644 --- a/go.sum +++ b/go.sum @@ -6,8 +6,8 @@ github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiE github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= github.com/charmbracelet/bubbles v0.20.0 h1:jSZu6qD8cRQ6k9OMfR1WlM+ruM8fkPWkHvQWD9LIutE= github.com/charmbracelet/bubbles v0.20.0/go.mod h1:39slydyswPy+uVOHZ5x/GjwVAFkCsV8IIVy+4MhzwwU= -github.com/charmbracelet/bubbletea v1.2.1 h1:J041h57zculJKEKf/O2pS4edXGIz+V0YvojvfGXePIk= -github.com/charmbracelet/bubbletea v1.2.1/go.mod h1:viLoDL7hG4njLJSKU2gw7kB3LSEmWsrM80rO1dBJWBI= +github.com/charmbracelet/bubbletea v1.2.2 h1:EMz//Ky/aFS2uLcKqpCst5UOE6z5CFDGRsUpyXz0chs= +github.com/charmbracelet/bubbletea v1.2.2/go.mod h1:Qr6fVQw+wX7JkWWkVyXYk/ZUQ92a6XNekLXa3rR18MM= github.com/charmbracelet/harmonica v0.2.0 h1:8NxJWRWg/bzKqqEaaeFNipOu77YR5t8aSwG4pgaUBiQ= github.com/charmbracelet/harmonica v0.2.0/go.mod h1:KSri/1RMQOZLbw7AHqgcBycp8pgJnQMYYT8QZRqZ1Ao= github.com/charmbracelet/lipgloss v1.0.0 h1:O7VkGDvqEdGi93X+DeqsQ7PKHDgtQfF8j8/O2qFMQNg= @@ -16,8 +16,8 @@ github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8 github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM= github.com/charmbracelet/x/ansi v0.4.5 h1:LqK4vwBNaXw2AyGIICa5/29Sbdq58GbGdFngSexTdRM= github.com/charmbracelet/x/ansi v0.4.5/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= -github.com/charmbracelet/x/term v0.2.0 h1:cNB9Ot9q8I711MyZ7myUR5HFWL/lc3OpU8jZ4hwm0x0= -github.com/charmbracelet/x/term v0.2.0/go.mod h1:GVxgxAbjUrmpvIINHIQnJJKpMlHiZ4cktEQCN6GWyF0= +github.com/charmbracelet/x/term v0.2.1 h1:AQeHeLZ1OqSXhrAWpYUtZyX1T3zVxfpZuEQMIQaGIAQ= +github.com/charmbracelet/x/term v0.2.1/go.mod h1:oQ4enTYFV7QN4m0i9mzHrViD7TQKvNEEkHUMCmsxdUg= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= @@ -64,12 +64,12 @@ github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af h1:6yITBqGTE2lEeTPG0 github.com/tadvi/systray v0.0.0-20190226123456-11a2b8fa57af/go.mod h1:4F09kP5F+am0jAwlQLddpoMDM+iewkxxt6nxUQ5nq5o= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY= golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/websocket/receive.go b/internal/websocket/receive.go index e4638a6..7912de3 100644 --- a/internal/websocket/receive.go +++ b/internal/websocket/receive.go @@ -19,6 +19,7 @@ func (c *Client) ProcessServerMessages(channel chan<- GoTomato.ServerMessage) { defer close(Done) for { + c.Conn.SetReadDeadline(time.Now().Add(10 * time.Second)) _, message, err := c.Conn.ReadMessage() if err != nil { // On normal closure exit gracefully @@ -26,6 +27,7 @@ func (c *Client) ProcessServerMessages(channel chan<- GoTomato.ServerMessage) { return } + c.LastErr = err // Try to reconnect on unexpected disconnect for { channel <- prevMessage // send previous ServerMessage to update view