From f0d7dc80fc37510c053ee831cf756ce1404a52b3 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sun, 27 Oct 2024 22:46:58 +0100
Subject: [PATCH 01/44] feat: update protocol version handling
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- add ProtocolVersion variable to metadata package
- don't set `ServerMessage.ProtocolVersion` in `main`
- update `ServerMessage` default to include ProtocolVersion
🤖
---
cmd/server/main.go | 4 +---
internal/metadata/version.go | 3 +++
internal/shared/state.go | 14 ++++++++------
3 files changed, 12 insertions(+), 9 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 5d0b3a0..9f9db88 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -10,7 +10,6 @@ import (
"github.com/charmbracelet/log"
"net/http"
"os"
- "strings"
)
func Start() {
@@ -21,10 +20,9 @@ func Start() {
showVersionFlag := flag.Bool("version", false, "Output version")
flag.Parse()
- shared.Message.ProtocolVersion = strings.Split(metadata.GoTomatoVersion, ".")[0]
if *showVersionFlag {
fmt.Printf("App-Version: %s\n", metadata.GoTomatoVersion)
- fmt.Printf("Protocol-Version: %s\n", shared.Message.ProtocolVersion)
+ fmt.Printf("Protocol-Version: %s\n", metadata.ProtocolVersion)
os.Exit(0)
}
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index d06d970..f1c52e1 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -1,3 +1,6 @@
package metadata
+import "strings"
+
const GoTomatoVersion = "v0.0.4" // The GoTomato Version
+var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0]
diff --git a/internal/shared/state.go b/internal/shared/state.go
index 1f8c670..a9eac1b 100644
--- a/internal/shared/state.go
+++ b/internal/shared/state.go
@@ -1,16 +1,18 @@
package shared
import (
+ "git.smsvc.net/pomodoro/GoTomato/internal/metadata"
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
var Message = models.ServerMessage{
- Mode: "Idle",
- Settings: DefaultPomodoroConfig,
- Session: 0,
- TimeLeft: DefaultPomodoroConfig.Work,
- Ongoing: false,
- Paused: false,
+ Mode: "Idle",
+ Settings: DefaultPomodoroConfig,
+ Session: 0,
+ TimeLeft: DefaultPomodoroConfig.Work,
+ Ongoing: false,
+ Paused: false,
+ ProtocolVersion: metadata.ProtocolVersion,
}
var PomodoroPassword string
From 3a6be4c1870fdefc783e4dbbe94ff856f73df95e Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 28 Oct 2024 09:30:00 +0100
Subject: [PATCH 02/44] feat: update settings handling for pomodoro
configuration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- add `UpdateSettings()` to update pomodoro configuration
- refactor client command handling to use `UpdateSettings()`
🤖
---
internal/pomodoro/pomodoro.go | 8 ++++++++
internal/websocket/client_commands.go | 6 +-----
2 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/internal/pomodoro/pomodoro.go b/internal/pomodoro/pomodoro.go
index be39e6e..c24d4a5 100644
--- a/internal/pomodoro/pomodoro.go
+++ b/internal/pomodoro/pomodoro.go
@@ -2,6 +2,7 @@ package pomodoro
import (
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
+ "git.smsvc.net/pomodoro/GoTomato/pkg/models"
"sync"
"time"
)
@@ -99,3 +100,10 @@ func IsPomodoroPaused() bool {
defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
return shared.Message.Paused
}
+
+func UpdateSettings(settings models.PomodoroConfig) {
+ if settings != (models.PomodoroConfig{}) {
+ shared.Message.Settings = settings
+ shared.Message.TimeLeft = settings.Work
+ }
+}
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index cafcd67..c1f323f 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -49,11 +49,7 @@ func handleClientCommands(ws *websocket.Conn) {
}
case "updateSettings":
if !pomodoro.IsPomodoroOngoing() {
- if clientCommand.Settings != (models.PomodoroConfig{}) {
- shared.Message.Settings = clientCommand.Settings
- shared.Message.TimeLeft = clientCommand.Settings.Work
- }
-
+ pomodoro.UpdateSettings(clientCommand.Settings)
}
}
}
From e2ab19066d563d0398f2159e5159caf64b5f8f9f Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 28 Oct 2024 09:33:05 +0100
Subject: [PATCH 03/44] format: update import statements order for consistency
---
cmd/server/main.go | 7 ++++---
internal/pomodoro/pomodoro.go | 5 +++--
internal/pomodoro/timer.go | 4 +---
internal/shared/configDefaults.go | 4 +---
internal/websocket/broadcast.go | 3 ++-
internal/websocket/client_commands.go | 5 +++--
internal/websocket/handle_connections.go | 3 ++-
7 files changed, 16 insertions(+), 15 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 9f9db88..67fba91 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -3,13 +3,14 @@ package server
import (
"flag"
"fmt"
+ "github.com/charmbracelet/log"
+ "net/http"
+ "os"
+
"git.smsvc.net/pomodoro/GoTomato/internal/metadata"
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
"git.smsvc.net/pomodoro/GoTomato/internal/websocket"
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
- "github.com/charmbracelet/log"
- "net/http"
- "os"
)
func Start() {
diff --git a/internal/pomodoro/pomodoro.go b/internal/pomodoro/pomodoro.go
index c24d4a5..6b83842 100644
--- a/internal/pomodoro/pomodoro.go
+++ b/internal/pomodoro/pomodoro.go
@@ -1,10 +1,11 @@
package pomodoro
import (
- "git.smsvc.net/pomodoro/GoTomato/internal/shared"
- "git.smsvc.net/pomodoro/GoTomato/pkg/models"
"sync"
"time"
+
+ "git.smsvc.net/pomodoro/GoTomato/internal/shared"
+ "git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
var mu sync.Mutex // to synchronize access to shared state
diff --git a/internal/pomodoro/timer.go b/internal/pomodoro/timer.go
index 55cb654..c80f288 100644
--- a/internal/pomodoro/timer.go
+++ b/internal/pomodoro/timer.go
@@ -1,8 +1,6 @@
package pomodoro
-import (
- "time"
-)
+import "time"
type Timer struct {
TimeLeft chan int // time left
diff --git a/internal/shared/configDefaults.go b/internal/shared/configDefaults.go
index a3840e0..9366889 100644
--- a/internal/shared/configDefaults.go
+++ b/internal/shared/configDefaults.go
@@ -1,8 +1,6 @@
package shared
-import (
- "git.smsvc.net/pomodoro/GoTomato/pkg/models"
-)
+import "git.smsvc.net/pomodoro/GoTomato/pkg/models"
var DefaultServerConfig = models.ServerConfig{
ListenAddress: "0.0.0.0",
diff --git a/internal/websocket/broadcast.go b/internal/websocket/broadcast.go
index 99827e7..64b8fb4 100644
--- a/internal/websocket/broadcast.go
+++ b/internal/websocket/broadcast.go
@@ -2,10 +2,11 @@ package websocket
import (
"encoding/json"
- "git.smsvc.net/pomodoro/GoTomato/internal/shared"
"github.com/charmbracelet/log"
"github.com/gorilla/websocket"
"time"
+
+ "git.smsvc.net/pomodoro/GoTomato/internal/shared"
)
// sends continous messages to all connected WebSocket clients.
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index c1f323f..472484f 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -2,11 +2,12 @@ package websocket
import (
"encoding/json"
+ "github.com/charmbracelet/log"
+ "github.com/gorilla/websocket"
+
"git.smsvc.net/pomodoro/GoTomato/internal/pomodoro"
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
- "github.com/charmbracelet/log"
- "github.com/gorilla/websocket"
)
// handleClientCommands listens for commands from WebSocket clients
diff --git a/internal/websocket/handle_connections.go b/internal/websocket/handle_connections.go
index 687f472..4b5f1b1 100644
--- a/internal/websocket/handle_connections.go
+++ b/internal/websocket/handle_connections.go
@@ -1,11 +1,12 @@
package websocket
import (
- "git.smsvc.net/pomodoro/GoTomato/pkg/models"
"github.com/charmbracelet/log"
"github.com/gorilla/websocket"
"net/http"
"sync"
+
+ "git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
// Clients is a map of connected WebSocket clients, where each client is represented by the Client struct
From d69a4bec1040cf298c75967f4d329a5411077fad Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 28 Oct 2024 09:34:12 +0100
Subject: [PATCH 04/44] format: use group style variable declaration to define
cli flags
---
cmd/server/main.go | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 67fba91..bb2eb2f 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -13,12 +13,15 @@ import (
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
+var (
+ // Define CLI flags
+ listenAddress = flag.String("listenAddress", shared.DefaultServerConfig.ListenAddress, "IP address to listen on")
+ listenPort = flag.Int("listenPort", shared.DefaultServerConfig.ListenPort, "Port to listen on")
+ password = flag.String("password", "", "Control password for pomodoro session (optional)")
+ showVersionFlag = flag.Bool("version", false, "Output version")
+)
+
func Start() {
- // Define CLI flags for ListenAddress and ListenPort
- listenAddress := flag.String("listenAddress", shared.DefaultServerConfig.ListenAddress, "IP address to listen on")
- listenPort := flag.Int("listenPort", shared.DefaultServerConfig.ListenPort, "Port to listen on")
- password := flag.String("password", "", "Control password for pomodoro session (optional)")
- showVersionFlag := flag.Bool("version", false, "Output version")
flag.Parse()
if *showVersionFlag {
From 5750ec96cb47593bedea3435f19e089d3662cedc Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 28 Oct 2024 10:41:20 +0100
Subject: [PATCH 05/44] refactor: update version output
- use `Println` for better readability
---
cmd/server/main.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index bb2eb2f..ebcee49 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -25,8 +25,8 @@ func Start() {
flag.Parse()
if *showVersionFlag {
- fmt.Printf("App-Version: %s\n", metadata.GoTomatoVersion)
- fmt.Printf("Protocol-Version: %s\n", metadata.ProtocolVersion)
+ fmt.Println("App-Version:", metadata.GoTomatoVersion)
+ fmt.Println("Protocol-Version:", metadata.ProtocolVersion)
os.Exit(0)
}
From b8823acc97c6a48ff9a21818a6718ce04423158c Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Tue, 29 Oct 2024 18:46:00 +0100
Subject: [PATCH 06/44] refacor: replace shared.Message with shared.State
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
🤖
---
internal/pomodoro/pomodoro.go | 40 ++++++++++++++++-----------------
internal/shared/state.go | 2 +-
internal/websocket/broadcast.go | 2 +-
3 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/internal/pomodoro/pomodoro.go b/internal/pomodoro/pomodoro.go
index 6b83842..9eeb04c 100644
--- a/internal/pomodoro/pomodoro.go
+++ b/internal/pomodoro/pomodoro.go
@@ -18,7 +18,7 @@ func waitForTimer(t Timer) bool {
return true
case <-t.Abort:
return false
- case shared.Message.TimeLeft = <-t.TimeLeft:
+ case shared.State.TimeLeft = <-t.TimeLeft:
// do nothing, just let the timer update the message
}
}
@@ -27,48 +27,48 @@ func waitForTimer(t Timer) bool {
// RunPomodoro iterates the Pomodoro work/break sessions.
func RunPomodoro() {
mu.Lock()
- shared.Message.Ongoing = true
- shared.Message.Paused = false
+ shared.State.Ongoing = true
+ shared.State.Paused = false
mu.Unlock()
- pomodoroConfig := shared.Message.Settings
+ pomodoroConfig := shared.State.Settings
for session := 1; session <= pomodoroConfig.Sessions; session++ {
timer = timer.Init()
- shared.Message.Session = session
+ shared.State.Session = session
- shared.Message.Mode = "Work"
+ shared.State.Mode = "Work"
go timer.Start(pomodoroConfig.Work)
if !waitForTimer(timer) {
break
}
if session < pomodoroConfig.Sessions {
- shared.Message.Mode = "ShortBreak"
+ shared.State.Mode = "ShortBreak"
go timer.Start(pomodoroConfig.ShortBreak)
if !waitForTimer(timer) {
break
}
} else { // last phase, prepare for finish
- shared.Message.Mode = "LongBreak"
+ shared.State.Mode = "LongBreak"
go timer.Start(pomodoroConfig.LongBreak)
if !waitForTimer(timer) {
break
}
- shared.Message.Mode = "End"
+ shared.State.Mode = "End"
time.Sleep(time.Second)
}
}
mu.Lock()
- shared.Message.Ongoing = false
- shared.Message.Paused = false
+ shared.State.Ongoing = false
+ shared.State.Paused = false
mu.Unlock()
- shared.Message.Mode = "Idle"
- shared.Message.Session = 0
- shared.Message.TimeLeft = shared.Message.Settings.Work
+ shared.State.Mode = "Idle"
+ shared.State.Session = 0
+ shared.State.TimeLeft = shared.State.Settings.Work
}
func ResetPomodoro() {
@@ -77,7 +77,7 @@ func ResetPomodoro() {
func PausePomodoro() {
mu.Lock()
- shared.Message.Paused = true
+ shared.State.Paused = true
mu.Unlock()
timer.Pause()
@@ -85,7 +85,7 @@ func PausePomodoro() {
func ResumePomodoro() {
mu.Lock()
- shared.Message.Paused = false
+ shared.State.Paused = false
mu.Unlock()
timer.Resume()
}
@@ -93,18 +93,18 @@ func ResumePomodoro() {
func IsPomodoroOngoing() bool {
mu.Lock()
defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
- return shared.Message.Ongoing
+ return shared.State.Ongoing
}
func IsPomodoroPaused() bool {
mu.Lock()
defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
- return shared.Message.Paused
+ return shared.State.Paused
}
func UpdateSettings(settings models.PomodoroConfig) {
if settings != (models.PomodoroConfig{}) {
- shared.Message.Settings = settings
- shared.Message.TimeLeft = settings.Work
+ shared.State.Settings = settings
+ shared.State.TimeLeft = settings.Work
}
}
diff --git a/internal/shared/state.go b/internal/shared/state.go
index a9eac1b..a6e1829 100644
--- a/internal/shared/state.go
+++ b/internal/shared/state.go
@@ -5,7 +5,7 @@ import (
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
-var Message = models.ServerMessage{
+var State = models.ServerMessage{
Mode: "Idle",
Settings: DefaultPomodoroConfig,
Session: 0,
diff --git a/internal/websocket/broadcast.go b/internal/websocket/broadcast.go
index 64b8fb4..d0e5f67 100644
--- a/internal/websocket/broadcast.go
+++ b/internal/websocket/broadcast.go
@@ -14,7 +14,7 @@ func SendPermanentBroadCastMessage() {
tick := time.NewTicker(time.Second)
for {
// Marshal the message into JSON format
- jsonMessage, err := json.Marshal(shared.Message)
+ jsonMessage, err := json.Marshal(shared.State)
if err != nil {
log.Error("Error marshalling message:", "msg", err)
return
From d83acc77b2be6fc01ed3b304177f2d98b7e7323d Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Tue, 29 Oct 2024 18:49:00 +0100
Subject: [PATCH 07/44] refactor: rename HandleConnections to HandleConnection
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- rename function to better reflect its purpose
🤖
---
cmd/server/main.go | 2 +-
.../websocket/{handle_connections.go => handle_connection.go} | 4 ++--
2 files changed, 3 insertions(+), 3 deletions(-)
rename internal/websocket/{handle_connections.go => handle_connection.go} (86%)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index ebcee49..e97a17d 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -38,7 +38,7 @@ func Start() {
listen := fmt.Sprintf("%s:%d", serverConfig.ListenAddress, serverConfig.ListenPort)
- http.HandleFunc("/ws", websocket.HandleConnections)
+ http.HandleFunc("/ws", websocket.HandleConnection)
go websocket.SendPermanentBroadCastMessage()
log.Info("GoTomato started", "version", metadata.GoTomatoVersion)
diff --git a/internal/websocket/handle_connections.go b/internal/websocket/handle_connection.go
similarity index 86%
rename from internal/websocket/handle_connections.go
rename to internal/websocket/handle_connection.go
index 4b5f1b1..707bea8 100644
--- a/internal/websocket/handle_connections.go
+++ b/internal/websocket/handle_connection.go
@@ -18,8 +18,8 @@ var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
-// HandleConnections upgrades HTTP requests to WebSocket connections and manages the client lifecycle.
-func HandleConnections(w http.ResponseWriter, r *http.Request) {
+// HandleConnection upgrades HTTP requests to WebSocket connections and manages the client lifecycle.
+func HandleConnection(w http.ResponseWriter, r *http.Request) {
// Upgrade initial GET request to a WebSocket
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
From d0b1260f6243a6b63ca26a025073b52aac920401 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 07:37:14 +0100
Subject: [PATCH 08/44] doc: add and improve comments
---
cmd/server/main.go | 11 +++++++++--
internal/metadata/version.go | 4 ++--
internal/pomodoro/pomodoro.go | 12 +++++++++---
internal/pomodoro/timer.go | 11 +++++++----
internal/shared/configDefaults.go | 2 ++
internal/shared/state.go | 2 ++
internal/websocket/broadcast.go | 2 +-
internal/websocket/client_commands.go | 2 +-
internal/websocket/handle_connection.go | 4 ++--
pkg/models/client.go | 16 +++++++++-------
pkg/models/config.go | 4 +++-
pkg/models/server.go | 6 +++---
12 files changed, 50 insertions(+), 26 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index e97a17d..126ec2f 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -14,35 +14,42 @@ import (
)
var (
- // Define CLI flags
+ // define CLI flags
listenAddress = flag.String("listenAddress", shared.DefaultServerConfig.ListenAddress, "IP address to listen on")
listenPort = flag.Int("listenPort", shared.DefaultServerConfig.ListenPort, "Port to listen on")
password = flag.String("password", "", "Control password for pomodoro session (optional)")
showVersionFlag = flag.Bool("version", false, "Output version")
)
+// Start the pomodoro server
func Start() {
flag.Parse()
+ // show server and protocl version and exit
if *showVersionFlag {
- fmt.Println("App-Version:", metadata.GoTomatoVersion)
+ fmt.Println("Server-Version:", metadata.GoTomatoVersion)
fmt.Println("Protocol-Version:", metadata.ProtocolVersion)
os.Exit(0)
}
+ // set server config
serverConfig := models.ServerConfig{
ListenAddress: *listenAddress,
ListenPort: *listenPort,
}
shared.PomodoroPassword = *password
+ // define listen address for websocket
listen := fmt.Sprintf("%s:%d", serverConfig.ListenAddress, serverConfig.ListenPort)
+ // start connection handler and broadcast
http.HandleFunc("/ws", websocket.HandleConnection)
go websocket.SendPermanentBroadCastMessage()
log.Info("GoTomato started", "version", metadata.GoTomatoVersion)
log.Info("Websocket listening", "address", listen)
+
+ // start the listener
err := http.ListenAndServe(listen, nil)
if err != nil {
log.Fatal("Error starting server:", "msg", err)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index f1c52e1..9463896 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "v0.0.4" // The GoTomato Version
-var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0]
+const GoTomatoVersion = "v0.0.4" // The GoTomato version
+var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
diff --git a/internal/pomodoro/pomodoro.go b/internal/pomodoro/pomodoro.go
index 9eeb04c..8228249 100644
--- a/internal/pomodoro/pomodoro.go
+++ b/internal/pomodoro/pomodoro.go
@@ -11,6 +11,8 @@ import (
var mu sync.Mutex // to synchronize access to shared state
var timer Timer
+// Update `State` with the remaining seconds of the passed timer
+// until the timer sends an End or Abort signal
func waitForTimer(t Timer) bool {
for {
select {
@@ -24,7 +26,7 @@ func waitForTimer(t Timer) bool {
}
}
-// RunPomodoro iterates the Pomodoro work/break sessions.
+// RunPomodoro iterates the Pomodoro work/break sessions
func RunPomodoro() {
mu.Lock()
shared.State.Ongoing = true
@@ -38,12 +40,14 @@ func RunPomodoro() {
shared.State.Session = session
+ // Work
shared.State.Mode = "Work"
go timer.Start(pomodoroConfig.Work)
if !waitForTimer(timer) {
break
}
+ // Breaks
if session < pomodoroConfig.Sessions {
shared.State.Mode = "ShortBreak"
go timer.Start(pomodoroConfig.ShortBreak)
@@ -56,6 +60,8 @@ func RunPomodoro() {
if !waitForTimer(timer) {
break
}
+
+ // send "End" state for one second
shared.State.Mode = "End"
time.Sleep(time.Second)
}
@@ -92,13 +98,13 @@ func ResumePomodoro() {
func IsPomodoroOngoing() bool {
mu.Lock()
- defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
+ defer mu.Unlock()
return shared.State.Ongoing
}
func IsPomodoroPaused() bool {
mu.Lock()
- defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
+ defer mu.Unlock()
return shared.State.Paused
}
diff --git a/internal/pomodoro/timer.go b/internal/pomodoro/timer.go
index c80f288..09a50ee 100644
--- a/internal/pomodoro/timer.go
+++ b/internal/pomodoro/timer.go
@@ -2,15 +2,17 @@ package pomodoro
import "time"
+// Represents a timer
type Timer struct {
- TimeLeft chan int // time left
+ TimeLeft chan int // signals time left on every second
End chan bool // signal on successful end
Abort chan bool // signal on premature end
- stop chan bool
- wait chan bool
- resume chan bool
+ stop chan bool // internal channel
+ wait chan bool // internal channel
+ resume chan bool // internal channel
}
+// Initializes a new timer with fresh channels
func (t Timer) Init() Timer {
return Timer{
TimeLeft: make(chan int),
@@ -22,6 +24,7 @@ func (t Timer) Init() Timer {
}
}
+// Start the timer
func (t *Timer) Start(duration int) {
tick := time.NewTicker(time.Second)
for timeLeft := duration; timeLeft > 0; {
diff --git a/internal/shared/configDefaults.go b/internal/shared/configDefaults.go
index 9366889..e125da8 100644
--- a/internal/shared/configDefaults.go
+++ b/internal/shared/configDefaults.go
@@ -2,11 +2,13 @@ package shared
import "git.smsvc.net/pomodoro/GoTomato/pkg/models"
+// The default server config if nothing else is set
var DefaultServerConfig = models.ServerConfig{
ListenAddress: "0.0.0.0",
ListenPort: 8080,
}
+// The default pomodoro config if nothing else is set
var DefaultPomodoroConfig = models.PomodoroConfig{
Work: 25 * 60,
ShortBreak: 5 * 60,
diff --git a/internal/shared/state.go b/internal/shared/state.go
index a6e1829..e21d4d3 100644
--- a/internal/shared/state.go
+++ b/internal/shared/state.go
@@ -5,6 +5,7 @@ import (
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
+// The global state of the pomodoro
var State = models.ServerMessage{
Mode: "Idle",
Settings: DefaultPomodoroConfig,
@@ -15,4 +16,5 @@ var State = models.ServerMessage{
ProtocolVersion: metadata.ProtocolVersion,
}
+// The password needed to execute client commands or change the pomodoro config
var PomodoroPassword string
diff --git a/internal/websocket/broadcast.go b/internal/websocket/broadcast.go
index d0e5f67..14254c0 100644
--- a/internal/websocket/broadcast.go
+++ b/internal/websocket/broadcast.go
@@ -9,7 +9,7 @@ import (
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
)
-// sends continous messages to all connected WebSocket clients.
+// Sends continous messages to all connected WebSocket clients
func SendPermanentBroadCastMessage() {
tick := time.NewTicker(time.Second)
for {
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index 472484f..53464dd 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -10,7 +10,7 @@ import (
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
-// handleClientCommands listens for commands from WebSocket clients
+// Listens for commands from a client and handles them
func handleClientCommands(ws *websocket.Conn) {
for {
var clientCommand models.ClientCommand
diff --git a/internal/websocket/handle_connection.go b/internal/websocket/handle_connection.go
index 707bea8..5e97df2 100644
--- a/internal/websocket/handle_connection.go
+++ b/internal/websocket/handle_connection.go
@@ -13,12 +13,12 @@ import (
var Clients = make(map[*websocket.Conn]*models.Client)
var mu sync.Mutex // Mutex to protect access to the Clients map
-// Upgrader to upgrade HTTP requests to WebSocket connections
+// Upgrade HTTP requests to WebSocket connections
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool { return true },
}
-// HandleConnection upgrades HTTP requests to WebSocket connections and manages the client lifecycle.
+// Upgrades HTTP requests to WebSocket connections and manages the client lifecycle
func HandleConnection(w http.ResponseWriter, r *http.Request) {
// Upgrade initial GET request to a WebSocket
ws, err := upgrader.Upgrade(w, r, nil)
diff --git a/pkg/models/client.go b/pkg/models/client.go
index 8116d8b..7a6ae21 100644
--- a/pkg/models/client.go
+++ b/pkg/models/client.go
@@ -6,19 +6,21 @@ import (
"sync"
)
-// ClientCommand represents a command from the client (start/stop).
+// Represents a command from the client (start/stop)
type ClientCommand struct {
- Command string `json:"command"` // comman send to the server
- Password string `json:"password"` // pomodoro control password
- Settings PomodoroConfig `json:"settings"` // pomodoro config
+ Command string `json:"command"` // Command send to the server
+ Password string `json:"password"` // Pomodoro control password
+ Settings PomodoroConfig `json:"settings"` // Pomodoro config
}
+// Represents a single client
type Client struct {
- Conn *websocket.Conn
- Mutex sync.Mutex
+ Conn *websocket.Conn // Websocket connection of the client
+ Mutex sync.Mutex // Mutex used to lock
}
-// It automatically locks and unlocks the mutex to ensure that only one goroutine can write at a time.
+// Sends a message to the websocket.
+// Automatically locks and unlocks the client mutex, to ensure that only one goroutine can write at a time.
func (c *Client) SendMessage(messageType int, data []byte) error {
c.Mutex.Lock()
defer c.Mutex.Unlock()
diff --git a/pkg/models/config.go b/pkg/models/config.go
index 50c7923..36b9dbb 100644
--- a/pkg/models/config.go
+++ b/pkg/models/config.go
@@ -1,12 +1,14 @@
package models
+// Represents the configuration of a pomodoro
type PomodoroConfig struct {
Work int `json:"work"` // Length of work sessions in seconds
ShortBreak int `json:"shortBreak"` // Length of short break in seconds
- LongBreak int `json:"longBreak"` // Length if ling break in seconds
+ LongBreak int `json:"longBreak"` // Length of long break in seconds
Sessions int `json:"sessions"` // Number of total sessions
}
+// Represents the server configuration
type ServerConfig struct {
ListenAddress string `json:"listenAddress"` // Server listen address
ListenPort int `json:"listenPort"` // Server listen port
diff --git a/pkg/models/server.go b/pkg/models/server.go
index 092c557..6aa914a 100644
--- a/pkg/models/server.go
+++ b/pkg/models/server.go
@@ -1,12 +1,12 @@
package models
-// ServerMessage represents the data sent to the client via WebSocket.
+// Represents the data sent to the client via WebSocket
type ServerMessage struct {
Mode string `json:"mode"` // "Idle", "Work", "ShortBreak", "LongBreak" or "End"
Settings PomodoroConfig `json:"settings"` // The currrent pomodoro settings
Session int `json:"session"` // Current session number
TimeLeft int `json:"time_left"` // Remaining time in seconds
- Ongoing bool `json:"ongoing"` // Ongoing pomodoro
+ Ongoing bool `json:"ongoing"` // Pomodoro ongoing
Paused bool `json:"paused"` // Is timer paused
- ProtocolVersion string `json:"version"` // Version of the server
+ ProtocolVersion string `json:"version"` // Version of the protocol
}
From 94b6786c7c8339def1bcee07c243ef066c90b74c Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 07:46:29 +0100
Subject: [PATCH 09/44] feat: implement asynchronous timer start
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- add new StartAsync method to Timer for non-blocking execution
- use new method in RunPomodoro()
🤖
---
internal/pomodoro/pomodoro.go | 6 +++---
internal/pomodoro/timer.go | 7 ++++++-
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/internal/pomodoro/pomodoro.go b/internal/pomodoro/pomodoro.go
index 8228249..a7bcc00 100644
--- a/internal/pomodoro/pomodoro.go
+++ b/internal/pomodoro/pomodoro.go
@@ -42,7 +42,7 @@ func RunPomodoro() {
// Work
shared.State.Mode = "Work"
- go timer.Start(pomodoroConfig.Work)
+ timer.StartAsync(pomodoroConfig.Work)
if !waitForTimer(timer) {
break
}
@@ -50,13 +50,13 @@ func RunPomodoro() {
// Breaks
if session < pomodoroConfig.Sessions {
shared.State.Mode = "ShortBreak"
- go timer.Start(pomodoroConfig.ShortBreak)
+ timer.StartAsync(pomodoroConfig.ShortBreak)
if !waitForTimer(timer) {
break
}
} else { // last phase, prepare for finish
shared.State.Mode = "LongBreak"
- go timer.Start(pomodoroConfig.LongBreak)
+ timer.StartAsync(pomodoroConfig.LongBreak)
if !waitForTimer(timer) {
break
}
diff --git a/internal/pomodoro/timer.go b/internal/pomodoro/timer.go
index 09a50ee..11b1070 100644
--- a/internal/pomodoro/timer.go
+++ b/internal/pomodoro/timer.go
@@ -24,7 +24,12 @@ func (t Timer) Init() Timer {
}
}
-// Start the timer
+// Start the timer (goroutine)
+func (t *Timer) StartAsync(duration int) {
+ go t.Start(duration)
+}
+
+// Start the timer (blocking)
func (t *Timer) Start(duration int) {
tick := time.NewTicker(time.Second)
for timeLeft := duration; timeLeft > 0; {
From bdfd5c3b8448cff5d7903ec136bfcb8d32afa2fa Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 08:09:41 +0100
Subject: [PATCH 10/44] feat: remove unused client mutex
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- remove unused Mutex from `models.Client` struct
- remove lock from `HandleConnection()`
- replace websocket.Conn with models.Client in `handleClientCommands()`
🤖
---
internal/websocket/client_commands.go | 4 ++--
internal/websocket/handle_connection.go | 9 +++++----
pkg/models/client.go | 7 +------
3 files changed, 8 insertions(+), 12 deletions(-)
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index 53464dd..4ea7e7d 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -3,7 +3,6 @@ package websocket
import (
"encoding/json"
"github.com/charmbracelet/log"
- "github.com/gorilla/websocket"
"git.smsvc.net/pomodoro/GoTomato/internal/pomodoro"
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
@@ -11,7 +10,8 @@ import (
)
// Listens for commands from a client and handles them
-func handleClientCommands(ws *websocket.Conn) {
+func handleClientCommands(c models.Client) {
+ ws := c.Conn
for {
var clientCommand models.ClientCommand
diff --git a/internal/websocket/handle_connection.go b/internal/websocket/handle_connection.go
index 5e97df2..37160d8 100644
--- a/internal/websocket/handle_connection.go
+++ b/internal/websocket/handle_connection.go
@@ -31,12 +31,13 @@ func HandleConnection(w http.ResponseWriter, r *http.Request) {
log.Info("Client connected", "host", ws.NetConn().RemoteAddr(), "clients", len(Clients)+1)
// Register the new client
- mu.Lock()
- Clients[ws] = &models.Client{
- Conn: ws, // Store the WebSocket connection
+ client := models.Client{
+ Conn: ws,
}
+ mu.Lock()
+ Clients[ws] = &client
mu.Unlock()
// Listen for commands from the connected client
- handleClientCommands(ws)
+ handleClientCommands(client)
}
diff --git a/pkg/models/client.go b/pkg/models/client.go
index 7a6ae21..f9eb116 100644
--- a/pkg/models/client.go
+++ b/pkg/models/client.go
@@ -3,7 +3,6 @@ package models
import (
"github.com/charmbracelet/log"
"github.com/gorilla/websocket"
- "sync"
)
// Represents a command from the client (start/stop)
@@ -15,16 +14,12 @@ type ClientCommand struct {
// Represents a single client
type Client struct {
- Conn *websocket.Conn // Websocket connection of the client
- Mutex sync.Mutex // Mutex used to lock
+ Conn *websocket.Conn
}
// Sends a message to the websocket.
// Automatically locks and unlocks the client mutex, to ensure that only one goroutine can write at a time.
func (c *Client) SendMessage(messageType int, data []byte) error {
- c.Mutex.Lock()
- defer c.Mutex.Unlock()
-
err := c.Conn.WriteMessage(messageType, data)
if err != nil {
log.Error("Error writing to WebSocket:", "msg", err)
From 2d2ea6ff7867319673895b35753d9bf226f1b382 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 08:11:54 +0100
Subject: [PATCH 11/44] feat: bump version to v0.0.5
---
internal/metadata/version.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index 9463896..e31bfed 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "v0.0.4" // The GoTomato version
+const GoTomatoVersion = "v0.0.5" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From ebb58a44893fb09ab57189461f13804c28534eb4 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 09:57:09 +0100
Subject: [PATCH 12/44] feat: rename `Client` model to `WebsocketClient`
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
🤖
---
internal/websocket/client_commands.go | 2 +-
internal/websocket/handle_connection.go | 4 ++--
pkg/models/client.go | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index 4ea7e7d..59e603a 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -10,7 +10,7 @@ import (
)
// Listens for commands from a client and handles them
-func handleClientCommands(c models.Client) {
+func handleClientCommands(c models.WebsocketClient) {
ws := c.Conn
for {
var clientCommand models.ClientCommand
diff --git a/internal/websocket/handle_connection.go b/internal/websocket/handle_connection.go
index 37160d8..dc5ad1c 100644
--- a/internal/websocket/handle_connection.go
+++ b/internal/websocket/handle_connection.go
@@ -10,7 +10,7 @@ import (
)
// Clients is a map of connected WebSocket clients, where each client is represented by the Client struct
-var Clients = make(map[*websocket.Conn]*models.Client)
+var Clients = make(map[*websocket.Conn]*models.WebsocketClient)
var mu sync.Mutex // Mutex to protect access to the Clients map
// Upgrade HTTP requests to WebSocket connections
@@ -31,7 +31,7 @@ func HandleConnection(w http.ResponseWriter, r *http.Request) {
log.Info("Client connected", "host", ws.NetConn().RemoteAddr(), "clients", len(Clients)+1)
// Register the new client
- client := models.Client{
+ client := models.WebsocketClient{
Conn: ws,
}
mu.Lock()
diff --git a/pkg/models/client.go b/pkg/models/client.go
index f9eb116..c0998f8 100644
--- a/pkg/models/client.go
+++ b/pkg/models/client.go
@@ -13,13 +13,13 @@ type ClientCommand struct {
}
// Represents a single client
-type Client struct {
+type WebsocketClient struct {
Conn *websocket.Conn
}
// Sends a message to the websocket.
// Automatically locks and unlocks the client mutex, to ensure that only one goroutine can write at a time.
-func (c *Client) SendMessage(messageType int, data []byte) error {
+func (c *WebsocketClient) SendMessage(messageType int, data []byte) error {
err := c.Conn.WriteMessage(messageType, data)
if err != nil {
log.Error("Error writing to WebSocket:", "msg", err)
From 0ee955189c7cdb4156ced500d9d582022708857d Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 10:17:24 +0100
Subject: [PATCH 13/44] feat: update client management to use local address as
identifier
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- change Clients map to use net.Addr as the key type
- update `HandleConnection()` to store clients using LocalAddr
- modify `handleClientCommands()` to delete clients by LocalAddr
🤖
---
internal/websocket/client_commands.go | 2 +-
internal/websocket/handle_connection.go | 7 ++++---
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index 59e603a..b38e55b 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -18,7 +18,7 @@ func handleClientCommands(c models.WebsocketClient) {
_, message, err := ws.ReadMessage()
if err != nil {
log.Info("Client disconnected:", "msg", err, "host", ws.NetConn().RemoteAddr(), "clients", len(Clients)-1)
- delete(Clients, ws)
+ delete(Clients, ws.LocalAddr())
break
}
diff --git a/internal/websocket/handle_connection.go b/internal/websocket/handle_connection.go
index dc5ad1c..b7b240f 100644
--- a/internal/websocket/handle_connection.go
+++ b/internal/websocket/handle_connection.go
@@ -3,14 +3,15 @@ package websocket
import (
"github.com/charmbracelet/log"
"github.com/gorilla/websocket"
+ "net"
"net/http"
"sync"
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
-// Clients is a map of connected WebSocket clients, where each client is represented by the Client struct
-var Clients = make(map[*websocket.Conn]*models.WebsocketClient)
+// Clients is a map of connected WebSocket clients, where each client is represented by the WebsocketClient struct
+var Clients = make(map[net.Addr]*models.WebsocketClient)
var mu sync.Mutex // Mutex to protect access to the Clients map
// Upgrade HTTP requests to WebSocket connections
@@ -35,7 +36,7 @@ func HandleConnection(w http.ResponseWriter, r *http.Request) {
Conn: ws,
}
mu.Lock()
- Clients[ws] = &client
+ Clients[ws.LocalAddr()] = &client
mu.Unlock()
// Listen for commands from the connected client
From f4fd37c55165a80876f4d29bae2a82c83c42c1fd Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 10:19:07 +0100
Subject: [PATCH 14/44] feat: update logging for client connect and disconnect
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- update logging to use ws.RemoteAddr()
🤖
---
internal/websocket/client_commands.go | 2 +-
internal/websocket/handle_connection.go | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index b38e55b..60158f2 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -17,7 +17,7 @@ func handleClientCommands(c models.WebsocketClient) {
_, message, err := ws.ReadMessage()
if err != nil {
- log.Info("Client disconnected:", "msg", err, "host", ws.NetConn().RemoteAddr(), "clients", len(Clients)-1)
+ log.Info("Client disconnected:", "msg", err, "host", ws.RemoteAddr(), "clients", len(Clients)-1)
delete(Clients, ws.LocalAddr())
break
}
diff --git a/internal/websocket/handle_connection.go b/internal/websocket/handle_connection.go
index b7b240f..6abb339 100644
--- a/internal/websocket/handle_connection.go
+++ b/internal/websocket/handle_connection.go
@@ -29,7 +29,7 @@ func HandleConnection(w http.ResponseWriter, r *http.Request) {
}
defer ws.Close()
- log.Info("Client connected", "host", ws.NetConn().RemoteAddr(), "clients", len(Clients)+1)
+ log.Info("Client connected", "host", ws.RemoteAddr(), "clients", len(Clients)+1)
// Register the new client
client := models.WebsocketClient{
From e7618b19ef8367c3942d7e4570c6538261439909 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 11:28:42 +0100
Subject: [PATCH 15/44] feat: validate client settings and improve logging
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- add a function to check if Pomodoro settings are valid
- log a warning for invalid client configurations
- log an info message for valid client configurations
- implement Stringer interface for PomodoroConfig model
🤖
---
internal/websocket/client_commands.go | 9 +++++++++
pkg/models/config.go | 7 +++++++
2 files changed, 16 insertions(+)
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index 60158f2..2fba584 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -9,6 +9,10 @@ import (
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
+func checkSettings(settings models.PomodoroConfig) bool {
+ return settings.Work > 0 && settings.ShortBreak > 0 && settings.LongBreak > 0 && settings.Sessions > 0
+}
+
// Listens for commands from a client and handles them
func handleClientCommands(c models.WebsocketClient) {
ws := c.Conn
@@ -50,6 +54,11 @@ func handleClientCommands(c models.WebsocketClient) {
}
case "updateSettings":
if !pomodoro.IsPomodoroOngoing() {
+ if !checkSettings(clientCommand.Settings) {
+ log.Warn("Ignoring invalid config:", "msg", clientCommand.Settings, "host", c.Conn.RemoteAddr())
+ break
+ }
+ log.Info("Client send config", "config", clientCommand.Settings, "host", c.Conn.RemoteAddr())
pomodoro.UpdateSettings(clientCommand.Settings)
}
}
diff --git a/pkg/models/config.go b/pkg/models/config.go
index 36b9dbb..1852165 100644
--- a/pkg/models/config.go
+++ b/pkg/models/config.go
@@ -1,5 +1,7 @@
package models
+import "fmt"
+
// Represents the configuration of a pomodoro
type PomodoroConfig struct {
Work int `json:"work"` // Length of work sessions in seconds
@@ -8,6 +10,11 @@ type PomodoroConfig struct {
Sessions int `json:"sessions"` // Number of total sessions
}
+// Stringer interface for the PomodocoConfig model
+func (c PomodoroConfig) String() string {
+ return fmt.Sprintf("{work: %d, short: %d, long: %d, sessions: %d}", c.Work, c.ShortBreak, c.LongBreak, c.Sessions)
+}
+
// Represents the server configuration
type ServerConfig struct {
ListenAddress string `json:"listenAddress"` // Server listen address
From dd9490bb3b8e80b0b4b272ac67ecce896b8cdb9b Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 30 Oct 2024 11:29:47 +0100
Subject: [PATCH 16/44] feat: bump version to v0.0.6
---
internal/metadata/version.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index e31bfed..2ab12fa 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "v0.0.5" // The GoTomato version
+const GoTomatoVersion = "v0.0.6" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From 44a64bfce4bc7435ad476071f8e0fe96e0e43d69 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sun, 3 Nov 2024 10:00:14 +0100
Subject: [PATCH 17/44] feat: handle X-Forward-For for log output
- add Gorilla handlers package for enhanced HTTP handling
- refactor HTTP server to use a new ServeMux for routing
- update ListenAndServe to utilize ProxyHeaders for better proxy support
- add RealIP field to client model
- use RealIP fild for connect/disconnect log output
---
cmd/server/main.go | 6 ++++--
go.mod | 2 ++
go.sum | 4 ++++
internal/websocket/client_commands.go | 2 +-
internal/websocket/handle_connection.go | 7 ++++---
pkg/models/client.go | 3 ++-
6 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 126ec2f..c30f3e4 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"github.com/charmbracelet/log"
+ "github.com/gorilla/handlers"
"net/http"
"os"
@@ -43,14 +44,15 @@ func Start() {
listen := fmt.Sprintf("%s:%d", serverConfig.ListenAddress, serverConfig.ListenPort)
// start connection handler and broadcast
- http.HandleFunc("/ws", websocket.HandleConnection)
+ r := http.NewServeMux()
+ r.HandleFunc("/ws", websocket.HandleConnection)
go websocket.SendPermanentBroadCastMessage()
log.Info("GoTomato started", "version", metadata.GoTomatoVersion)
log.Info("Websocket listening", "address", listen)
// start the listener
- err := http.ListenAndServe(listen, nil)
+ err := http.ListenAndServe(listen, handlers.ProxyHeaders(r))
if err != nil {
log.Fatal("Error starting server:", "msg", err)
}
diff --git a/go.mod b/go.mod
index 148683e..e78b89d 100644
--- a/go.mod
+++ b/go.mod
@@ -4,12 +4,14 @@ go 1.23
require (
github.com/charmbracelet/log v0.4.0
+ github.com/gorilla/handlers v1.5.2
github.com/gorilla/websocket v1.5.3
)
require (
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
github.com/charmbracelet/lipgloss v0.10.0 // indirect
+ github.com/felixge/httpsnoop v1.0.3 // indirect
github.com/go-logfmt/logfmt v0.6.0 // indirect
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
diff --git a/go.sum b/go.sum
index 9437970..77f660c 100644
--- a/go.sum
+++ b/go.sum
@@ -6,8 +6,12 @@ github.com/charmbracelet/log v0.4.0 h1:G9bQAcx8rWA2T3pWvx7YtPTPwgqpk7D68BX21IRW8
github.com/charmbracelet/log v0.4.0/go.mod h1:63bXt/djrizTec0l11H20t8FDSvA4CRZJ1KH22MdptM=
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/felixge/httpsnoop v1.0.3 h1:s/nj+GCswXYzN5v2DpNMuMQYe+0DDwt5WVCU6CWBdXk=
+github.com/felixge/httpsnoop v1.0.3/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4=
github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
+github.com/gorilla/handlers v1.5.2 h1:cLTUSsNkgcwhgRqvCNmdbRWG0A3N4F+M2nWKdScwyEE=
+github.com/gorilla/handlers v1.5.2/go.mod h1:dX+xVpaxdSw+q0Qek8SSsl3dfMk3jNddUkMzo0GtH0w=
github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg=
github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index 2fba584..1a66198 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -21,8 +21,8 @@ func handleClientCommands(c models.WebsocketClient) {
_, message, err := ws.ReadMessage()
if err != nil {
- log.Info("Client disconnected:", "msg", err, "host", ws.RemoteAddr(), "clients", len(Clients)-1)
delete(Clients, ws.LocalAddr())
+ log.Info("Client disconnected:", "msg", err, "host", c.RealIP, "clients", len(Clients))
break
}
diff --git a/internal/websocket/handle_connection.go b/internal/websocket/handle_connection.go
index 6abb339..6ee22bc 100644
--- a/internal/websocket/handle_connection.go
+++ b/internal/websocket/handle_connection.go
@@ -29,16 +29,17 @@ func HandleConnection(w http.ResponseWriter, r *http.Request) {
}
defer ws.Close()
- log.Info("Client connected", "host", ws.RemoteAddr(), "clients", len(Clients)+1)
-
// Register the new client
client := models.WebsocketClient{
- Conn: ws,
+ Conn: ws,
+ RealIP: r.RemoteAddr,
}
mu.Lock()
Clients[ws.LocalAddr()] = &client
mu.Unlock()
+ log.Info("Client connected", "host", client.RealIP, "clients", len(Clients))
+
// Listen for commands from the connected client
handleClientCommands(client)
}
diff --git a/pkg/models/client.go b/pkg/models/client.go
index c0998f8..aec2f3c 100644
--- a/pkg/models/client.go
+++ b/pkg/models/client.go
@@ -14,7 +14,8 @@ type ClientCommand struct {
// Represents a single client
type WebsocketClient struct {
- Conn *websocket.Conn
+ Conn *websocket.Conn
+ RealIP string
}
// Sends a message to the websocket.
From 76f395429978bc46340dd081746b7065df0577ca Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sun, 3 Nov 2024 11:19:03 +0100
Subject: [PATCH 18/44] feat: bump version to v0.0.7
---
internal/metadata/version.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index 2ab12fa..84b8dd7 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "v0.0.6" // The GoTomato version
+const GoTomatoVersion = "v0.0.7" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From 600d2ed2ffffc69d5832648fbfaf544dc1774a4e Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 4 Nov 2024 20:33:25 +0100
Subject: [PATCH 19/44] feat: implement centralized logging helper
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- remove direct log usage
- create a new logging helper
- update all log calls to use the new Logger instance
- set timestamp to ISO8601
🤖
---
cmd/server/main.go | 8 ++++----
internal/helper/logging.go | 12 ++++++++++++
internal/websocket/broadcast.go | 6 +++---
internal/websocket/client_commands.go | 10 +++++-----
internal/websocket/handle_connection.go | 6 +++---
pkg/models/client.go | 5 +++--
6 files changed, 30 insertions(+), 17 deletions(-)
create mode 100644 internal/helper/logging.go
diff --git a/cmd/server/main.go b/cmd/server/main.go
index c30f3e4..a109f38 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -3,11 +3,11 @@ package server
import (
"flag"
"fmt"
- "github.com/charmbracelet/log"
"github.com/gorilla/handlers"
"net/http"
"os"
+ "git.smsvc.net/pomodoro/GoTomato/internal/helper"
"git.smsvc.net/pomodoro/GoTomato/internal/metadata"
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
"git.smsvc.net/pomodoro/GoTomato/internal/websocket"
@@ -48,12 +48,12 @@ func Start() {
r.HandleFunc("/ws", websocket.HandleConnection)
go websocket.SendPermanentBroadCastMessage()
- log.Info("GoTomato started", "version", metadata.GoTomatoVersion)
- log.Info("Websocket listening", "address", listen)
+ helper.Logger.Info("GoTomato started", "version", metadata.GoTomatoVersion)
+ helper.Logger.Info("Websocket listening", "address", listen)
// start the listener
err := http.ListenAndServe(listen, handlers.ProxyHeaders(r))
if err != nil {
- log.Fatal("Error starting server:", "msg", err)
+ helper.Logger.Fatal("Error starting server:", "msg", err)
}
}
diff --git a/internal/helper/logging.go b/internal/helper/logging.go
new file mode 100644
index 0000000..ecb7371
--- /dev/null
+++ b/internal/helper/logging.go
@@ -0,0 +1,12 @@
+package helper
+
+import (
+ "github.com/charmbracelet/log"
+ "os"
+ "time"
+)
+
+var Logger = log.NewWithOptions(os.Stdout, log.Options{
+ ReportTimestamp: true,
+ TimeFormat: time.RFC3339,
+})
diff --git a/internal/websocket/broadcast.go b/internal/websocket/broadcast.go
index 14254c0..def8309 100644
--- a/internal/websocket/broadcast.go
+++ b/internal/websocket/broadcast.go
@@ -2,10 +2,10 @@ package websocket
import (
"encoding/json"
- "github.com/charmbracelet/log"
"github.com/gorilla/websocket"
"time"
+ "git.smsvc.net/pomodoro/GoTomato/internal/helper"
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
)
@@ -16,14 +16,14 @@ func SendPermanentBroadCastMessage() {
// Marshal the message into JSON format
jsonMessage, err := json.Marshal(shared.State)
if err != nil {
- log.Error("Error marshalling message:", "msg", err)
+ helper.Logger.Error("Error marshalling message:", "msg", err)
return
}
// Iterate over all connected clients and broadcast the message
for _, client := range Clients {
err := client.SendMessage(websocket.TextMessage, jsonMessage)
if err != nil {
- log.Error("Error broadcasting to client:", "msg", err)
+ helper.Logger.Error("Error broadcasting to client:", "msg", err)
// The client is responsible for closing itself on error
}
}
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index 1a66198..bdb6e7a 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -2,8 +2,8 @@ package websocket
import (
"encoding/json"
- "github.com/charmbracelet/log"
+ "git.smsvc.net/pomodoro/GoTomato/internal/helper"
"git.smsvc.net/pomodoro/GoTomato/internal/pomodoro"
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
@@ -22,14 +22,14 @@ func handleClientCommands(c models.WebsocketClient) {
_, message, err := ws.ReadMessage()
if err != nil {
delete(Clients, ws.LocalAddr())
- log.Info("Client disconnected:", "msg", err, "host", c.RealIP, "clients", len(Clients))
+ helper.Logger.Info("Client disconnected:", "msg", err, "host", c.RealIP, "clients", len(Clients))
break
}
// Handle incoming commands
err = json.Unmarshal(message, &clientCommand)
if err != nil {
- log.Error("Error unmarshalling command:", "msg", err)
+ helper.Logger.Error("Error unmarshalling command:", "msg", err)
continue
}
@@ -55,10 +55,10 @@ func handleClientCommands(c models.WebsocketClient) {
case "updateSettings":
if !pomodoro.IsPomodoroOngoing() {
if !checkSettings(clientCommand.Settings) {
- log.Warn("Ignoring invalid config:", "msg", clientCommand.Settings, "host", c.Conn.RemoteAddr())
+ helper.Logger.Warn("Ignoring invalid config:", "msg", clientCommand.Settings, "host", c.Conn.RemoteAddr())
break
}
- log.Info("Client send config", "config", clientCommand.Settings, "host", c.Conn.RemoteAddr())
+ helper.Logger.Info("Client send config", "config", clientCommand.Settings, "host", c.Conn.RemoteAddr())
pomodoro.UpdateSettings(clientCommand.Settings)
}
}
diff --git a/internal/websocket/handle_connection.go b/internal/websocket/handle_connection.go
index 6ee22bc..9c4b43f 100644
--- a/internal/websocket/handle_connection.go
+++ b/internal/websocket/handle_connection.go
@@ -1,12 +1,12 @@
package websocket
import (
- "github.com/charmbracelet/log"
"github.com/gorilla/websocket"
"net"
"net/http"
"sync"
+ "git.smsvc.net/pomodoro/GoTomato/internal/helper"
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
)
@@ -24,7 +24,7 @@ func HandleConnection(w http.ResponseWriter, r *http.Request) {
// Upgrade initial GET request to a WebSocket
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
- log.Error("WebSocket upgrade error:", "msg", err)
+ helper.Logger.Error("WebSocket upgrade error:", "msg", err)
return
}
defer ws.Close()
@@ -38,7 +38,7 @@ func HandleConnection(w http.ResponseWriter, r *http.Request) {
Clients[ws.LocalAddr()] = &client
mu.Unlock()
- log.Info("Client connected", "host", client.RealIP, "clients", len(Clients))
+ helper.Logger.Info("Client connected", "host", client.RealIP, "clients", len(Clients))
// Listen for commands from the connected client
handleClientCommands(client)
diff --git a/pkg/models/client.go b/pkg/models/client.go
index aec2f3c..eef9663 100644
--- a/pkg/models/client.go
+++ b/pkg/models/client.go
@@ -1,8 +1,9 @@
package models
import (
- "github.com/charmbracelet/log"
"github.com/gorilla/websocket"
+
+ "git.smsvc.net/pomodoro/GoTomato/internal/helper"
)
// Represents a command from the client (start/stop)
@@ -23,7 +24,7 @@ type WebsocketClient struct {
func (c *WebsocketClient) SendMessage(messageType int, data []byte) error {
err := c.Conn.WriteMessage(messageType, data)
if err != nil {
- log.Error("Error writing to WebSocket:", "msg", err)
+ helper.Logger.Error("Error writing to WebSocket:", "msg", err)
c.Conn.Close() // Close the connection on error
}
return err
From d7b77890512385b8c17df8838eaa8f5b9f201ffd Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 4 Nov 2024 20:35:01 +0100
Subject: [PATCH 20/44] feat: bump version to v0.0.8
---
internal/metadata/version.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index 84b8dd7..8968337 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "v0.0.7" // The GoTomato version
+const GoTomatoVersion = "v0.0.8" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From cbe2e007de082c23293d4e37ab9bd07f0ebf5758 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Tue, 5 Nov 2024 23:29:24 +0100
Subject: [PATCH 21/44] break: drop "v" from version string const
- removes "v" from the ProtocolVersion in the ServerMessage
- remove "v" prefix from GoTomatoVersion constant
- re-add "v" for for human readable output (`-version`)
- update README
---
README.md | 10 +++++-----
cmd/server/main.go | 4 ++--
internal/metadata/version.go | 2 +-
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/README.md b/README.md
index 15e4f08..c2d9e51 100644
--- a/README.md
+++ b/README.md
@@ -67,11 +67,11 @@ The server periodically (every second) sends JSON-encoded messages to all connec
| Message Type | Example |
| --- | --- |
-| Welcome Message | {"mode":"Idle", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":1500, "ongoing":false, "paused":false, "version":"v0"} |
-| Session Running | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":1, "time_left":900, "ongoing":true, "paused":false, "version":"v0"} |
-| Session Running | {"mode":"ShortBreak", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":50, "ongoing":true, "paused":false, "version":"v0"} |
-| Session Paused | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":456, "ongoing":true, "paused":true, "version":"v0"} |
-| Session End/Reset | {"mode":"End", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":0, "ongoing":false, "paused":false, "version":"v0"} |
+| Welcome Message | {"mode":"Idle", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":1500, "ongoing":false, "paused":false, "version":"0"} |
+| Session Running | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":1, "time_left":900, "ongoing":true, "paused":false, "version":"0"} |
+| Session Running | {"mode":"ShortBreak", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":50, "ongoing":true, "paused":false, "version":"0"} |
+| Session Paused | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":456, "ongoing":true, "paused":true, "version":"0"} |
+| Session End/Reset | {"mode":"End", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":0, "ongoing":false, "paused":false, "version":"0"} |
## Testing
diff --git a/cmd/server/main.go b/cmd/server/main.go
index a109f38..29241f0 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -28,8 +28,8 @@ func Start() {
// show server and protocl version and exit
if *showVersionFlag {
- fmt.Println("Server-Version:", metadata.GoTomatoVersion)
- fmt.Println("Protocol-Version:", metadata.ProtocolVersion)
+ fmt.Printf("Server-Version: v%s\n", metadata.GoTomatoVersion)
+ fmt.Printf("Protocol-Version: v%s\n", metadata.ProtocolVersion)
os.Exit(0)
}
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index 8968337..f05a892 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "v0.0.8" // The GoTomato version
+const GoTomatoVersion = "0.0.8" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From b15324f6f8ca32c3ee196e23f7792d3724f22db7 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 6 Nov 2024 08:27:12 +0100
Subject: [PATCH 22/44] feat: bump version to v0.1.0
---
internal/metadata/version.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index f05a892..9b7f4f7 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "0.0.8" // The GoTomato version
+const GoTomatoVersion = "0.1.0" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From f346cbbcaa78a69979c413cadcf98f19b421d32e Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 6 Nov 2024 18:11:37 +0100
Subject: [PATCH 23/44] feat: add initial configuration for GoReleaser
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
🤖
---
.gitignore | 2 ++
.goreleaser.yaml | 41 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 43 insertions(+)
create mode 100644 .goreleaser.yaml
diff --git a/.gitignore b/.gitignore
index 2201ae4..5ee2497 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1 +1,3 @@
GoTomato
+
+dist/
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
new file mode 100644
index 0000000..aa2e879
--- /dev/null
+++ b/.goreleaser.yaml
@@ -0,0 +1,41 @@
+# vim: set ts=2 sw=2 tw=0 fo=cnqoj
+
+version: 2
+
+before:
+ hooks:
+ - rm -fr ./dist
+ - go mod tidy
+
+builds:
+ - goos:
+ - linux
+ goarch:
+ - amd64
+ - arm64
+ env:
+ - CGO_ENABLED=0
+
+upx:
+ - enabled: true
+ compress: best
+ lzma: true
+
+changelog:
+ sort: desc
+ filters:
+ exclude:
+ - "bump version to"
+
+archives:
+ - format: binary
+
+release:
+ gitea:
+ owner: pomodoro
+ name: GoTomato
+ mode: replace
+
+gitea_urls:
+ download: http://git.smsvc.net
+ api: http://git.smsvc.net/api/v1
From 783d158e9231a4e95276c50decb17ecb427a4234 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Wed, 6 Nov 2024 20:44:44 +0100
Subject: [PATCH 24/44] feat: bump version to 0.1.1
---
internal/metadata/version.go | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index 9b7f4f7..22e394e 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,5 @@ package metadata
import "strings"
-const GoTomatoVersion = "0.1.0" // The GoTomato version
+const GoTomatoVersion = "0.1.1" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From 93f39507c1477cd7b8853be0d40d7b441b60ccfd Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Thu, 7 Nov 2024 11:38:45 +0100
Subject: [PATCH 25/44] feat(gorleaser): set version from git tag on build
- make `GoTomatoVersion` a variable and default it to "devel"
- add ldflags to `.goreleaser.yaml` for version tagging
- remove "v" from output of `-version`
---
.goreleaser.yaml | 2 ++
cmd/server/main.go | 4 ++--
internal/metadata/version.go | 3 ++-
3 files changed, 6 insertions(+), 3 deletions(-)
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index aa2e879..4b315c5 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -15,6 +15,8 @@ builds:
- arm64
env:
- CGO_ENABLED=0
+ ldflags:
+ - -s -w -X git.smsvc.net/pomodoro/GoTomato/internal/metadata.GoTomatoVersion={{.Version}}
upx:
- enabled: true
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 29241f0..a109f38 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -28,8 +28,8 @@ func Start() {
// show server and protocl version and exit
if *showVersionFlag {
- fmt.Printf("Server-Version: v%s\n", metadata.GoTomatoVersion)
- fmt.Printf("Protocol-Version: v%s\n", metadata.ProtocolVersion)
+ fmt.Println("Server-Version:", metadata.GoTomatoVersion)
+ fmt.Println("Protocol-Version:", metadata.ProtocolVersion)
os.Exit(0)
}
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index 22e394e..ecac17b 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -2,5 +2,6 @@ package metadata
import "strings"
-const GoTomatoVersion = "0.1.1" // The GoTomato version
+// This will be overwritten by goreleaser on build
+var GoTomatoVersion = "devel" // The GoTomato version
var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
From 467d90065c43d9384da3ba3da63d98435171b01b Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Thu, 7 Nov 2024 19:29:48 +0100
Subject: [PATCH 26/44] feat(goreleaser): update changelog configuration
- uses the compare Gitea API
- drop `sort` setting
- remove the filter that excludes version bump entries
---
.goreleaser.yaml | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index 4b315c5..a3190f6 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -24,10 +24,7 @@ upx:
lzma: true
changelog:
- sort: desc
- filters:
- exclude:
- - "bump version to"
+ use: gitea
archives:
- format: binary
From 9852f80461172d23230000420272c48f0cce0c89 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Fri, 8 Nov 2024 14:23:54 +0100
Subject: [PATCH 27/44] fix: restore filter that excludes version bump entries
---
.goreleaser.yaml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index a3190f6..48ad016 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -25,6 +25,9 @@ upx:
changelog:
use: gitea
+ filters:
+ exclude:
+ - "chore: bump version to"
archives:
- format: binary
From 2032688c1f9ce981d1f8675a33339783ad472cf3 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sat, 9 Nov 2024 15:59:30 +0100
Subject: [PATCH 28/44] feat!: always retrieve version from
`runtime/debug.Main.Version` or latest git tag
- set version from runtime/debug.Main.Version
- use latest git tag as fallback
- allow GoTomatoVersion to be overwritten via ldflags
- this will break `go build .` and `go install .`
---
internal/metadata/version.go | 38 ++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)
diff --git a/internal/metadata/version.go b/internal/metadata/version.go
index ecac17b..1d76b3e 100644
--- a/internal/metadata/version.go
+++ b/internal/metadata/version.go
@@ -1,7 +1,37 @@
package metadata
-import "strings"
+import (
+ "os/exec"
+ "runtime/debug"
+ "strings"
+)
-// This will be overwritten by goreleaser on build
-var GoTomatoVersion = "devel" // The GoTomato version
-var ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0] // The protocol version
+var (
+ GoTomatoVersion = "" // The GoTomato version
+ ProtocolVersion = "" // The protocol version
+)
+
+func stripVersionPrefix(version string) string {
+ return strings.TrimLeft(version, "v")
+}
+
+func getLatestTag() string {
+ bytes, _ := exec.Command("git", "describe", "--tags").Output()
+ output := strings.TrimSpace(string(bytes))
+ return stripVersionPrefix(output)
+}
+
+// set GoTomatoVersion from runtime/debug.Main.Version
+// use latest git tag as fallback
+// can be overwritten via ldflags (e,g. by goreleaser)
+func init() {
+ if GoTomatoVersion == "" {
+ info, _ := debug.ReadBuildInfo()
+ if info.Main.Version != "(devel)" {
+ GoTomatoVersion = stripVersionPrefix(info.Main.Version)
+ } else {
+ GoTomatoVersion = getLatestTag()
+ }
+ }
+ ProtocolVersion = strings.Split(GoTomatoVersion, ".")[0]
+}
From 05a8701a263e063a6d4fa134638b91952c2f99a8 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Fri, 8 Nov 2024 14:22:54 +0100
Subject: [PATCH 29/44] feat: update `-version` output
---
cmd/server/main.go | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index a109f38..2024fa2 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -28,8 +28,8 @@ func Start() {
// show server and protocl version and exit
if *showVersionFlag {
- fmt.Println("Server-Version:", metadata.GoTomatoVersion)
- fmt.Println("Protocol-Version:", metadata.ProtocolVersion)
+ fmt.Printf("GoTomato v%s\n", metadata.GoTomatoVersion)
+ fmt.Printf("Protocol-Version: %s\n", metadata.ProtocolVersion)
os.Exit(0)
}
From 2f337bb9d69842c92f2af2c3525758b4c8943d88 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Fri, 8 Nov 2024 15:13:46 +0100
Subject: [PATCH 30/44] feat: add release management via `Task`
- create `Taskfile.yml`
- initial tasks
- add new version tag
- push to remote and run goreleaser
- create snapshot via goreleaser
---
Taskfile.yml | 32 ++++++++++++++++++++++++++++++++
1 file changed, 32 insertions(+)
create mode 100644 Taskfile.yml
diff --git a/Taskfile.yml b/Taskfile.yml
new file mode 100644
index 0000000..77dfff5
--- /dev/null
+++ b/Taskfile.yml
@@ -0,0 +1,32 @@
+# github.com/go-task/task/v3/cmd/task@latest
+# Requirements:
+# github.com/caarlos0/svu@latest
+# github.com/goreleaser/goreleaser/v2@latest
+
+version: '3'
+
+tasks:
+
+ release:
+ desc: Create and publish an new release
+ vars:
+ RELEASE:
+ sh: svu next
+ BRANCH:
+ sh: git branch --show-current
+ COMMIT:
+ sh: git rev-parse --short --verify {{.BRANCH}}
+ preconditions:
+ - sh: test "{{.BRANCH}}" == "main"
+ msg: "You must be on the main branch to release"
+ prompt: Create new release {{.RELEASE}} from {{.COMMIT}}@{{.BRANCH}}?
+ cmds:
+ - git tag {{.RELEASE}}
+ - git push
+ - git push origin tag {{.RELEASE}}
+ - goreleaser release --clean
+
+ snapshot:
+ desc: Create a local snapshot release
+ cmds:
+ - goreleaser release --clean --snapshot
From 13e2c2d0e406eb2fbb37b4d72a8643ac304c62d8 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sat, 9 Nov 2024 09:51:07 +0100
Subject: [PATCH 31/44] fix(goreleaser): don't force-remove `./dist`
---
.goreleaser.yaml | 1 -
1 file changed, 1 deletion(-)
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index 48ad016..22dc0d9 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -4,7 +4,6 @@ version: 2
before:
hooks:
- - rm -fr ./dist
- go mod tidy
builds:
From 8683cb2a6b21d4d82b217453f18988b684243675 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sat, 9 Nov 2024 10:42:26 +0100
Subject: [PATCH 32/44] chore: add yaml schemas to `Taskfile.yml` and
`.goreleaser.yaml`
---
.goreleaser.yaml | 1 +
Taskfile.yml | 2 ++
2 files changed, 3 insertions(+)
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index 22dc0d9..9bdad83 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -1,4 +1,5 @@
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
+# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
version: 2
diff --git a/Taskfile.yml b/Taskfile.yml
index 77dfff5..8efbf3a 100644
--- a/Taskfile.yml
+++ b/Taskfile.yml
@@ -1,3 +1,5 @@
+# yaml-language-server: $schema=https://taskfile.dev/schema.json
+#
# github.com/go-task/task/v3/cmd/task@latest
# Requirements:
# github.com/caarlos0/svu@latest
From 64f790bf90cb31b74d2fa9f2636e6af829236f4d Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sat, 9 Nov 2024 22:37:52 +0100
Subject: [PATCH 33/44] feat(goreleaser): update build command to use
`.ModulePath` variable
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- change hardcoded module path to dynamic reference
🤖
---
.goreleaser.yaml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/.goreleaser.yaml b/.goreleaser.yaml
index 9bdad83..77a3e60 100644
--- a/.goreleaser.yaml
+++ b/.goreleaser.yaml
@@ -16,7 +16,7 @@ builds:
env:
- CGO_ENABLED=0
ldflags:
- - -s -w -X git.smsvc.net/pomodoro/GoTomato/internal/metadata.GoTomatoVersion={{.Version}}
+ - -s -w -X {{.ModulePath}}/internal/metadata.GoTomatoVersion={{.Version}}
upx:
- enabled: true
From b3f403cf1afc2ee4c68866731bbfd18b1df8cded Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Sun, 10 Nov 2024 16:47:57 +0100
Subject: [PATCH 34/44] fix(renovate): make Go deps always a "chore"
- add package rules to set semantic commit type for gomod
---
.renovaterc.json | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/.renovaterc.json b/.renovaterc.json
index ff27ef5..aceb001 100644
--- a/.renovaterc.json
+++ b/.renovaterc.json
@@ -2,5 +2,11 @@
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
"extends": [
"local>infrastructure/renovate-config"
+ ],
+ "packageRules": [
+ {
+ "matchManagers": ["gomod"],
+ "semanticCommitType": "chore"
+ }
]
}
From 31179d4af4fbfe0b7a8f0c41460b489224091609 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 18 Nov 2024 08:11:39 +0100
Subject: [PATCH 35/44] break: update terminology from "Work" to "Focus"
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- change mode from "Work" to "Focus" in server messages
- modify pomodoro configuration to use "Focus" instead of "Work"
- adjust default settings to reflect new terminology
- ensure all references to work duration are updated to focus duration
- update variable names in HTML and JavaScript for clarity
🤖
---
README.md | 26 +++++++++++++-------------
cmd/server/main.go | 10 +++++-----
index.html | 8 ++++----
internal/pomodoro/pomodoro.go | 12 ++++++------
internal/shared/configDefaults.go | 2 +-
internal/shared/state.go | 2 +-
internal/websocket/client_commands.go | 2 +-
pkg/models/config.go | 4 ++--
pkg/models/server.go | 2 +-
9 files changed, 34 insertions(+), 34 deletions(-)
diff --git a/README.md b/README.md
index c2d9e51..596cb46 100644
--- a/README.md
+++ b/README.md
@@ -34,17 +34,17 @@ Here are the available commands:
| `pause` | Pauses the current session | `{"command": "pause", "password": ""}` |
| `resume` | Resumes a paused session | `{"command": "resume", "password": ""}` |
| `reset` | Stops and resets the current session | `{"command": "reset", "password": ""}` |
-| `updateSettings` | Update Pomodoro settings | `{"command": "updateSettings", "password": "", "settings": {"work": 600, "shortBreak": 60, "longBreak": 300, "sessions": 2}}` |
+| `updateSettings` | Update Pomodoro settings | `{"command": "updateSettings", "password": "", "settings": {"focus": 600, "shortBreak": 60, "longBreak": 300, "sessions": 2}}` |
#### Update Settings Command (`updateSettings`)
-The `updateSettings` command allows clients to modify the Pomodoro timer configuration, including the length of work sessions, short breaks, long breaks, and the total number of sessions in a cycle. This command must include a valid password to be accepted by the server. The updateSettings command can be used when the timer is stopped.
+The `updateSettings` command allows clients to modify the Pomodoro timer configuration, including the length of focus sessions, short breaks, long breaks, and the total number of sessions in a cycle. This command must include a valid password to be accepted by the server. The updateSettings command can be used when the timer is stopped.
- Fields in the `settings` Object:
- - `work`: Length of the work session (in seconds).
+ - `focus`: Length of the focus session (in seconds).
- `shortBreak`: Length of the short break (in seconds).
- `longBreak`: Length of the long break (in seconds).
- - `sessions`: Total number of work/break sessions in the Pomodoro cycle.
+ - `sessions`: Total number of focus/break sessions in the Pomodoro cycle.
All fields are mandatory and may not be ommitted.
@@ -52,14 +52,14 @@ All fields are mandatory and may not be ommitted.
The server periodically (every second) sends JSON-encoded messages to all connected clients to update them on the current state of the Pomodoro session. These messages contain the following fields:
-- mode: Indicates the current phase of the Pomodoro session ("Work", "ShortBreak", "LongBreak", "End" or "Idle").
+- mode: Indicates the current phase of the Pomodoro session ("Focus", "ShortBreak", "LongBreak", "End" or "Idle").
- "End" is send only once, after all sessions are finished
- settings: Contains the current Pomodoro settings:
- - work: Length of the work session in seconds (e.g., 1500 for 25 minutes).
+ - focus: Length of the focus session in seconds (e.g., 1500 for 25 minutes).
- shortBreak: Length of the short break in seconds (e.g., 300 for 5 minutes).
- longBreak: Length of the long break in seconds (e.g., 900 for 15 minutes).
- - sessions: The total number of work/break sessions (e.g., 4).
-- session: The current session number (e.g., 1 for the first work session).
+ - sessions: The total number of focus/break sessions (e.g., 4).
+- session: The current session number (e.g., 1 for the first focus session).
- time_left: The remaining time for the current mode, in seconds (e.g., 900 for 15 minutes).
- ongoing: Whether a Pomodoro session is currently ongoing.
- paused: Whether the timer is paused.
@@ -67,11 +67,11 @@ The server periodically (every second) sends JSON-encoded messages to all connec
| Message Type | Example |
| --- | --- |
-| Welcome Message | {"mode":"Idle", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":1500, "ongoing":false, "paused":false, "version":"0"} |
-| Session Running | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":1, "time_left":900, "ongoing":true, "paused":false, "version":"0"} |
-| Session Running | {"mode":"ShortBreak", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":50, "ongoing":true, "paused":false, "version":"0"} |
-| Session Paused | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":456, "ongoing":true, "paused":true, "version":"0"} |
-| Session End/Reset | {"mode":"End", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":0, "ongoing":false, "paused":false, "version":"0"} |
+| Welcome Message | {"mode":"Idle", "settings":{"focus":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":1500, "ongoing":false, "paused":false, "version":"0"} |
+| Session Running | {"mode":"Focus", "settings":{"focus":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":1, "time_left":900, "ongoing":true, "paused":false, "version":"0"} |
+| Session Running | {"mode":"ShortBreak", "settings":{"focus":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":50, "ongoing":true, "paused":false, "version":"0"} |
+| Session Paused | {"mode":"Focus", "settings":{"focus":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":456, "ongoing":true, "paused":true, "version":"0"} |
+| Session End/Reset | {"mode":"End", "settings":{"focus":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":0, "ongoing":false, "paused":false, "version":"0"} |
## Testing
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 2024fa2..330afec 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -16,10 +16,10 @@ import (
var (
// define CLI flags
- listenAddress = flag.String("listenAddress", shared.DefaultServerConfig.ListenAddress, "IP address to listen on")
- listenPort = flag.Int("listenPort", shared.DefaultServerConfig.ListenPort, "Port to listen on")
- password = flag.String("password", "", "Control password for pomodoro session (optional)")
- showVersionFlag = flag.Bool("version", false, "Output version")
+ listenAddress = flag.String("listenAddress", shared.DefaultServerConfig.ListenAddress, "IP address to listen on")
+ listenPort = flag.Int("listenPort", shared.DefaultServerConfig.ListenPort, "Port to listen on")
+ password = flag.String("password", "", "Control password for pomodoro session (optional)")
+ showVersion = flag.Bool("version", false, "Output version")
)
// Start the pomodoro server
@@ -27,7 +27,7 @@ func Start() {
flag.Parse()
// show server and protocl version and exit
- if *showVersionFlag {
+ if *showVersion {
fmt.Printf("GoTomato v%s\n", metadata.GoTomatoVersion)
fmt.Printf("Protocol-Version: %s\n", metadata.ProtocolVersion)
os.Exit(0)
diff --git a/index.html b/index.html
index f04bf34..a75e885 100644
--- a/index.html
+++ b/index.html
@@ -40,8 +40,8 @@
-
-
+
+
@@ -98,7 +98,7 @@
document.getElementById("saveButton").addEventListener("click", function () {
// Get the values from the input fields
var password = document.getElementById("password").value;
- var work = parseInt(document.getElementById("workDuration").value);
+ var focus = parseInt(document.getElementById("focusDuration").value);
var shortBreak = parseInt(document.getElementById("shortBreakDuration").value);
var longBreak = parseInt(document.getElementById("longBreakDuration").value);
var sessions = parseInt(document.getElementById("sessions").value);
@@ -108,7 +108,7 @@
command: "updateSettings",
password: password,
settings: {
- work: work,
+ focus: focus,
shortBreak: shortBreak,
longBreak: longBreak,
sessions: sessions
diff --git a/internal/pomodoro/pomodoro.go b/internal/pomodoro/pomodoro.go
index a7bcc00..1dc0e46 100644
--- a/internal/pomodoro/pomodoro.go
+++ b/internal/pomodoro/pomodoro.go
@@ -26,7 +26,7 @@ func waitForTimer(t Timer) bool {
}
}
-// RunPomodoro iterates the Pomodoro work/break sessions
+// RunPomodoro iterates the Pomodoro focus/break sessions
func RunPomodoro() {
mu.Lock()
shared.State.Ongoing = true
@@ -40,9 +40,9 @@ func RunPomodoro() {
shared.State.Session = session
- // Work
- shared.State.Mode = "Work"
- timer.StartAsync(pomodoroConfig.Work)
+ // Focus
+ shared.State.Mode = "Focus"
+ timer.StartAsync(pomodoroConfig.Focus)
if !waitForTimer(timer) {
break
}
@@ -74,7 +74,7 @@ func RunPomodoro() {
shared.State.Mode = "Idle"
shared.State.Session = 0
- shared.State.TimeLeft = shared.State.Settings.Work
+ shared.State.TimeLeft = shared.State.Settings.Focus
}
func ResetPomodoro() {
@@ -111,6 +111,6 @@ func IsPomodoroPaused() bool {
func UpdateSettings(settings models.PomodoroConfig) {
if settings != (models.PomodoroConfig{}) {
shared.State.Settings = settings
- shared.State.TimeLeft = settings.Work
+ shared.State.TimeLeft = settings.Focus
}
}
diff --git a/internal/shared/configDefaults.go b/internal/shared/configDefaults.go
index e125da8..5b668cc 100644
--- a/internal/shared/configDefaults.go
+++ b/internal/shared/configDefaults.go
@@ -10,7 +10,7 @@ var DefaultServerConfig = models.ServerConfig{
// The default pomodoro config if nothing else is set
var DefaultPomodoroConfig = models.PomodoroConfig{
- Work: 25 * 60,
+ Focus: 25 * 60,
ShortBreak: 5 * 60,
LongBreak: 15 * 60,
Sessions: 4,
diff --git a/internal/shared/state.go b/internal/shared/state.go
index e21d4d3..00934f5 100644
--- a/internal/shared/state.go
+++ b/internal/shared/state.go
@@ -10,7 +10,7 @@ var State = models.ServerMessage{
Mode: "Idle",
Settings: DefaultPomodoroConfig,
Session: 0,
- TimeLeft: DefaultPomodoroConfig.Work,
+ TimeLeft: DefaultPomodoroConfig.Focus,
Ongoing: false,
Paused: false,
ProtocolVersion: metadata.ProtocolVersion,
diff --git a/internal/websocket/client_commands.go b/internal/websocket/client_commands.go
index bdb6e7a..7149faa 100644
--- a/internal/websocket/client_commands.go
+++ b/internal/websocket/client_commands.go
@@ -10,7 +10,7 @@ import (
)
func checkSettings(settings models.PomodoroConfig) bool {
- return settings.Work > 0 && settings.ShortBreak > 0 && settings.LongBreak > 0 && settings.Sessions > 0
+ return settings.Focus > 0 && settings.ShortBreak > 0 && settings.LongBreak > 0 && settings.Sessions > 0
}
// Listens for commands from a client and handles them
diff --git a/pkg/models/config.go b/pkg/models/config.go
index 1852165..b1a41ac 100644
--- a/pkg/models/config.go
+++ b/pkg/models/config.go
@@ -4,7 +4,7 @@ import "fmt"
// Represents the configuration of a pomodoro
type PomodoroConfig struct {
- Work int `json:"work"` // Length of work sessions in seconds
+ Focus int `json:"focus"` // Length of focus sessions in seconds
ShortBreak int `json:"shortBreak"` // Length of short break in seconds
LongBreak int `json:"longBreak"` // Length of long break in seconds
Sessions int `json:"sessions"` // Number of total sessions
@@ -12,7 +12,7 @@ type PomodoroConfig struct {
// Stringer interface for the PomodocoConfig model
func (c PomodoroConfig) String() string {
- return fmt.Sprintf("{work: %d, short: %d, long: %d, sessions: %d}", c.Work, c.ShortBreak, c.LongBreak, c.Sessions)
+ return fmt.Sprintf("{focus: %d, short: %d, long: %d, sessions: %d}", c.Focus, c.ShortBreak, c.LongBreak, c.Sessions)
}
// Represents the server configuration
diff --git a/pkg/models/server.go b/pkg/models/server.go
index 6aa914a..f495505 100644
--- a/pkg/models/server.go
+++ b/pkg/models/server.go
@@ -2,7 +2,7 @@ package models
// Represents the data sent to the client via WebSocket
type ServerMessage struct {
- Mode string `json:"mode"` // "Idle", "Work", "ShortBreak", "LongBreak" or "End"
+ Mode string `json:"mode"` // "Idle", "Focus", "ShortBreak", "LongBreak" or "End"
Settings PomodoroConfig `json:"settings"` // The currrent pomodoro settings
Session int `json:"session"` // Current session number
TimeLeft int `json:"time_left"` // Remaining time in seconds
From 256837c1302032516e2d4eed1ca210a7062932bd Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 18 Nov 2024 08:57:32 +0100
Subject: [PATCH 36/44] feat: add client instructions to usage output
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
- add custom usage message
- include instructions for WebSocket client connection
🤖
---
cmd/server/main.go | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 330afec..25fc443 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -24,6 +24,13 @@ var (
// Start the pomodoro server
func Start() {
+ // Update usage output
+ flag.Usage = func() {
+ fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", "GoTomato")
+ flag.PrintDefaults()
+ fmt.Println("\nPoint your client to 'ws://:/ws'")
+ }
+
flag.Parse()
// show server and protocl version and exit
From e8e65c4f3a036c1aaf2d744190fb79ae72db6569 Mon Sep 17 00:00:00 2001
From: Sebastian Mark
Date: Mon, 18 Nov 2024 17:43:49 +0100
Subject: [PATCH 37/44] break: remove `/ws` from websocket path
---
cmd/server/main.go | 4 ++--
index.html | 2 +-
2 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/cmd/server/main.go b/cmd/server/main.go
index 25fc443..d8eb8f6 100644
--- a/cmd/server/main.go
+++ b/cmd/server/main.go
@@ -28,7 +28,7 @@ func Start() {
flag.Usage = func() {
fmt.Fprintf(flag.CommandLine.Output(), "Usage of %s:\n", "GoTomato")
flag.PrintDefaults()
- fmt.Println("\nPoint your client to 'ws://:/ws'")
+ fmt.Println("\nPoint your client to 'ws://:'")
}
flag.Parse()
@@ -52,7 +52,7 @@ func Start() {
// start connection handler and broadcast
r := http.NewServeMux()
- r.HandleFunc("/ws", websocket.HandleConnection)
+ r.HandleFunc("/", websocket.HandleConnection)
go websocket.SendPermanentBroadCastMessage()
helper.Logger.Info("GoTomato started", "version", metadata.GoTomatoVersion)
diff --git a/index.html b/index.html
index a75e885..1de404b 100644
--- a/index.html
+++ b/index.html
@@ -64,7 +64,7 @@