Fixing the Focus Timer Pause/Resume Bug
After pausing and resuming, the timer showed 10 minutes remaining instead of 20. Pause time was being counted as elapsed time.
Start a 25-minute focus timer. Wait 5 minutes (20 remaining). Pause for 10 minutes. Resume. The timer shows 10 minutes remaining instead of 20. The pause time was being counted as elapsed.
The Bug
public function getCurrentElapsedSeconds(): int
{
$elapsed = $this->elapsed_seconds ?? 0;
if ($this->status === 'running' && $this->paused_at === null) {
// BUG: calculates from original start, ignoring accumulated pause time
$elapsed = abs(now()->diffInSeconds($this->started_at));
}
return max(0, (int) $elapsed);
}
After resume, paused_at is null (cleared on resume), so it calculates now - started_at -- the total wall-clock time since the original start, including all pause durations.
The Fix
Added a resumed_at timestamp. On resume, it resets the reference point:
public function start(): void
{
if ($this->status === 'paused') {
$this->paused_at = null;
$this->resumed_at = now(); // New reference point
} else {
$this->started_at = now();
$this->resumed_at = now();
$this->elapsed_seconds = 0;
}
$this->status = 'running';
$this->save();
}
public function getCurrentElapsedSeconds(): int
{
$elapsed = $this->elapsed_seconds ?? 0; // Accumulated from previous cycles
if ($this->status === 'running' && $this->resumed_at) {
$elapsed += (int) abs(now()->diffInSeconds($this->resumed_at));
}
return max(0, (int) $elapsed);
}
The formula is now: total elapsed = accumulated (saved on pause) + time since last resume. Each pause accumulates elapsed time; each resume resets the reference point. Multiple pause/resume cycles work correctly because the accumulator carries forward.
The bug only manifested in the pause/resume path -- normal usage without pausing calculated now - started_at correctly, which is why it went undetected.
Built while working on PlanPal.
Back to danielships ->