Skip to content

Commit a832d8e

Browse files
committed
feat: add max session time setting and auto-pause functionality for Pomodoro sessions
1 parent 3b356b9 commit a832d8e

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

src/core/pomodoro-timer.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ export class PomodoroTimer {
3030
this.currentSessionElapsedTime = 0; // Actual elapsed time for current session (in seconds)
3131
this.lastCompletedSessionTime = 0; // Time of the last completed session for undo functionality
3232
this.sessionCompletedButNotSaved = false; // Flag to track if session completed but not saved yet
33+
this.maxSessionTime = 120 * 60 * 1000; // Default 2 hours in milliseconds
34+
this.maxSessionTimeReached = false; // Flag to track if max session time was reached
3335

3436
// Timer accuracy tracking (for background throttling fix)
3537
this.timerStartTime = null; // When the timer was started (Date.now())
@@ -667,6 +669,9 @@ export class PomodoroTimer {
667669
}
668670
}
669671

672+
// Check if max session time has been reached
673+
this.checkMaxSessionTime();
674+
670675
this.updateDisplay();
671676

672677
// Warning when less than 2 minutes remaining
@@ -696,6 +701,35 @@ export class PomodoroTimer {
696701
}
697702
}
698703

704+
checkMaxSessionTime() {
705+
// Only check during focus sessions and if a session is active
706+
if (this.currentMode !== 'focus' || !this.sessionStartTime || this.maxSessionTimeReached) {
707+
return;
708+
}
709+
710+
const now = Date.now();
711+
const sessionElapsed = now - this.sessionStartTime;
712+
713+
// Check if session has exceeded max time
714+
if (sessionElapsed >= this.maxSessionTime) {
715+
this.maxSessionTimeReached = true;
716+
this.pauseTimer();
717+
718+
// Show notification
719+
const maxTimeInMinutes = Math.floor(this.maxSessionTime / (60 * 1000));
720+
NotificationUtils.showNotificationPing(
721+
`Session automatically paused after ${maxTimeInMinutes} minutes. Take a break! 🛑`,
722+
'warning'
723+
);
724+
725+
// Show desktop notification if enabled
726+
NotificationUtils.showDesktopNotification(
727+
'Session Time Limit Reached',
728+
`Your session has been automatically paused after ${maxTimeInMinutes} minutes. Consider taking a break!`
729+
);
730+
}
731+
}
732+
699733
pauseTimer() {
700734
if (this.isRunning) {
701735
this.isRunning = false;
@@ -748,6 +782,7 @@ export class PomodoroTimer {
748782
this.sessionStartTime = null;
749783
this.currentSessionElapsedTime = 0;
750784
this.sessionCompletedButNotSaved = false; // Reset flag
785+
this.maxSessionTimeReached = false; // Reset max session time flag
751786

752787
// Reset timer accuracy tracking
753788
this.timerStartTime = null;
@@ -1022,6 +1057,7 @@ export class PomodoroTimer {
10221057
this.sessionStartTime = null;
10231058
this.currentSessionElapsedTime = 0;
10241059
this.sessionCompletedButNotSaved = false; // Reset flag
1060+
this.maxSessionTimeReached = false; // Reset max session time flag
10251061

10261062
// Reset timer accuracy tracking
10271063
this.timerStartTime = null;
@@ -1617,6 +1653,7 @@ export class PomodoroTimer {
16171653
this.currentSessionElapsedTime = 0;
16181654
this.lastCompletedSessionTime = 0;
16191655
this.sessionCompletedButNotSaved = false; // Reset flag
1656+
this.maxSessionTimeReached = false; // Reset max session time flag
16201657

16211658
// Reset timer accuracy tracking
16221659
this.timerStartTime = null;
@@ -2148,6 +2185,9 @@ export class PomodoroTimer {
21482185
}
21492186

21502187
this.totalSessions = settings.timer.total_sessions;
2188+
2189+
// Update max session time (convert from minutes to milliseconds)
2190+
this.maxSessionTime = (settings.timer.max_session_time || 120) * 60 * 1000;
21512191

21522192
// If timer is not running, update current time remaining
21532193
if (!this.isRunning) {
@@ -2231,6 +2271,7 @@ export class PomodoroTimer {
22312271
this.sessionStartTime = null;
22322272
this.currentSessionElapsedTime = 0;
22332273
this.lastCompletedSessionTime = 0;
2274+
this.maxSessionTimeReached = false; // Reset max session time flag
22342275

22352276
// Reset timer accuracy tracking
22362277
this.timerStartTime = null;

src/index.html

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,12 @@ <h3 class="section-header">Timer Durations</h3>
543543
<input type="number" id="total-sessions" min="1" max="20" value="10">
544544
<p class="setting-description">Number of focus sessions to complete each day</p>
545545
</div>
546+
547+
<div class="setting-item">
548+
<label for="max-session-time">Max Session Time (minutes):</label>
549+
<input type="number" id="max-session-time" min="30" max="480" value="120">
550+
<p class="setting-description">Maximum time per session before auto-pause (default: 2 hours)</p>
551+
</div>
546552
</div>
547553
</div>
548554

src/managers/settings-manager.js

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,8 @@ export class SettingsManager {
9999
break_duration: 5,
100100
long_break_duration: 20,
101101
total_sessions: 10,
102-
weekly_goal_minutes: 125
102+
weekly_goal_minutes: 125,
103+
max_session_time: 120 // 2 hours in minutes
103104
},
104105
notifications: {
105106
desktop_notifications: true,
@@ -133,6 +134,12 @@ export class SettingsManager {
133134
document.getElementById('break-duration').value = this.settings.timer.break_duration;
134135
document.getElementById('long-break-duration').value = this.settings.timer.long_break_duration;
135136
document.getElementById('total-sessions').value = this.settings.timer.total_sessions;
137+
138+
// Populate max session time
139+
const maxSessionTimeField = document.getElementById('max-session-time');
140+
if (maxSessionTimeField) {
141+
maxSessionTimeField.value = this.settings.timer.max_session_time || 120;
142+
}
136143

137144
// Populate weekly goal
138145
const weeklyGoalField = document.getElementById('weekly-goal-minutes');
@@ -421,6 +428,12 @@ export class SettingsManager {
421428
this.settings.timer.break_duration = parseInt(document.getElementById('break-duration').value);
422429
this.settings.timer.long_break_duration = parseInt(document.getElementById('long-break-duration').value);
423430
this.settings.timer.total_sessions = parseInt(document.getElementById('total-sessions').value);
431+
432+
// Max session time setting
433+
const maxSessionTimeField = document.getElementById('max-session-time');
434+
if (maxSessionTimeField) {
435+
this.settings.timer.max_session_time = parseInt(maxSessionTimeField.value) || 120;
436+
}
424437

425438
// Appearance settings
426439
const themeSelect = document.getElementById('theme-select');
@@ -527,7 +540,8 @@ export class SettingsManager {
527540
'break-duration',
528541
'long-break-duration',
529542
'total-sessions',
530-
'weekly-goal-minutes'
543+
'weekly-goal-minutes',
544+
'max-session-time'
531545
];
532546

533547
// Appearance settings
@@ -629,6 +643,12 @@ export class SettingsManager {
629643
this.settings.timer.long_break_duration = parseInt(document.getElementById('long-break-duration').value);
630644
this.settings.timer.total_sessions = parseInt(document.getElementById('total-sessions').value);
631645

646+
// Max session time setting
647+
const maxSessionTimeField = document.getElementById('max-session-time');
648+
if (maxSessionTimeField) {
649+
this.settings.timer.max_session_time = parseInt(maxSessionTimeField.value) || 120;
650+
}
651+
632652
// Weekly goal setting
633653
const weeklyGoalField = document.getElementById('weekly-goal-minutes');
634654
if (weeklyGoalField) {

src/utils/theme-loader.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ class ThemeLoader {
3939
// that gets updated by the build process or manually maintained
4040

4141
// This could be enhanced to use a build-time script that generates this list
42-
const knownThemes = [
42+
const knownThemes = [
4343
'espresso.css',
4444
'pipboy.css',
4545
'pommodore64.css'

0 commit comments

Comments
 (0)