generated from zroei/pastiow-pomodoro-timer
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathscript.js
More file actions
271 lines (235 loc) · 9.97 KB
/
script.js
File metadata and controls
271 lines (235 loc) · 9.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
document.addEventListener('DOMContentLoaded', function() {
// DOM Elements
const minutesDisplay = document.getElementById('minutes');
const secondsDisplay = document.getElementById('seconds');
const startBtn = document.getElementById('start-btn');
const pauseBtn = document.getElementById('pause-btn');
const resetBtn = document.getElementById('reset-btn');
const modeBtns = document.querySelectorAll('.mode-btn');
const themeBtns = document.querySelectorAll('.theme-btn');
const settingsBtn = document.getElementById('settings-btn');
const settingsModal = document.getElementById('settings-modal');
const closeBtn = settingsModal.querySelector('.close-btn'); // More specific selector
const saveSettingsBtn = document.getElementById('save-settings');
const alarmSound = document.getElementById('alarm-sound');
const timerDisplay = document.querySelector('.timer-display'); // For pulsating effect
// Timer variables
let timer;
let totalSeconds; // Will be set based on currentMode and settings
let remainingSeconds;
let isRunning = false;
let currentMode = 'pomodoro'; // Default mode
// Timer settings (default values)
let settings = {
pomodoro: 25,
shortBreak: 5,
longBreak: 10
};
// Load settings from localStorage if available
if (localStorage.getItem('pomodoroSettings')) {
settings = JSON.parse(localStorage.getItem('pomodoroSettings'));
}
// Load saved theme
const savedTheme = localStorage.getItem('selectedTheme');
if (savedTheme) {
document.body.setAttribute('data-theme', savedTheme);
// Ensure the correct theme button is highlighted if needed, but not critical for functionality
} else {
// Set a default theme if none is saved
document.body.setAttribute('data-theme', 'nature');
}
// Initialize timer with default or saved mode
switchMode(currentMode, false); // Initialize without resetting settings just yet
updateDisplay();
initFavicon(); // Initialize favicon
// Event Listeners
startBtn.addEventListener('click', startTimer);
pauseBtn.addEventListener('click', pauseTimer);
resetBtn.addEventListener('click', resetTimer);
modeBtns.forEach(btn => {
btn.addEventListener('click', () => switchMode(btn.dataset.mode));
});
themeBtns.forEach(btn => {
btn.addEventListener('click', () => switchTheme(btn.dataset.theme));
});
settingsBtn.addEventListener('click', openSettings);
closeBtn.addEventListener('click', closeSettings);
saveSettingsBtn.addEventListener('click', saveSettings);
// Close modal when clicking outside
window.addEventListener('click', (event) => {
if (event.target === settingsModal) {
closeSettings();
}
});
// Request notification permission on page load
if (Notification.permission !== 'granted' && Notification.permission !== 'denied') {
Notification.requestPermission();
}
// --- Timer functions ---
function startTimer() {
if (!isRunning) {
isRunning = true;
timer = setInterval(updateTimer, 1000);
startBtn.disabled = true;
pauseBtn.disabled = false;
timerDisplay.classList.add('pulsate'); // Add pulsating effect
}
}
function pauseTimer() {
clearInterval(timer);
isRunning = false;
startBtn.disabled = false;
pauseBtn.disabled = true;
timerDisplay.classList.remove('pulsate'); // Remove pulsating effect
}
function resetTimer() {
pauseTimer();
switch (currentMode) {
case 'pomodoro':
totalSeconds = settings.pomodoro * 60;
break;
case 'short-break':
totalSeconds = settings.shortBreak * 60;
break;
case 'long-break':
totalSeconds = settings.longBreak * 60;
break;
}
remainingSeconds = totalSeconds;
updateDisplay();
updateFavicon(Math.floor(remainingSeconds / 60), remainingSeconds % 60);
}
function updateTimer() {
if (remainingSeconds > 0) {
remainingSeconds--;
updateDisplay();
updateFavicon(Math.floor(remainingSeconds / 60), remainingSeconds % 60);
} else {
timerComplete();
}
}
function updateDisplay() {
const minutes = Math.floor(remainingSeconds / 60);
const seconds = remainingSeconds % 60;
minutesDisplay.textContent = minutes.toString().padStart(2, '0');
secondsDisplay.textContent = seconds.toString().padStart(2, '0');
}
function timerComplete() {
pauseTimer();
alarmSound.play();
// Notify user
if (Notification.permission === 'granted') {
new Notification('Timer Completed!', {
body: `Your ${currentMode.replace('-', ' ')} timer has finished!`,
icon: 'assets/images/icon.png' // Ensure you have an icon in this path
});
} else if (Notification.permission !== 'denied') {
Notification.requestPermission().then(permission => {
if (permission === 'granted') {
new Notification('Timer Completed!', {
body: `Your ${currentMode.replace('-', ' ')} timer has finished!`,
icon: 'assets/images/icon.png'
});
}
});
}
// Auto-switch mode
if (currentMode === 'pomodoro') {
// Basic auto-switch to short break
setTimeout(() => {
switchMode('short-break');
// You might want to auto-start the next timer here, or let the user decide
// startTimer();
}, 1000);
} else {
// After a break, switch back to pomodoro
setTimeout(() => {
switchMode('pomodoro');
// startTimer();
}, 1000);
}
}
function switchMode(mode, resetCurrentSettings = true) {
currentMode = mode;
// Update active button
modeBtns.forEach(btn => {
btn.classList.remove('active');
if (btn.dataset.mode === mode) {
btn.classList.add('active');
}
});
// Set timer based on mode
if (resetCurrentSettings) {
resetTimer(); // Resets timer and updates totalSeconds based on new mode
} else {
// Initial load, just set totalSeconds
switch (mode) {
case 'pomodoro':
totalSeconds = settings.pomodoro * 60;
break;
case 'short-break':
totalSeconds = settings.shortBreak * 60;
break;
case 'long-break':
totalSeconds = settings.longBreak * 60;
break;
}
remainingSeconds = totalSeconds; // Ensure remainingSeconds is also set
}
updateDisplay();
updateFavicon(Math.floor(totalSeconds / 60), 0); // Update favicon on mode switch
}
function switchTheme(theme) {
document.body.setAttribute('data-theme', theme);
localStorage.setItem('selectedTheme', theme);
}
// --- Settings functions ---
function openSettings() {
document.getElementById('pomodoro-time').value = settings.pomodoro;
document.getElementById('short-break-time').value = settings.shortBreak;
document.getElementById('long-break-time').value = settings.longBreak;
settingsModal.style.display = 'flex'; // Use flex for centering
}
function closeSettings() {
settingsModal.style.display = 'none';
}
function saveSettings() {
settings.pomodoro = parseInt(document.getElementById('pomodoro-time').value);
settings.shortBreak = parseInt(document.getElementById('short-break-time').value);
settings.longBreak = parseInt(document.getElementById('long-break-time').value);
localStorage.setItem('pomodoroSettings', JSON.stringify(settings));
// Update current timer if settings changed for current mode
// This will ensure the timer reflects new settings immediately
resetTimer();
closeSettings();
}
// --- Favicon related functions ---
function initFavicon() {
if (!document.getElementById('dynamic-favicon')) {
const link = document.createElement('link');
link.id = 'dynamic-favicon';
link.rel = 'icon';
link.type = 'image/svg+xml';
document.head.appendChild(link);
}
// Initialize with current timer state
updateFavicon(Math.floor(remainingSeconds / 60), remainingSeconds % 60);
}
function updateFavicon(minutes, seconds) {
const isBreak = currentMode !== 'pomodoro';
// Get color from the current theme's primary color, or a default if not found
const themePrimaryColor = getComputedStyle(document.body).getPropertyValue('--primary-color');
const color = isBreak ? '#4CAF50' : themePrimaryColor; // Green for break, theme's primary for pomodoro
// Ensure seconds are always two digits
const formattedSeconds = seconds.toString().padStart(2, '0');
const svg = `
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100">
<rect width="100" height="100" fill="${color}"/>
<text x="50%" y="68%" font-family="Poppins, sans-serif" font-size="50" text-anchor="middle" dominant-baseline="middle" fill="white">
${minutes}:${formattedSeconds}
</text>
</svg>
`;
document.getElementById('dynamic-favicon').href = `data:image/svg+xml,${encodeURIComponent(svg)}`;
}
});