feat: implement permanent broadcast message functionality
- add SendPermanentBroadCastMessage to continuously send updates
- refactor BroadcastMessage to use a shared Message struct
- update pomodoro logic to modify broadcast.Message directly
- adjust client command handling to use broadcast.Clients map
- enhance ServerMessage struct with "Ongoing" and "Paused" fields
🤖
This commit is contained in:
parent
eba4065c6f
commit
9615d4d449
8 changed files with 75 additions and 65 deletions
|
@ -5,23 +5,37 @@ import (
|
|||
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
|
||||
"github.com/gorilla/websocket"
|
||||
"log"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BroadcastMessage sends a message to all connected WebSocket clients.
|
||||
func BroadcastMessage(clients map[*websocket.Conn]*models.Client, message models.ServerMessage) {
|
||||
// Marshal the message into JSON format
|
||||
jsonMessage, err := json.Marshal(message)
|
||||
if err != nil {
|
||||
log.Printf("Error marshalling message: %v", err)
|
||||
return
|
||||
}
|
||||
// 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 Message = models.ServerMessage{
|
||||
Mode: "none",
|
||||
Session: 0,
|
||||
TotalSession: 0,
|
||||
TimeLeft: 0,
|
||||
Ongoing: false,
|
||||
Paused: false,
|
||||
}
|
||||
|
||||
// Iterate over all connected clients and broadcast the message
|
||||
for _, client := range clients {
|
||||
err := client.SendMessage(websocket.TextMessage, jsonMessage)
|
||||
// BroadcastMessage sends a message to all connected WebSocket clients.
|
||||
func SendPermanentBroadCastMessage() {
|
||||
for {
|
||||
// Marshal the message into JSON format
|
||||
jsonMessage, err := json.Marshal(Message)
|
||||
if err != nil {
|
||||
log.Printf("Error broadcasting to client: %v", err)
|
||||
// The client is responsible for closing itself on error
|
||||
log.Printf("Error marshalling message: %v", 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.Printf("Error broadcasting to client: %v", err)
|
||||
// The client is responsible for closing itself on error
|
||||
}
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,6 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
var pomodoroOngoing bool
|
||||
var pomodoroPaused bool
|
||||
|
||||
var pomodoroResetChannel = make(chan bool, 1)
|
||||
var pomodoroPauseChannel = make(chan bool, 1)
|
||||
var pomodoroResumeChannel = make(chan bool, 1)
|
||||
|
@ -19,52 +16,53 @@ var mu sync.Mutex // to synchronize access to shared state
|
|||
// RunPomodoro iterates the Pomodoro work/break sessions.
|
||||
func RunPomodoro(clients map[*websocket.Conn]*models.Client, config models.GoTomatoPomodoroConfig) {
|
||||
mu.Lock()
|
||||
pomodoroOngoing = true
|
||||
pomodoroPaused = false
|
||||
broadcast.Message.Ongoing = true
|
||||
broadcast.Message.Paused = false
|
||||
mu.Unlock()
|
||||
|
||||
broadcast.Message.TotalSession = config.Sessions
|
||||
|
||||
for session := 1; session <= config.Sessions; session++ {
|
||||
if !startTimer(clients, config.Work, "Work", session, config.Sessions) {
|
||||
broadcast.Message.Session = session
|
||||
if !startTimer(clients, config.Work, "Work") {
|
||||
break
|
||||
}
|
||||
if session == config.Sessions {
|
||||
if !startTimer(clients, config.LongBreak, "LongBreak", session, config.Sessions) {
|
||||
if !startTimer(clients, config.LongBreak, "LongBreak") {
|
||||
break
|
||||
}
|
||||
} else {
|
||||
if !startTimer(clients, config.ShortBreak, "ShortBreak", session, config.Sessions) {
|
||||
if !startTimer(clients, config.ShortBreak, "ShortBreak") {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mu.Lock()
|
||||
pomodoroOngoing = false
|
||||
broadcast.Message.Ongoing = false
|
||||
mu.Unlock()
|
||||
}
|
||||
|
||||
// ResetPomodoro resets the running Pomodoro timer.
|
||||
func ResetPomodoro(clients map[*websocket.Conn]*models.Client) {
|
||||
mu.Lock()
|
||||
pomodoroOngoing = false // Reset the running state
|
||||
pomodoroPaused = false // Reset the paused state
|
||||
mu.Unlock()
|
||||
|
||||
// Broadcast the reset message to all clients
|
||||
broadcast.BroadcastMessage(clients, models.ServerMessage{
|
||||
Mode: "none",
|
||||
Session: 0,
|
||||
TotalSession: 0,
|
||||
TimeLeft: 0,
|
||||
})
|
||||
|
||||
// Send a reset signal to stop any running timers
|
||||
pomodoroResetChannel <- true
|
||||
|
||||
mu.Lock()
|
||||
broadcast.Message.Ongoing = false
|
||||
broadcast.Message.Paused = false
|
||||
mu.Unlock()
|
||||
|
||||
// Reset message
|
||||
broadcast.Message.Mode = "none"
|
||||
broadcast.Message.Session = 0
|
||||
broadcast.Message.TotalSession = 0
|
||||
broadcast.Message.TimeLeft = 0
|
||||
}
|
||||
|
||||
func PausePomodoro() {
|
||||
mu.Lock()
|
||||
pomodoroPaused = true
|
||||
broadcast.Message.Paused = true
|
||||
mu.Unlock()
|
||||
|
||||
pomodoroPauseChannel <- true
|
||||
|
@ -72,7 +70,7 @@ func PausePomodoro() {
|
|||
|
||||
func ResumePomodoro() {
|
||||
mu.Lock()
|
||||
pomodoroPaused = false
|
||||
broadcast.Message.Paused = false
|
||||
mu.Unlock()
|
||||
pomodoroResumeChannel <- true
|
||||
}
|
||||
|
@ -80,11 +78,11 @@ func ResumePomodoro() {
|
|||
func IsPomodoroOngoing() bool {
|
||||
mu.Lock()
|
||||
defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
|
||||
return pomodoroOngoing
|
||||
return broadcast.Message.Ongoing
|
||||
}
|
||||
|
||||
func IsPomodoroPaused() bool {
|
||||
mu.Lock()
|
||||
defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
|
||||
return pomodoroPaused
|
||||
return broadcast.Message.Paused
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
)
|
||||
|
||||
// startTimer runs the countdown and broadcasts every second.
|
||||
func startTimer(clients map[*websocket.Conn]*models.Client, remainingSeconds int, mode string, session int, totalSessions int) bool {
|
||||
func startTimer(clients map[*websocket.Conn]*models.Client, remainingSeconds int, mode string) bool {
|
||||
for remainingSeconds > 0 {
|
||||
select {
|
||||
case <-pomodoroResetChannel:
|
||||
|
@ -20,12 +20,8 @@ func startTimer(clients map[*websocket.Conn]*models.Client, remainingSeconds int
|
|||
default:
|
||||
// Broadcast the current state to all clients
|
||||
if !IsPomodoroPaused() {
|
||||
broadcast.BroadcastMessage(clients, models.ServerMessage{
|
||||
Mode: mode,
|
||||
Session: session,
|
||||
TotalSession: totalSessions,
|
||||
TimeLeft: remainingSeconds,
|
||||
})
|
||||
broadcast.Message.Mode = mode
|
||||
broadcast.Message.TimeLeft = remainingSeconds
|
||||
time.Sleep(time.Second)
|
||||
remainingSeconds--
|
||||
}
|
||||
|
@ -33,12 +29,7 @@ func startTimer(clients map[*websocket.Conn]*models.Client, remainingSeconds int
|
|||
}
|
||||
|
||||
// Final broadcast when time reaches zero
|
||||
broadcast.BroadcastMessage(clients, models.ServerMessage{
|
||||
Mode: mode,
|
||||
Session: session,
|
||||
TotalSession: totalSessions,
|
||||
TimeLeft: 0,
|
||||
})
|
||||
broadcast.Message.TimeLeft = remainingSeconds
|
||||
|
||||
return true
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package websocket
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"git.smsvc.net/pomodoro/GoTomato/internal/broadcast"
|
||||
"git.smsvc.net/pomodoro/GoTomato/internal/pomodoro"
|
||||
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
|
||||
"github.com/gorilla/websocket"
|
||||
|
@ -24,7 +25,7 @@ func handleClientCommands(ws *websocket.Conn) {
|
|||
_, message, err := ws.ReadMessage()
|
||||
if err != nil {
|
||||
log.Printf("Client disconnected: %v", err)
|
||||
delete(Clients, ws)
|
||||
delete(broadcast.Clients, ws)
|
||||
break
|
||||
}
|
||||
|
||||
|
@ -42,11 +43,11 @@ func handleClientCommands(ws *websocket.Conn) {
|
|||
if clientCommand.Config != unsetPomodoroConfig {
|
||||
pomodoroConfig = clientCommand.Config
|
||||
}
|
||||
go pomodoro.RunPomodoro(Clients, pomodoroConfig) // Start the timer with the list of clients
|
||||
go pomodoro.RunPomodoro(broadcast.Clients, pomodoroConfig) // Start the timer with the list of clients
|
||||
}
|
||||
case "stop":
|
||||
if pomodoro.IsPomodoroOngoing() {
|
||||
pomodoro.ResetPomodoro(Clients) // Reset Pomodoro
|
||||
pomodoro.ResetPomodoro(broadcast.Clients) // Reset Pomodoro
|
||||
}
|
||||
case "pause":
|
||||
if pomodoro.IsPomodoroOngoing() && !pomodoro.IsPomodoroPaused() {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package websocket
|
||||
|
||||
import (
|
||||
"git.smsvc.net/pomodoro/GoTomato/internal/broadcast"
|
||||
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
|
||||
"github.com/gorilla/websocket"
|
||||
"log"
|
||||
|
@ -8,8 +9,6 @@ import (
|
|||
"sync"
|
||||
)
|
||||
|
||||
// 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 mu sync.Mutex // Mutex to protect access to the Clients map
|
||||
|
||||
// Upgrader to upgrade HTTP requests to WebSocket connections
|
||||
|
@ -29,7 +28,7 @@ func HandleConnections(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// Register the new client
|
||||
mu.Lock()
|
||||
Clients[ws] = &models.Client{
|
||||
broadcast.Clients[ws] = &models.Client{
|
||||
Conn: ws, // Store the WebSocket connection
|
||||
}
|
||||
mu.Unlock()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue