-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: optimize timer behavior in background tabs
- Implement different timer strategies for foreground/background states - Use setInterval for smooth updates in foreground (1000ms) - Switch to setTimeout for one-time update in background - Add visibility change detection to handle tab state changes - Immediately update timer display when switching between states - Clean up timers properly when stopping or switching states This change improves timer accuracy and reduces resource usage when the tab is in background.
- Loading branch information
Showing
2 changed files
with
108 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,104 @@ | ||
let targetEndTime = null; | ||
let timerInterval = null; | ||
let updateInterval = null; | ||
let backgroundTimeout = null; | ||
let isInBackground = false; | ||
|
||
self.onmessage = function(event) { | ||
const { command, time } = event.data; | ||
// 處理前景更新 | ||
function handleForegroundUpdate() { | ||
if (updateInterval) { | ||
clearInterval(updateInterval); | ||
} | ||
|
||
if (command === 'start') { | ||
// 清除現有計時器 | ||
if (timerInterval) { | ||
clearInterval(timerInterval); | ||
} | ||
|
||
// 只記錄目標結束時間 | ||
targetEndTime = Date.now() + time; | ||
|
||
// 使用 1 秒的更新頻率 | ||
timerInterval = setInterval(() => { | ||
const now = Date.now(); | ||
const remainingTime = Math.max(0, targetEndTime - now); | ||
updateInterval = setInterval(() => { | ||
sendTimeUpdate(); | ||
}, 1000); | ||
} | ||
|
||
if (remainingTime > 0) { | ||
self.postMessage({ | ||
command: 'tick', | ||
remainingTime: remainingTime | ||
}); | ||
// 處理背景更新 | ||
function handleBackgroundUpdate() { | ||
// 清除前景的 interval | ||
if (updateInterval) { | ||
clearInterval(updateInterval); | ||
updateInterval = null; | ||
} | ||
|
||
const now = Date.now(); | ||
const remainingTime = targetEndTime - now; | ||
|
||
if (remainingTime > 0) { | ||
// 設置一次性 timeout 到結束時間 | ||
backgroundTimeout = setTimeout(() => { | ||
sendTimeUpdate(); | ||
self.postMessage({ command: 'end' }); | ||
}, remainingTime); | ||
} | ||
} | ||
|
||
// 發送時間更新 | ||
function sendTimeUpdate() { | ||
if (!targetEndTime) return; | ||
|
||
const now = Date.now(); | ||
const remainingTime = Math.max(0, targetEndTime - now); | ||
|
||
if (remainingTime > 0) { | ||
self.postMessage({ | ||
command: 'tick', | ||
remainingTime: remainingTime | ||
}); | ||
} else { | ||
// 清理所有計時器 | ||
cleanup(); | ||
self.postMessage({ command: 'end' }); | ||
} | ||
} | ||
|
||
// 清理函數 | ||
function cleanup() { | ||
if (updateInterval) { | ||
clearInterval(updateInterval); | ||
updateInterval = null; | ||
} | ||
if (backgroundTimeout) { | ||
clearTimeout(backgroundTimeout); | ||
backgroundTimeout = null; | ||
} | ||
} | ||
|
||
self.onmessage = function(event) { | ||
const { command, time, isBackground } = event.data; | ||
|
||
switch (command) { | ||
case 'start': | ||
cleanup(); | ||
targetEndTime = Date.now() + time; | ||
isInBackground = isBackground; | ||
|
||
if (isBackground) { | ||
handleBackgroundUpdate(); | ||
} else { | ||
clearInterval(timerInterval); | ||
timerInterval = null; | ||
self.postMessage({ command: 'end' }); | ||
handleForegroundUpdate(); | ||
} | ||
// 立即發送第一次更新 | ||
sendTimeUpdate(); | ||
break; | ||
|
||
case 'stop': | ||
cleanup(); | ||
targetEndTime = null; | ||
break; | ||
|
||
case 'visibility-change': | ||
isInBackground = isBackground; | ||
if (targetEndTime) { | ||
if (isBackground) { | ||
handleBackgroundUpdate(); | ||
} else { | ||
handleForegroundUpdate(); | ||
} | ||
// 切換時立即更新一次 | ||
sendTimeUpdate(); | ||
} | ||
}, 1000); | ||
|
||
} else if (command === 'stop') { | ||
if (timerInterval) { | ||
clearInterval(timerInterval); | ||
timerInterval = null; | ||
} | ||
targetEndTime = null; | ||
break; | ||
} | ||
}; |