feat: add pause and resume functionality
- implement pause and resume commands in the Pomodoro package
- modify timer logic to handle paused state
- adjust client command handling for pause and resume actions
- update HTML to include pause/resume button
🤖
This commit is contained in:
parent
c9501c3bbb
commit
bc3a306c00
4 changed files with 94 additions and 22 deletions
39
index.html
39
index.html
|
@ -23,12 +23,14 @@
|
||||||
<h1>Pomodoro Timer</h1>
|
<h1>Pomodoro Timer</h1>
|
||||||
<div id="timer">Connecting to server...</div>
|
<div id="timer">Connecting to server...</div>
|
||||||
|
|
||||||
<!-- Buttons to start and stop the timer -->
|
<!-- Buttons to start, pause/resume, and stop the timer -->
|
||||||
<button id="startButton">Start</button>
|
<button id="startButton">Start</button>
|
||||||
<button id="stopButton">Stop</button>
|
<button id="pauseResumeButton" style="display: none;">Pause</button>
|
||||||
|
<button id="stopButton" style="display: none;">Stop</button>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
var ws = new WebSocket("ws://localhost:8080/ws");
|
var ws = new WebSocket("ws://localhost:8080/ws");
|
||||||
|
var isPaused = false; // Track if the timer is paused
|
||||||
|
|
||||||
ws.onopen = function () {
|
ws.onopen = function () {
|
||||||
document.getElementById("timer").innerText = "Connected to server.";
|
document.getElementById("timer").innerText = "Connected to server.";
|
||||||
|
@ -57,14 +59,43 @@
|
||||||
return minutes.toString().padStart(2, '0') + ":" + remainingSeconds.toString().padStart(2, '0');
|
return minutes.toString().padStart(2, '0') + ":" + remainingSeconds.toString().padStart(2, '0');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Send start command to the server
|
// Start Button Click Event
|
||||||
document.getElementById("startButton").addEventListener("click", function () {
|
document.getElementById("startButton").addEventListener("click", function () {
|
||||||
ws.send(JSON.stringify({command: "start"}));
|
ws.send(JSON.stringify({command: "start"}));
|
||||||
|
|
||||||
|
// Hide start button and show pause/resume and stop buttons
|
||||||
|
document.getElementById("startButton").style.display = "none";
|
||||||
|
document.getElementById("pauseResumeButton").style.display = "inline-block";
|
||||||
|
document.getElementById("stopButton").style.display = "inline-block";
|
||||||
|
|
||||||
|
// Set the pause/resume button to show "Pause" initially
|
||||||
|
isPaused = false;
|
||||||
|
document.getElementById("pauseResumeButton").innerText = "Pause";
|
||||||
});
|
});
|
||||||
|
|
||||||
// Send stop command to the server
|
// Pause/Resume Button Click Event
|
||||||
|
document.getElementById("pauseResumeButton").addEventListener("click", function () {
|
||||||
|
if (isPaused) {
|
||||||
|
// If paused, send resume command and update button text
|
||||||
|
ws.send(JSON.stringify({command: "resume"}));
|
||||||
|
document.getElementById("pauseResumeButton").innerText = "Pause";
|
||||||
|
isPaused = false;
|
||||||
|
} else {
|
||||||
|
// If running, send pause command and update button text
|
||||||
|
ws.send(JSON.stringify({command: "pause"}));
|
||||||
|
document.getElementById("pauseResumeButton").innerText = "Resume";
|
||||||
|
isPaused = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Stop Button Click Event
|
||||||
document.getElementById("stopButton").addEventListener("click", function () {
|
document.getElementById("stopButton").addEventListener("click", function () {
|
||||||
ws.send(JSON.stringify({command: "stop"}));
|
ws.send(JSON.stringify({command: "stop"}));
|
||||||
|
|
||||||
|
// Reset buttons after stopping
|
||||||
|
document.getElementById("startButton").style.display = "inline-block";
|
||||||
|
document.getElementById("pauseResumeButton").style.display = "none";
|
||||||
|
document.getElementById("stopButton").style.display = "none";
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|
|
@ -13,12 +13,20 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
var pomodoroRunning bool
|
var pomodoroRunning bool
|
||||||
|
var pomodoroPaused bool
|
||||||
|
|
||||||
|
var pomodoroStopChannel = make(chan bool, 1)
|
||||||
|
var pomodoroPauseChannel = make(chan bool, 1)
|
||||||
|
var pomodoroResumeChannel = make(chan bool, 1)
|
||||||
|
|
||||||
var mu sync.Mutex // to synchronize access to shared state
|
var mu sync.Mutex // to synchronize access to shared state
|
||||||
|
|
||||||
// RunPomodoroTimer iterates the Pomodoro work/break sessions.
|
// RunPomodoroTimer iterates the Pomodoro work/break sessions.
|
||||||
func RunPomodoroTimer(clients map[*websocket.Conn]bool) {
|
func RunPomodoroTimer(clients map[*websocket.Conn]bool) {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
pomodoroRunning = true
|
pomodoroRunning = true
|
||||||
|
pomodoroPaused = false
|
||||||
|
mu.Unlock()
|
||||||
|
|
||||||
for session := 1; session <= sessions; session++ {
|
for session := 1; session <= sessions; session++ {
|
||||||
if !startTimer(clients, workDuration, "Work", session) {
|
if !startTimer(clients, workDuration, "Work", session) {
|
||||||
|
@ -35,11 +43,32 @@ func RunPomodoroTimer(clients map[*websocket.Conn]bool) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mu.Lock()
|
||||||
pomodoroRunning = false
|
pomodoroRunning = false
|
||||||
mu.Unlock()
|
mu.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsPomodoroRunning returns the status of the timer.
|
// StopPomodoro sends a signal to stop the running Pomodoro timer.
|
||||||
|
func StopPomodoro() {
|
||||||
|
pomodoroStopChannel <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func PausePomodoro() {
|
||||||
|
pomodoroPauseChannel <- true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResumePomodoro() {
|
||||||
|
pomodoroResumeChannel <- true
|
||||||
|
}
|
||||||
|
|
||||||
func IsPomodoroRunning() bool {
|
func IsPomodoroRunning() bool {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
|
||||||
return pomodoroRunning
|
return pomodoroRunning
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsPomodoroPaused() bool {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock() // Ensures that the mutex is unlocked after the function is done
|
||||||
|
return pomodoroPaused
|
||||||
|
}
|
||||||
|
|
|
@ -7,16 +7,23 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var timerStopChannel = make(chan bool, 1)
|
|
||||||
|
|
||||||
// startTimer runs the countdown and broadcasts every second.
|
// startTimer runs the countdown and broadcasts every second.
|
||||||
func startTimer(clients map[*websocket.Conn]bool, remainingSeconds int, mode string, session int) bool {
|
func startTimer(clients map[*websocket.Conn]bool, remainingSeconds int, mode string, session int) bool {
|
||||||
for remainingSeconds > 0 {
|
for remainingSeconds > 0 {
|
||||||
select {
|
select {
|
||||||
case <-timerStopChannel:
|
case <-pomodoroStopChannel:
|
||||||
return false // Stop the timer if a stop command is received
|
return false // Stop the timer if a stop command is received
|
||||||
|
case <-pomodoroPauseChannel:
|
||||||
|
mu.Lock()
|
||||||
|
pomodoroPaused = true
|
||||||
|
mu.Unlock()
|
||||||
|
case <-pomodoroResumeChannel:
|
||||||
|
mu.Lock()
|
||||||
|
pomodoroPaused = false
|
||||||
|
mu.Unlock()
|
||||||
default:
|
default:
|
||||||
// Broadcast the current state to all clients
|
// Broadcast the current state to all clients
|
||||||
|
if !pomodoroPaused {
|
||||||
broadcast.BroadcastMessage(clients, models.BroadcastMessage{
|
broadcast.BroadcastMessage(clients, models.BroadcastMessage{
|
||||||
Mode: mode,
|
Mode: mode,
|
||||||
Session: session,
|
Session: session,
|
||||||
|
@ -27,6 +34,7 @@ func startTimer(clients map[*websocket.Conn]bool, remainingSeconds int, mode str
|
||||||
remainingSeconds--
|
remainingSeconds--
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Final broadcast when time reaches zero
|
// Final broadcast when time reaches zero
|
||||||
broadcast.BroadcastMessage(clients, models.BroadcastMessage{
|
broadcast.BroadcastMessage(clients, models.BroadcastMessage{
|
||||||
|
@ -38,8 +46,3 @@ func startTimer(clients map[*websocket.Conn]bool, remainingSeconds int, mode str
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// StopTimer sends a signal to stop the running Pomodoro timer.
|
|
||||||
func StopTimer() {
|
|
||||||
timerStopChannel <- true
|
|
||||||
}
|
|
||||||
|
|
|
@ -34,8 +34,17 @@ func handleClientCommands(ws *websocket.Conn) {
|
||||||
}
|
}
|
||||||
case "stop":
|
case "stop":
|
||||||
if pomodoro.IsPomodoroRunning() {
|
if pomodoro.IsPomodoroRunning() {
|
||||||
pomodoro.StopTimer() // Stop the timer in the Pomodoro package
|
pomodoro.StopPomodoro() // Stop the timer in the Pomodoro package
|
||||||
|
}
|
||||||
|
case "pause":
|
||||||
|
if pomodoro.IsPomodoroRunning() && !pomodoro.IsPomodoroPaused() {
|
||||||
|
pomodoro.PausePomodoro() // Pause the timer
|
||||||
|
}
|
||||||
|
case "resume":
|
||||||
|
if pomodoro.IsPomodoroRunning() && pomodoro.IsPomodoroPaused() {
|
||||||
|
pomodoro.ResumePomodoro() // Resume the timer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue