Compare commits

..

2 commits

Author SHA1 Message Date
cb6616f400 break: add updateSettings command to modify Pomodoro settings
- add `updateSettings` command to modify Pomodoro configuration
- remove ability to set Pomodoro configuration in `start` command
- update demo client
- update README

🤖
2024-10-22 08:51:22 +02:00
a0dba673a2 break: enhance server message structure and settings
- add explicit server messages for start and end
- include pomodoro setttings in server messages
- update README

🤖
2024-10-22 08:10:26 +02:00
7 changed files with 109 additions and 86 deletions

View file

@ -28,50 +28,48 @@ If the client sends a command with an incorrect password it will not be allowed
Here are the available commands:
| Command | Action | Example Sent by Client |
|----------|-------------------------------------|-----------------------------------|
| `start` | Starts a new Pomodoro session | `{"command": "start", "password": ""}` |
| `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": ""}` |
| Command | Action | Example Sent by Client |
| ---------- | ------------------------------------- | ----------------------------------- |
| `start` | Starts a new Pomodoro session | `{"command": "start", "password": ""}` |
| `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}}` |
#### Optional Start Parameters
#### Update Settings Command (`updateSettings`)
The Start-Command may contain an optional Pomodoro-Config, which allows you to customize the length of the work session, short break, long break, and the number of sessions. If no configuration is provided, the server will use default values.
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.
Example:
```json
{
command: "start",
password: "foobar",
config: {
"work": 10, // Length of the work session in seconds
"shortBreak": 5, // Length of the short break in seconds
"longBreak": 10, // Length of the long break in seconds
"sessions": 2 // Number of total sessions
}
}
```
- Fields in the `settings` Object:
- `work`: Length of the work 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.
All fields are mandatory and may not be ommitted.
### Server Messages
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:
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", or empty if no session is running).
- mode: Indicates the current phase of the Pomodoro session ("Work", "ShortBreak", "LongBreak", "End" or "Idle").
- settings: Contains the current Pomodoro settings:
- work: Length of the work 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).
- total_sessions: The total number of sessions for the current Pomodoro cycle (e.g., 4 if the cycle consists of 4 work/break sessions).
- time_left: The remaining time for the current mode, in seconds (e.g., 900 for 15 minutes).
- ongoing: Wether a pomodoro is currently ongoing
- paused: Wether the timer is paused
- ongoing: Whether a Pomodoro session is currently ongoing.
- paused: Whether the timer is paused.
| Message Type | Example |
| --------------------- | --------------------------------------------------- |
| Welcome Message | `{"mode": "", "session":0, "total_sessions":0, "time_left":0, "ongoing": false, "paused": false}` |
| Session Running | `{"mode": "Work", "session": 1, "total_sessions": 4, "time_left": 900, "ongoing": true, "paused": false}` |
| Session Running | `{"mode": "ShortBreak", "session": 2, "total_sessions": 4, "time_left": 50, "ongoing": true, "paused": false}` |
| Session Paused | `{"mode": "Work", "session": 2, "total_sessions": 4, "time_left": 456, "ongoing": true, "paused": true}` |
| Session End/Reset | `{"mode": "", "session": 0, "total_sessions": 0, "time_left": 0, "ongoing": false, "paused": false}` |
| 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} |
| Session Running | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":1, "time_left":900, "ongoing":true, "paused":false} |
| Session Running | {"mode":"ShortBreak", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":50, "ongoing":true, "paused":false} |
| Session Paused | {"mode":"Work", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":2, "time_left":456, "ongoing":true, "paused":true} |
| Session End/Reset | {"mode":"End", "settings":{"work":1500, "shortBreak":300, "longBreak":900, "sessions":4}, "session":0, "time_left":0, "ongoing":false, "paused":false} |
## Testing

View file

@ -20,6 +20,13 @@
input {
width: 75px;
}
.settings {
border: 2px solid black;
background: #e7e7e7;
padding: 10px;
display: inline-block;
}
</style>
</head>
@ -27,23 +34,27 @@
<h1>Pomodoro Timer</h1>
<!-- Input fields for custom Pomodoro config and control password -->
<p>
<label for="password">Control Password:</label>
<input type="text" id="password" placeholder="Password" />
</p>
<p>
<label for="workDuration">Work Duration (seconds):</label>
<input type="number" id="workDuration" placeholder="Work time in seconds" value="900" />
<br />
<label for="shortBreakDuration">Short Break Duration (seconds):</label>
<input type="number" id="shortBreakDuration" placeholder="Short break in seconds" value="300" />
<br />
<label for="longBreakDuration">Long Break Duration (seconds):</label>
<input type="number" id="longBreakDuration" placeholder="Long break in seconds" value="600" />
<br />
<label for="sessions">Number of Sessions:</label>
<input type="number" id="sessions" placeholder="Number of sessions" value="4" />
</p>
<div class="settings">
<p>
<label for="password">Control Password:</label>
<input type="text" id="password" placeholder="Password" />
</p>
<p>
<label for="workDuration">Work Duration (seconds):</label>
<input type="number" id="workDuration" placeholder="Work time in seconds" value="900" />
<br />
<label for="shortBreakDuration">Short Break Duration (seconds):</label>
<input type="number" id="shortBreakDuration" placeholder="Short break in seconds" value="300" />
<br />
<label for="longBreakDuration">Long Break Duration (seconds):</label>
<input type="number" id="longBreakDuration" placeholder="Long break in seconds" value="600" />
<br />
<label for="sessions">Number of Sessions:</label>
<input type="number" id="sessions" placeholder="Number of sessions" value="4" />
<br />
<button id="saveButton">Save Settings</button>
</p>
</div>
<div id="timer">Connting to server...</div>
@ -65,7 +76,7 @@
var data = JSON.parse(event.data);
var mode = data.mode;
var session = data.session;
var totalSession = data.total_sessions;
var totalSession = data.settings.sessions;
var timeLeft = data.time_left;
document.getElementById("timer").innerText =
@ -83,8 +94,8 @@
return minutes.toString().padStart(2, '0') + ":" + remainingSeconds.toString().padStart(2, '0');
}
// Start Button Click Event
document.getElementById("startButton").addEventListener("click", function () {
// saveButton Click Event
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);
@ -94,15 +105,22 @@
// Send the start command with the custom config and password
ws.send(JSON.stringify({
command: "start",
command: "updateSettings",
password: password,
config: {
settings: {
work: work,
shortBreak: shortBreak,
longBreak: longBreak,
sessions: sessions
}
}));
});
// Start Button Click Event
document.getElementById("startButton").addEventListener("click", function () {
var password = document.getElementById("password").value;
// Send the start command with the custom config and password
ws.send(JSON.stringify({command: "start", password: password}));
// Hide start button and show pause/resume and reset buttons
document.getElementById("startButton").style.display = "none";

View file

@ -2,7 +2,7 @@ package pomodoro
import (
"git.smsvc.net/pomodoro/GoTomato/internal/shared"
"git.smsvc.net/pomodoro/GoTomato/pkg/models"
// "git.smsvc.net/pomodoro/GoTomato/pkg/models"
"sync"
)
@ -13,34 +13,38 @@ var pomodoroResumeChannel = make(chan bool, 1)
var mu sync.Mutex // to synchronize access to shared state
// RunPomodoro iterates the Pomodoro work/break sessions.
func RunPomodoro(config models.GoTomatoPomodoroConfig) {
func RunPomodoro() {
mu.Lock()
shared.Message.Ongoing = true
shared.Message.Paused = false
mu.Unlock()
shared.Message.TotalSession = config.Sessions
pomodoroConfig := shared.Message.PomodoroSettings
for session := 1; session <= config.Sessions; session++ {
for session := 1; session <= pomodoroConfig.Sessions; session++ {
shared.Message.Session = session
shared.Message.Mode = "Work"
if !startTimer(config.Work) {
if !startTimer(pomodoroConfig.Work) {
break
}
if session == config.Sessions {
if session == pomodoroConfig.Sessions {
shared.Message.Mode = "LongBreak"
if !startTimer(config.LongBreak) {
if !startTimer(pomodoroConfig.LongBreak) {
break
}
} else {
shared.Message.Mode = "ShortBreak"
if !startTimer(config.ShortBreak) {
if !startTimer(pomodoroConfig.ShortBreak) {
break
}
}
shared.Message.Mode = "End"
}
shared.Message = shared.ResetToDefault()
mu.Lock()
shared.Message.Ongoing = false
shared.Message.Paused = false
mu.Unlock()
}
// ResetPomodoro resets the running Pomodoro timer.

View file

@ -8,12 +8,12 @@ var Message = ResetToDefault()
func ResetToDefault() models.ServerMessage {
return models.ServerMessage{
Mode: "",
Session: 0,
TotalSession: 0,
TimeLeft: 0,
Ongoing: false,
Paused: false,
Mode: "Idle",
PomodoroSettings: DefaultPomodoroConfig,
Session: 0,
TimeLeft: DefaultPomodoroConfig.Work,
Ongoing: false,
Paused: false,
}
}

View file

@ -9,8 +9,6 @@ import (
"log"
)
var pomodoroConfig = shared.DefaultPomodoroConfig
// handleClientCommands listens for commands from WebSocket clients
func handleClientCommands(ws *websocket.Conn) {
for {
@ -35,10 +33,7 @@ func handleClientCommands(ws *websocket.Conn) {
switch clientCommand.Command {
case "start":
if !pomodoro.IsPomodoroOngoing() {
if clientCommand.Config != shared.UnsetPomodoroConfig {
pomodoroConfig = clientCommand.Config
}
go pomodoro.RunPomodoro(pomodoroConfig) // Start the timer with the list of clients
go pomodoro.RunPomodoro() // Start the timer with the list of clients
}
case "stop":
if pomodoro.IsPomodoroOngoing() {
@ -52,6 +47,14 @@ func handleClientCommands(ws *websocket.Conn) {
if pomodoro.IsPomodoroOngoing() && pomodoro.IsPomodoroPaused() {
pomodoro.ResumePomodoro() // Resume the timer
}
case "updateSettings":
if !pomodoro.IsPomodoroOngoing() {
if clientCommand.PomodoroSettings != shared.UnsetPomodoroConfig {
shared.Message.PomodoroSettings = clientCommand.PomodoroSettings
shared.Message.TimeLeft = clientCommand.PomodoroSettings.Work
}
}
}
}

View file

@ -8,9 +8,9 @@ import (
// ClientCommand 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
Config GoTomatoPomodoroConfig `json:"config"` // pomodoro config
Command string `json:"command"` // comman send to the server
Password string `json:"password"` // pomodoro control password
PomodoroSettings GoTomatoPomodoroConfig `json:"settings"` // pomodoro config
}
type Client struct {

View file

@ -2,10 +2,10 @@ package models
// ServerMessage represents the data sent to the client via WebSocket.
type ServerMessage struct {
Mode string `json:"mode"` // "Work", "ShortBreak", or "LongBreak"
Session int `json:"session"` // Current session number
TotalSession int `json:"total_sessions"` // Total number of sessions
TimeLeft int `json:"time_left"` // Remaining time in seconds
Ongoing bool `json:"ongoing"` // Ongoing pomodoro
Paused bool `json:"paused"` // Is timer paused
Mode string `json:"mode"` // "Idle", "Work", "ShortBreak", "LongBreak" or "End"
PomodoroSettings GoTomatoPomodoroConfig `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
Paused bool `json:"paused"` // Is timer paused
}